#5 Python面向物件(四)
前言
本節將是Python面向物件的最後一篇博文了,這節將記錄類的特殊方法、特殊成員方法、舊類和新類的不同,以及一些其他知識。Go!
一、類的特殊方法
Python有三種特殊方法:例項方法、靜態方法、類方法。如果你讀過一些原始碼,你一定疑惑過這些程式碼:@staticmethod、@classmethod ,前面見到的所有方法都是例項方法,例項方法的第一個引數為例項本身(self),由於例項方法經過前面幾節已經掌握,所有本節將會熟悉剩下的兩種特殊方法
1.1 靜態方法
之前在類中編寫的各種方法其實都是屬於例項方法,每一個方法的第一個引數是例項本身(self),例項方法固然好用,但是在開發中,需要一些這樣的方法:與類有關,在使用時不需要引用類和例項,也就是不能訪問類變數和例項變數。 這些方法通常用來作全域性的配置方法,使程式碼更加簡潔和安全。
1.1.1 建立靜態方法
在類中的方法的前面使用裝飾器: @staticmethod 即可,靜態方法已經和普通函式沒有太大區別,唯一的區別就是靜態方法要通過物件來訪問,看例:
1 class Teacher: 2def __init__(self, name, gender): 3self.name = name 4self.gender = gender 5 6def talk(self): 7print('I am {}'.format(self.name)) 8 9@staticmethod# 建立 is_man 靜態方法 10def is_man(gender): 11if gender == 'male': 12return 1 13return 0
通過上例可以看到靜態方法的建立比較簡單,基本上已經和類無關了,按照普通的函式建立即可
1.1.2 呼叫靜態方法
靜態方法與函式的區別就是呼叫方式不同,函式直接呼叫即可,但是靜態方法多多少少和類還是有一些關係的,那就是呼叫時需要物件來呼叫:
zhangsan = Teacher('zhangsan', 'male') print(zhangsan.is_man('male')) # 執行結果: 1
注意:靜態方法無法呼叫類變數和例項變數,這裡就不作演示了。
『防抄襲:讀者請忽略這段文字,文章作者是部落格園的MinuteSheep』
但是靜態方法通常並不會在類外呼叫靜態方法,而是直接在類內作為全域性配置方法使用,例如:
1 class Teacher: 2def __init__(self, name, gender): 3self.name = name 4self.gender = gender 5 6def talk(self): 7print('I am {}'.format(self.name)) 8 9@staticmethod 10def is_man(gender): 11if gender == 'male': 12return 1 13return 0 14 15def eat(self): 16flag = self.is_man(self.gender)# 作為全域性配置使用 17if flag: 18print('I am man, I will eat 2 buns') 19else: 20print('I am woman, I will eat 1 bun') 21 22 23 zhangsan = Teacher('zhangsan', 'male') 24 25 zhangsan.eat()
# 執行結果: I am man, I will eat 2 buns
1.1.3 繼承靜態方法
如果超類中有靜態方法時,子類繼承時會發生什麼呢?
class Teacher(object): def __init__(self, name, gender): self.name = name self.gender = gender @staticmethod def is_man(gender): if gender == 'male': return 1 return 0 def eat(self): flag = self.is_man(self.gender)# 作為全域性配置使用 if flag: print('I am {}, I will eat 2 buns'.format(flag)) else: print('I am {}, I will eat 1 bun'.formar(flag)) class Chinese(Teacher): ''' 建立一個語文老師類, 繼承Teacher ''' def __init__(self, name, gender): super().__init__(name, gender) @staticmethod# 改寫超類的靜態方法 def is_man(gender): if gender == 'male': return 'man' return 'woman' zhangsan = Chinese('zhangsan', 'male') zhangsan.eat()
繼承後將超類靜態方法改寫,執行結果j將按照子類的靜態方法執行,結果如下:
# 執行結果: I am man, I will eat 2 buns # 而不是按照超類的靜態方法 # I am 1,I will eat 2 buns
1.2 類方法
類方法,顧名思義是一種直接作用於類的方法。類方法和例項方法的區別就在於:類方法只能訪問類變數,不能訪問例項變數。
1.2.1 建立類方法
在類中的方法前面使用裝飾器: @classmethod 即可,類方法和例項方法格式相似,類方法第一個引數必須是類本身(cls),看例:
class Teacher(object): food = 'bun' def __init__(self, name, gender): self.name = name self.gender = gender @classmethod# 建立類方法 eat def eat(cls): print(cls.food)
通過上面程式碼可以看到,類方法的第一個引數為類本身,習慣上用cls表示,當然也可以用其他單詞表示(這一點與self類似)
1.2.2 呼叫類方法
類方法的呼叫與例項方法無異,看例:
zhangsan = Teacher('zhangsan', 'male') zhangsan.eat() # 執行結果: bun
注意:類方法只能呼叫類變數,不能呼叫例項變數,這裡就不作演示了
『防抄襲:讀者請忽略這段文字,文章作者是部落格園的MinuteSheep』
類方法經常出現在原始碼中,通常用來為類傳入新的引數。
二、類的特殊成員方法
什麼事特殊成員方法呢?其實你已經見過了,那就是類似__init__這樣 __方法__ 形式的方法
2.1 常用的特殊成員方法
__init__「建構函式,當例項化類物件時,會自動呼叫該方法」
class Test: def __init__(self): print('例項化類物件後就會執行我') Test() # 執行結果: 例項化類物件後就會執行我
__del__「解構函式,當類物件在記憶體中被釋放時(也就是類物件執行完後),會自動呼叫該方法」
class Test: def __del__(self): print('類物件釋放後就會執行我') Test() # 執行結果: 類物件釋放後就會執行我
__call__「call方法,在類或者物件後加括號執行該方法」
class Test: def __call__(self): print('我是部落格園MinuteSheep,神馬文庫抄襲我的博文,不要臉') Test()() # 或者 # obj = Test() # obj() # 執行結果: 我是部落格園MinuteSheep,神馬文庫抄襲我的博文,不要臉
__dict__「dict方法,檢視類或者物件的所有成員資訊」
class Test: x = 1000 y = 'MS' print(Test.__dict__) # 執行結果: {'__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Test' objects>, 'x': 1000, '__doc__': None, 'y': 'MS', '__dict__': <attribute '__dict__' of 'Test' objects>}
__doc__「doc方法,檢視類的描述資訊」
class Test: ''' 這裡是類的描述資訊 ''' x = 1000 y = 'MS' print(Test.__doc__) # 執行結果: 這裡是類的描述資訊
三、舊類與新類
Python3中,只有新類,舊類以及被移除, class 類名: 和 class 類名(object): 都是新類;Python2中, class 類名: 是舊類, class 類名(object): 是新類
對舊類和新類瞭解一下即可
3.1 舊類與新類的區別
舊類:深度優先
新類:廣度優先
1 # 在Python2中 2 3 4 class A: 5pass 6 7 8 class B(A): 9pass 10 11 12 class C(B): 13pass 14 15 16 class D(A, B, C): 17pass 18 19 20 D()
在Python2中,上述程式碼的呼叫順序為:D->A->B->A->C->B->A
明顯是深度優先
1 # 在Python2中 2 3 4 class A(object): 5pass 6 7 8 class B(A): 9pass 10 11 12 class C(B): 13pass 14 15 16 class D(A, B, C): 17pass 18 19 20 D()
在Python2中,上訴程式碼的呼叫順序為:D->A->B->C->A->B->A->object
明顯是廣度優先
四、其他知識
4.1 私有成員和私有方法
接觸類這麼久了,你一定發現了又的方法和成員沒有下劃線,有的方法和成員只有一條下劃線,有的方法和成員首尾各有兩條下劃線,這到底是什麼含義呢?
-
無下劃線foo :表示普通方法和成員
-
一條下劃線_foo :表示被保護方法和成員,不能被 from xxx import _foo 匯入
-
兩條下劃線__foo :表示私有方法和成員,只執行類本身進行訪問
-
首尾各兩條下劃線__foo__ :表示特殊方法,一般由系統自定義
結語
Python面向物件的知識到此結束,多加理解和聯絡才能真正掌握面向物件的知識,拜拜~