深入理解Python的元類(lèi)
什么是元類(lèi)
Python中,一切皆對(duì)象,我們定義的數(shù)字、字符串、函數(shù)、列表等都是對(duì)象,對(duì)象是類(lèi)(class)的是實(shí)例,而類(lèi)(class)其實(shí)也是對(duì)象,是type的實(shí)例。這個(gè)type就是Python中的元類(lèi)(metaclass
)。所謂元類(lèi)就是用于創(chuàng)建所有類(lèi)型的類(lèi),Python中的所有新式類(lèi)以及Python3中的所有類(lèi)都是type元類(lèi)的實(shí)例。我們看下面這個(gè)例子:
print(type(0)) # <class 'int'> print(type(int)) # <class 'type'> print(type("tigeriaf")) # <class 'str'> print(type(str)) # <class 'type'> print(type([1, 2, 3])) # <class 'list'> print(type(list)) # <class 'type'> class User: pass u = User() print(type(u)) # <class '__main__.User'> print(type(User)) # <class 'type'> print(type(type)) # <class 'type'>
type元類(lèi)動(dòng)態(tài)創(chuàng)建類(lèi)
之前我們定義類(lèi)要使用class關(guān)鍵字進(jìn)行創(chuàng)建,除了這樣我們還可以使用type動(dòng)態(tài)的去創(chuàng)建類(lèi)。
用法如下:
type(name, bases, dict)
,接收三個(gè)參數(shù)
- 第一個(gè)參數(shù)name是指要?jiǎng)?chuàng)建類(lèi)的名稱(chēng)
- 第二個(gè)參數(shù)bases是指需要繼承父類(lèi)的元組
- 第三個(gè)參數(shù)dict是類(lèi)的屬性
例如:
class User: def __init__(self): self.name = 'tigeriaf' print(User) user = User() print(user.name)
class User: def __init__(self): self.name = 'tigeriaf' print(User) user = User() print(user.name)
以上兩種方式都可以創(chuàng)建類(lèi),輸出結(jié)果也是一樣的,可見(jiàn)使用type動(dòng)態(tài)的去創(chuàng)建類(lèi)也是非常方便的。
自定義元類(lèi)
通過(guò)上面的例子我們知道可以使用type(name, bases, dict)
來(lái)創(chuàng)建類(lèi),如果當(dāng)使用type元類(lèi)無(wú)法滿足我們的一些需求時(shí),我們可以自定義一個(gè)元類(lèi)并使用該元類(lèi)去創(chuàng)建類(lèi)嗎?答案是可以的,下面我們來(lái)看一下:
class MyMetaClass(type): def __init__(cls, name, bases, dict): super().__init__(name, bases, dict) cls.int_attrs = {} for k, v in dict.items(): if type(v) is int: cls.int_attrs[k] = v User = MyMetaClass('User', (), {'name': 'tigeriaf', "age": 24, "level": 2, "introduction": "Python全菜工程師"}) print(User) # <class '__main__.User'> user = User() print(user.name) # tigeriaf print(user.int_attrs) # {'age': 24, 'level': 2}
也可以使用下面這種方法,去創(chuàng)建繼承元類(lèi)的類(lèi)。
class User(metaclass=MyMetaClass): pass
注意:在Python2中使用元類(lèi)需要在要?jiǎng)?chuàng)建的類(lèi)內(nèi)對(duì)__metaclass__進(jìn)行賦值,值為元類(lèi)。
上述代碼定義一個(gè)類(lèi)MyMetaClass,繼承自type類(lèi),因?yàn)閠ype是元類(lèi),所以MyMetaClass也是一個(gè)元類(lèi),在__init__通過(guò)super().__init__(name, bases, dict)
調(diào)用了父類(lèi)type的__init__()方法,在實(shí)現(xiàn)自定義元類(lèi)的基礎(chǔ)上,還在創(chuàng)建類(lèi)的時(shí)候把屬性循環(huán)了一遍,然后值為int類(lèi)型的屬性單獨(dú)存了起來(lái)。這樣我們就實(shí)現(xiàn)了比type元類(lèi)更定制化的元類(lèi)了,我們可以隨意在元類(lèi)內(nèi)添加我們想要的功能。
總結(jié)
總體下來(lái),發(fā)現(xiàn)元類(lèi)及其使用有些難以理解且看不出有什么特別的地方能讓我們?nèi)ナ褂茫冒桑_實(shí)如此,通常情況下確實(shí)可能用不到它,其實(shí)元類(lèi)主要就是在類(lèi)和實(shí)例創(chuàng)建的時(shí)候發(fā)揮作用,來(lái)實(shí)現(xiàn)一些功能,如果確實(shí)不清楚什么時(shí)候該去使用的話,那我們就不需要它,當(dāng)真正需要它的時(shí)候,我們可能就會(huì)發(fā)現(xiàn)它的強(qiáng)大之處。
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python 通過(guò)監(jiān)聽(tīng)端口實(shí)現(xiàn)唯一腳本運(yùn)行方式
這篇文章主要介紹了Python 通過(guò)監(jiān)聽(tīng)端口實(shí)現(xiàn)唯一腳本運(yùn)行方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05Paddle模型性能分析工具Profiler定位瓶頸點(diǎn)優(yōu)化程序詳解
這篇文章主要為大家介紹了Paddle模型性能分析工具Profiler定位瓶頸點(diǎn)優(yōu)化程序詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Python面向?qū)ο蟮娜筇匦苑庋b、繼承、多態(tài)
這篇文章介紹了Python面向?qū)ο蟮娜筇匦苑庋b、繼承、多態(tài),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Django debug為T(mén)rue時(shí),css加載失敗的解決方案
這篇文章主要介紹了Django debug為T(mén)rue時(shí),css加載失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04django配置DJANGO_SETTINGS_MODULE的實(shí)現(xiàn)
本文主要介紹了django配置DJANGO_SETTINGS_MODULE,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Python實(shí)現(xiàn)MySql數(shù)據(jù)庫(kù)交互的示例
本文主要介紹了Python實(shí)現(xiàn)MySql數(shù)據(jù)庫(kù)交互的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Python基于HOG+SVM/RF/DT等模型實(shí)現(xiàn)目標(biāo)人行檢測(cè)功能
這篇文章主要介紹了Python基于HOG+SVM/RF/DT等模型實(shí)現(xiàn)目標(biāo)檢測(cè)[行人檢測(cè)],今天這里并不是說(shuō)要做出怎樣的效果,而是基于HOG+SVM來(lái)實(shí)踐機(jī)器學(xué)習(xí)檢測(cè)的流程,需要的朋友可以參考下2022-06-06使用matplotlib畫(huà)圖之坐標(biāo)軸不等距
這篇文章主要介紹了使用matplotlib畫(huà)圖之坐標(biāo)軸不等距方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02詳解Python排序算法的實(shí)現(xiàn)(冒泡,選擇,插入,快速)
這篇文章主要為大家介紹了Python中常見(jiàn)的四種排序算法的實(shí)現(xiàn):冒泡排序、選擇排序、插入排序和快速排序,文中通過(guò)圖片詳細(xì)講解了它們實(shí)現(xiàn)的原理與代碼,需要的可以參考一下2022-04-04mvc框架打造筆記之wsgi協(xié)議的優(yōu)缺點(diǎn)以及接口實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于mvc框架打造筆記之wsgi協(xié)議的優(yōu)缺點(diǎn)以及接口實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08