python面向物件(2)
阿新 • • 發佈:2022-04-07
python面向物件(2)
動態方法和靜態方法
# 動態方法 1.繫結給物件的方法 class Student: def run(self): print(self) # 類呼叫繫結給物件的方法:有幾個引數就需要傳幾個引數 Student.run(123) # 物件呼叫繫結給物件的方法:會自動將物件當做第一個引數傳入 obj1.run() 2.繫結給類的方法 class Student: @classmethod def eat(cls): pr(cls) # 類呼叫繫結給類的方法:會自動將類當做第一個引數傳入 print(Student) # <class '__main__.Student'> Student.eat() # <class '__main__.Student'> # 物件呼叫繫結給類的方法:也不需要傳參 會講產生該物件的類自動當做第一個引數傳入 obj1.eat() # <class '__main__.Student'> '''在類定義中,使用@classmethod裝飾器修飾的方法,必須至少有一個引數,且第一個引數留給了cls,cls指代呼叫者即類物件自身 cls這個識別符號可以是任意合法名稱,但是為了易讀,請不要修改 通過cls可以直接操作類的屬性''' # 動態方法 class Student: @staticmethod def speak(cls): print(cls) 1.普普通通的函式:無論誰來調 都必須傳固定的引數個數 # 類呼叫靜態方法:要自己傳值 Student.speak(123) # 物件呼叫靜態方法:要自己傳值 obj1.speak(321)
面向物件的三大特性之一:繼承
# 繼承的概念:
子類 擁有 父類 的所有 方法 和 屬性
# 繼承的基本使用
"""
class A(B):
pass
我們將被繼承的類稱為:父類或者基類 B
繼承別人的類稱為:子類或者派生類 A
"""
# 在python中一個類可以同時繼承多個父類
class A(B,C,D):
pass
子類 繼承自父類,可以直接享受 父類中已經封裝好的方法,不需要再次開發
子類 中應該根據 職責,封裝 子類特有的屬性和方法
繼承的本質
抽象:由下往上抽取相同特徵 繼承:由上往下直接白嫖資源 """ 在面向物件程式設計中 其實類和父類的主要功能都是用來減少程式碼冗餘的 物件:資料與功能的結合體 類:多個物件相同資料和功能的結合體 父類:多個類相同資料和功能的結合體 """ class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def teach(self): print(f'{self.name}老師正在講課') class Student(Person): def study(self): print(f'{self.name}學生正在學習') stu1 = Student('jason', 18, 'male') #總結 class Studen(Person)這種形式就是從父類繼承,括號中寫上繼承的類的列表。 繼承可以讓子類從父類獲取特徵(屬性和方法) 父類: calss Person就是Student和Teacher的父類,也稱為基類,超類 子類: Student就是Person的子類,也成為派生類 #在Python3中,object類是所有物件的根基類 class A: pass '如果類定義時,沒有基類列表,等同於繼承自object' class A(object): pass
新式類和經典類
#新式類:
以 object 為基類的類,推薦使用
#經典類:
不以 object 為基類的類,不推薦使用
Python 3.x
定義類時,如果沒有指定父類,會 預設使用 object 作為該類的 基類 —— Python 3.x 中定義的類都是 新式類
Python 2.x
定義類時,如果沒有指定父類,則不會以 object 作為 基類
'''為了保證編寫的程式碼能夠同時在 Python 2.x 和 Python 3.x 執行!
今後在定義類時為了相容,如果沒有父類,建議統一繼承自 object '''
檢視繼承的特殊屬性和方法
class A: pass print(A.__base__) #類的基類。 print(A.__bases__) #類的基類元組。 print(A.__mro__) #顯示方法查詢順序,基類的元組。 print(A.mro()) #同上,返回列表。 print(A.__subclasses__()) #類的子類列表。
繼承的優缺點
#繼承的特點:
a.子類的獨享可以直接訪問父類中未被私有化的屬性,訪問私有化屬性時,需要在父類提供get和set方法
b.子類物件可以呼叫父類中未被私有化的方法
c.父類物件無法訪問子類物件的屬性和方法
#優缺點:
1.優點:
可以簡化程式碼,減少冗餘
可以提高程式碼的維護性
可以提高程式碼的安全性
繼承是多型的前提
2.缺點:
耦合和內聚被用來描述類與類之間的關係,一般高內聚低耦合說明程式碼比較好
繼承關係中耦合性相對較高【如果修改父類,則所有子類需求都會改變】
名字的查詢順序
不繼承情況下
# 名字的查詢順序是
先從物件自己的名稱空間中查詢 沒有則去類裡面的名稱空間查詢
物件 >>> 類
'''注意設定值的情況下是在自身的名稱空間中新增或者修改資料'''
單繼承情況下
#名字的查詢順序是
先從物件自己的名稱空間中查詢 沒有擇取產生物件的類中查詢
如果還沒有並且類有父類則去父類中查詢 以此往復下去!!!
物件 >>> 類 >>> 父類
# 程式碼示例:
class A:
def f1(self):
print('from A.f1')
def f2(self):
print('from A.f2')
self.f1() '''以後看到self點東西 一定要問自己self是誰'''
class MyClass(A):
def f1(self):
print('from MyClass.f1')
obj = MyClass()
obj.f2()
# 執行的方法分別是A裡面的f2和MyClass裡面的f1
#查詢順序
1.物件.屬性 : 先從物件空間找,再從類名空間找,再從父類找
2.類名.屬性 : 先從類名空間找,再從父類找
3.物件與物件之間是相互獨立的
多繼承情況下(瞭解)
'研究菱形和非菱形問題object不參與圖形構建'
#非菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從左往右依次查詢
如果多個父類還有分類 那麼遵循"深度優先"
eg:D->C->B->A
#菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從左往右依次查詢
如果多個父類還有分類 那麼遵循"廣度優先"
D->B->C->A
派生類
# 派生的定義:
子類可以新增自己新的屬性或者在自己這裡重新定義這些屬性(不會影響到父類)
重新定義了自己的屬性且與父類重名那麼呼叫新增的屬性時 就以自己為準
#程式碼示例:
class Animal():
def __init__(self,name,age,gender,birth):
self.name = name
self.age = age
self.gender = gender
self.birth = birth
class Cat(Animal):
def __init__(self,name,age,gender,birth,eat,live):
# 子類呼叫父類的方法
super().__init__(name,age,gender,birth)
# 自己還要新增一個額外的東西
self.eat = eat
self.live = live
class Dog(Animal):
def __init__(self,name,age,gender,birth,play,sleep):
super().__init__(name,age,gender,birth)
self.play = play
self.sleep = sleep
"""
如果自己寫的子類需要使用父類的方法 並且還需要基於該方法做擴充套件
這樣的子類我們稱之為派生類(本質還是子類)
那麼可以使用super關鍵字來實現
"""