Python中的元類 metaclass

2021-07-05 00:07:41 字數 2240 閱讀 7044

在wiki上面,metaclass是這樣定義的:in object-oriented programming, a metaclass is a class whose instances are classes.

python中物件模型如下圖:

其中,實線表示 is-kind-of(派生)的關係,虛線表示 is-instance-of(例項化)的關係。

可以看出,object 是其他所有類的基類。

這裡並不完整,因為元類並不只有type乙個,比如enum.enummeta就是標準庫定義的乙個元類,而且也可以自己定義元類:

metaclass的原理其實是這樣的:當定義好類之後,建立類的時候其實是呼叫了 type 的 __new__ 方法為這個類分配記憶體空間,然後再呼叫type的__init__ 方法初始化。所以 metaclass 的所有 magic 其實就在這個 __new__ 方法裡面了。

一般情況下,如果你要用自定義 metaclass 的話,該類需要繼承自 type,而且通常會重寫 type 的 __new__ 方法來控制建立過程,對自定義類呼叫type() 函式的結果是

isinstance() 函式用來判斷派生關係,type() 函式可以用來檢視乙個型別或變數的型別。

當使用者定義乙個類的時候,python 直譯器首先在當前類的定義中查詢 metaclass,如果沒有找到,就繼續在基類中查詢 metaclass,找到了,就使用它建立類,也就是說,metaclass 可以隱式地繼承到子類,但子類自己卻感覺不到。

乙個類的定義方式可以是這樣的:

class c(object, metaclass=mymetaclass):

......

class的__new__ 是用來構建object的,__init__是用來在構建好object後進行初始化的,__new__ 第乙個引數是class本身,__init__的第乙個引數是self,self就是已經構建好的object啊,其他引數相同。

這™不就是把c++裡建構函式的功能分開了嘛!然而我覺得普通類的__new__ 並沒什麼用,又不需要和c++似的去操縱記憶體,不過是一層一層呼叫基類的__new__ 。

關鍵是python還有個metaclass啊,用來構建class,這些metaclass的基類是type。metaclass的__init__反而不重要了,只要構造出class來就行,不需要初始化。

metaclass的__new__(cls, name, bases, attrs)是長這個樣子的,其中:

cls:指的是metaclass本身

name:class的名字,是乙個字串,也就是我們通常用 類名.__name__ 獲得的那個

bases:class的基類組成的元組

attrs:class的屬性組成的dict

什麼時候構建類呢?就在類定義的時候,比如下面class x的定義:

class

meta

(type):

def__new__

(cls, name, bases, attrs):

print('in meta')

return type.__new__(cls, name, bases, attrs)

class

x(object, metaclass=meta):

pass

# 輸出in meta

這個定義其實是被直譯器解釋為x = meta('x', (object,), {})的,meta既然是metaclass,那也是class啊,所以先呼叫了__new__來構建x,然後呼叫__init__來初始化x。所以列印出了「in meta」。

在建立類的過程,我們可以在__new__裡面修改 name,bases,attrs 的值來達到我們的功能。這裡常用的配合方法是 getattr 和 setattr。

另外還有乙個限制,the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases。

python中的元類

python中的元類大家都可能比較很陌生,因為大家都聽說過99 的情況下是用不到元類的,但是大家對類確很了解,大家都知道在python中萬物皆物件,那麼python中的類是不是物件呢?物件的樣子 1,物件可以在程式中動態的進行建立,python的語言動態特性。2,物件可以通過 class 獲取該物件...

Python 中的元類

如果看完以後還是感覺莫名其妙,執行這樣乙個demo 可能會對你有所幫助 元類程式設計在我看來,如果你想開發一些框架,可以嘗試一下 class upperattrmetaclass type type dict def new cls,cls name,bases,attr dict news cls...

python中的元類

目錄其他 我們建立乙個類目的是為了建立該類的例項物件,而元類就是用來建立類的。換個理解方式就是,元類就是建立類的類。在python中可以使用type函式建立乙個類,參考 python中type的用法 用法如下 tpye name,bases,dict 實際上type 函式就是乙個元類,是python...