?python中的元類metaclass詳情
動機(jī)
python語言因為工作偏向于 AI ,所以對于這門語言還停留在表面,對于 python 深層并沒有接觸到。
今天來聊一聊元類(metaclass) ,想必大多數(shù)人都或多或少聽過元編程這個詞,但是對于元編程是什么以及如何應(yīng)用元編程熟悉應(yīng)該不多,在 python 中的 metaclass 就是幫助 developer 實現(xiàn)元編程,因此產(chǎn)生一個想法
最近時間還算寬裕,所以想要文章認(rèn)真弄一弄
從一個問題引出 MetaClass
在 python 語言中,并沒有函數(shù)重載,我們下面通過一個具體例子來說明。
class A():
def f(self, x:int):
print('A.f int overload',self,x)
def f(self,x:str):
print('A.f str overload',self,x)
def f(self,x,y):
print('A.f two arg overload',self,x,y)
if __name__ == "__main__":
a = A()
a.f(1)當(dāng)執(zhí)行上面代碼我們會得到一個錯誤信息,實例化 A 類后,調(diào)用實例的 f 方法,因為在 python 語言中沒有重裝方法,所以 def f(self,x:str) 會覆蓋之前的 def f(self, x:int), 而 def f(self,x,y) 方法會覆蓋于 def f(self,x:str) 方法,所以當(dāng)通過傳入 1 一個參數(shù),不會調(diào)用 def f(self,x:int) 而是調(diào)用 def f(self,x,y) 方法。
TypeError: f() missing 1 required positional argument: 'y'
那么什么是正確的姿勢解決這個問題呢? 這里先不急于給出答案,當(dāng)我們介紹完 metaclass 后,答案就自然浮出水面。
Metaclass 編程
想要了解 Metaclass 也就是元類,meta 在英文中超越的意思,也就是 Metaclass 是高級于 class,用于創(chuàng)建 class 的 class。有的時候我們需要控制類創(chuàng)建過程,通常創(chuàng)建類工作是由 type 完成的,因為 type 直接設(shè)計到 c,我們希望在 type 創(chuàng)建類過程插入一些自定義的東西,所以引入了 Metaclass 讓某一個類創(chuàng)建工作不再由 type 來實現(xiàn),而是由指定 class 來實現(xiàn)
在 python 中,我們可以通過 class 來實例化對象,不過這里要說在 python 中 class 其實也是對象。既然 class 也是對象,那么 class 的類型又是什么呢
class A:
a = 1
b = "hello"
def f(self):
return 12
def main():
print(f'{type(2)=}')
print(f'{type("hello")=}')
print(f'{type([])=}')
print(f'{type(A())=}')
if __name__ == "__main__":
main()輸出一下 2、hello 、空數(shù)組和 A 類實例的類型,結(jié)果發(fā)現(xiàn)他們類別分別為 int、str、list 和 A 類別。其實他們也是對象,既然是對象,那么就會有一個 class 用于創(chuàng)建這個類別。
type(2)=<class 'int'>
type("hello")=<class 'str'>
type([])=<class 'list'>
type(A())=<class '__main__.A'>接下來我們就看一下這些 class(int,str,list) 那么這些對象又是什么類別呢
class A:
a = 1
b = "hello"
def f(self):
return 12
if __name__ == "__main__":
print(f'{type(int)=}')
print(f'{type(str)=}')
print(f'{type(list)=}')
print(f'{type(A)=}')type(int)=<class 'type'> type(str)=<class 'type'> type(list)=<class 'type'> type(A)=<class 'type'>
不難看出多有 class 的類型都是 type ,例如數(shù)字 2 的 int 的一個實例,而 int 又是 type 的一個實例。
如果大家從類似 java 這些語言開始,然后再去學(xué)習(xí) python 可能會有這樣疑問,在 python 中 type 和 class 有什么區(qū)別,他們不都是類型嗎? 其實答案就是這兩者在 python3 中并沒有區(qū)別,可以將他們看做一個東西。
def main():
x = int()
print(f'{x=}')
B = type('B',(),{})
print(f'{B=}')
if __name__ == "__main__":
main()不過如果進(jìn)一步深入研究,兩種 class 和 type 在字面上,是不同兩樣?xùn)|西,class 作為關(guān)鍵字來定義類型時,是調(diào)用其構(gòu)造器來做了一些初始化的工作。
def main():
x = int()
print(f'{x=}')
B = type('B',(),{})
print(f'{B=}')
if __name__ == "__main__":
main()我們可以這樣來定義一個類型
x=0 B=<class '__main__.B'>
可以用 class 方式來定義一個類 A,然后我們在用 type 方式來創(chuàng)建一個類,type 接受 3 個參數(shù)分別是類的名稱,這里接受的字符串類型的名稱、以及該類的基類,是組元的形式,接下來是就是一個屬性,屬性是字典形式數(shù)據(jù),鍵是屬性名稱,值是屬性值。
class A:
a = 2
b = 'hello'
def f(self):
return 12下面我們用 make_A 來創(chuàng)建一個類, 這里使用 type 來定義一個類
def make_A():
name = 'A'
bases = ()
a = 2
b = 'hello'
def f(self):
return 12
namespace = {'a':a,'b':b,'f':f}
A = type(name,bases,namespace)
return通過 type 創(chuàng)建類時候需要傳入類名稱 A 然后 base 是一個要創(chuàng)建類 A 的基類,namescpace 是類屬性,是 dict 形式,鍵是屬性名稱,而值是屬性值。
def make_A_more_accurate():
name = 'A'
bases = ()
namespace = type.__prepare__(name,bases)
body = (
"""
a = 1
b = 'hello'
def f(self):
return 12
"""
)
exec(body,globals(),namespace)
A = type(name,bases,namespace)
return Ametaclass 是繼承于 type,那么 metaclass 的工作也是用于創(chuàng)建 class,我們可以在 metaclass 中做一些自定義的事情,
這里可能比較難理解是 __prepare__ 上網(wǎng)找到關(guān)于 __prepare__ 解釋,暫時說一下自己認(rèn)識,可能有點淺,感覺就是為類創(chuàng)建了一個局部的作用域。
namespace = type.__prepare__(name,bases) print(namespace)
type.__prepare__ 應(yīng)該是返回一個局部命名空間,
exec(body,globals(),namespace)
class Tut:
...
tut = Tut()
print(f'{type(tut)=}')
print(f'{type(Tut)=}')上面例子定義一個類,然后實例化 Tut 類得到對象 tut,接下來分別輸出 tut 和 Tut 類型
type(tut)=<class '__main__.Tut'> type(Tut)=<class 'type'>
不難看出 tut 是 Tut 的實例,而 Tut 是 type 的對象
class TutMetaClass(type):
...
class Tut(metaclass=TutMetaClass):
...然后我們定義一個 TutMetaClass 繼承于 type,然后將 Tut 類的 metaclass 指向 TutMetaClass ,然后 tut 類型為 Tut,而 Tut 類型為 TutMetaClass 類型
type(tut)=<class '__main__.Tut'> type(Tut)=<class '__main__.TutMetaClass'>
到此這篇關(guān)于 python 中的 元類metaclass詳情的文章就介紹到這了,更多相關(guān) python metaclass 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python?matplotlib.pyplot.hist()繪制直方圖的方法實例
直方圖(Histogram)又稱質(zhì)量分布圖,是一種統(tǒng)計報告圖,由一系列高度不等的縱向條紋或線段表示數(shù)據(jù)分布的情況,一般用橫軸表示數(shù)據(jù)類型,縱軸表示分布情況,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib.pyplot.hist()繪制直方圖的相關(guān)資料,需要的朋友可以參考下2022-06-06
python 實現(xiàn)二維字典的鍵值合并等函數(shù)
今天小編就為大家分享一篇python 實現(xiàn)二維字典的鍵值合并等函數(shù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
Python 數(shù)據(jù)化運營之KMeans聚類分析總結(jié)
這篇文章主要介紹了Python 數(shù)據(jù)化運營KMeans聚類相關(guān)的一些總結(jié),感興趣的話一起來閱讀下文吧2021-08-08
為什么入門大數(shù)據(jù)選擇Python而不是Java?
為什么入門大數(shù)據(jù)選擇Python而不是Java?這篇文章就來談?wù)剬W(xué)習(xí)大數(shù)據(jù)入門語言的選擇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
pycharm日志總是彈出“無法運行Git,未安裝Git”的問題
這篇文章主要介紹了pycharm日志總是彈出“無法運行Git,未安裝Git”的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

