前言
在學習 python 過程中想必大家都會去看源碼,看源碼的過程中會看到一些元類,但是看起來感覺很吃力看不懂,那是因為我們對元類不夠了解。
今天我們就來聊一聊 python 元類,看看元類到底是何方神聖。
必要知識儲備
● 在講元類之前我們得先搞清楚類和對象的概念以及類的創建過程,這個至關重要,這取決於我們是否能真正理解和正確使用元類。
● 類和對象概念
1、類:用來描述具有相同的屬性和方法的對象的集合(抽象)
2、對象:類的實體就是對象(具體)傳統方式創建類
傳統方式創建類
1、代碼演示
class Demo:
def __init__(self,name):
self.name = name
print("初始化self.name = ",self.name)
if __name__ == '__main__'
print("Demo類是由誰創建的:",type(Demo))
print("Demo類的父類:",Demo.__bases__)
cl = Demo("老王")
print("cl實例是由誰創建的:",type(cl))
2、輸出:
Demo類是由誰創建的:<class 'type'>
Demo類的父類:(<class 'object'>,)
初始化self.name = 老王
cl實例是由誰創建的:<class '__main__.Demo'>
3、結論:
a、類(Demo)是由type創建的
b、對象(cl)是由類(Demo)創建的
c、基於類(Demo)創建對象(cl),先執行父類(object)的__new__()方法,返回對象(cl)
type 創建類
1、通過上面的例子我們知道,類是由type創建的,那麼我們能不能直接通過type來創建類
2、type語法
type("類名",(繼承哪個類,),{"屬性名稱":"屬性值","方法名稱key":"方法名稱"})
3、代碼演示
demo = type("Demo",(object,),{"name":"老王"})
print("類名稱:",demo.__name__)
print("Demo類是由誰創建的:",type(demo))
cl = demo()
print("cl實例是由誰創建的:",type(cl))
4、輸出:
類名稱:Demo
Demo類是由誰創建的:<class 'type'>
cl實例是由誰創建的:<class '__main__.Demo'>
5、結論
a、類(Demo)是由type創建的
b、對象(cl)是由類(Demo)創建的
c、直接用type創建類和傳統方式創建類,效果一模一樣
元類
● 概念
1、什麼是元類:用來創建其他類的類叫元類
2、思考一個問題,我們能不能基於自己定義的類來創建其他的類?
自定義元類並創建類
1、代碼演示
class Demo1(type):
def __init__(self,*args, **kwargs):
super().__init__(*args, **kwargs)
class Demo2(metaclass=Demo1):
def __init__(self,name,age):
self.name = name
self.age = age
print("Demo2類的實例屬性:name={}".format(self.name))
print("Demo2類的實例屬性:age={}".format(self.age))
if __name__ == '__main__':
print("Demo2是由誰創建的:",type(Demo2))
cl = Demo2("老王","20")
2、輸出:
Demo2是由誰創建的:<class '__main__.Demo1'>
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
3、結論
a、類(Demo2)是由Demo1創建的
b、可以通過自定義類來創建其他類
元類經典應用
1、通過元類實現單例模式
2、單例模式:在程序執行過程中一個類只實例化一次
3、原理:干預類實例化的過程,如果已經實例化了就不再進行實例化
class Demo1(type):
def __init__(self,name,bases, attrs):
super().__init__(name,bases, attrs)
self._instance = None
def __call__(self, *args, **kwargs):
#判斷是否創建了對象,未創建就調用__new__()方法創建對象,已創建了就不調用__new__()方法,直接返回已創建好的對象
if self._instance is None:
self._instance = self.__new__(self,*args, **kwargs)
#調用自己類(Demo2)的實例化方法
self.__init__(self._instance,*args, **kwargs)
return self._instance
class Demo2(metaclass=Demo1):
def __init__(self,name,age):
self.name = name
self.age = age
print("Demo2類的實例屬性:name={}".format(self.name))
print("Demo2類的實例屬性:age={}".format(self.age))
if __name__ == '__main__':
print("Demo2是由誰創建的:",type(Demo2))
cl1 = Demo2("老王",20)
cl2 = Demo2("老王",20)
print("cl1實例的內存地址:",id(cl1))
print("cl2實例的內存地址:",id(cl1))
print("cl1 是否是 cl2",cl1 is cl2)
4、輸出:
Demo2是由誰創建的:<class '__main__.Demo1'>
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
Demo2類的實例屬性:name=老王
Demo2類的實例屬性:age=20
cl1實例的內存地址:1842280993096
cl2實例的內存地址:1842280993096
cl1 是否是 cl2 True
最後感謝每一個認真閱讀我文章的人,看著粉絲一路的上漲和關注,禮尚往來總是要有的,雖然不是什麼很值錢的東西,如果你用得到的話可以直接拿走!
房子要一層一層蓋,知識要一點一點學。大家在學習過程中要好基礎,多上手實操,話不多說,這裡狠狠上一次干貨!我熬夜整理好的各階段(功能、接口、自動化、性能、測開)技能學習資料+實操講解,非常適合私下裡學習,比找資料自學高效多了,分享給你們。
領取關 w/x/g/z/h:軟件測試小dao
敲字不易,如果此文章對你有幫助的話,點個贊收個藏來個關注,給作者一個鼓勵。也方便你下次能夠快速查找。