在嘗試?yán)斫庠悇?chuàng)建類實(shí)例的順序時(shí),我感到困惑.根據(jù)該圖(source),
我鍵入以下代碼進(jìn)行驗(yàn)證.
class Meta(type):
def __call__(self):
print("Meta __call__")
super(Meta, self).__call__()
def __new__(mcs, name, bases, attrs, **kwargs):
print("Meta __new__")
return super().__new__(mcs, name, bases, kwargs)
def __prepare__(msc, name, **kwargs):
print("Meta __prepare__")
return {}
class SubMeta(Meta):
def __call__(self):
print("SubMeta __call__!")
super().__call__()
def __new__(mcs, name, bases, attrs, **kwargs):
print("SubMeta __new__")
return super().__new__(mcs, name, bases, kwargs)
def __prepare__(msc, name, **kwargs):
print("SubMeta __prepare__")
return Meta.__prepare__(name, kwargs)
class B(metaclass = SubMeta):
pass
b = B()
但是,結(jié)果似乎不是這樣的.
SubMeta __prepare__
Meta __prepare__
SubMeta __new__
Meta __new__
SubMeta __call__!
Meta __call__
任何幫助將不勝感激. 解決方法: 盡管@ torek的長篇答案,以及關(guān)于課堂創(chuàng)作的許多其他細(xì)節(jié),你在這個(gè)問題上匯集的內(nèi)容大多是正確的.
你的代碼中唯一錯(cuò)誤的就是讓你感到困惑的是你調(diào)用Meta的te類本身就是SubMeta的元類,而不是它的父元素.
只需將Submeta聲明更改為:
class SubMeta(type, metaclass=Meta):
...
(也不需要它繼承“Meta” – 它只能從類型派生.除此之外,我想要定制類型.__ call__,這對于創(chuàng)建類的實(shí)例同時(shí)是有用的(當(dāng)調(diào)用SubMeta .__ call__時(shí),你的類本身(調(diào)用Meta .__ call__))
這是我剛在終端輸入的另一個(gè)較短的例子.很抱歉命名不一致,并且不太完整 – 但它顯示了要點(diǎn):
class M(type):
def __call__(mmcls, *args, **kwargs):
print("M's call", args, kwargs)
return super().__call__(*args, **kwargs)
class MM(type, metaclass=M):
def __prepare__(cls, *args, **kw):
print("MM Prepare")
return {}
def __new__(mcls, *args, **kw):
print("MM __new__")
return super().__new__(mcls, *args, **kw)
class klass(metaclass=MM):
pass
在處理klass體時(shí),Python輸出是:
MM Prepare
M's call ('klass', (), {'__module__': '__main__', '__qualname__': 'klass'}) {}
MM __new__
此外
正如您所看到的,使用元元類,可以自定義元類__init__和__new__的調(diào)用順序和參數(shù),但仍然存在無法從純Python代碼自定義的步驟,并且需要對API的本機(jī)調(diào)用(以及可能的原始對象結(jié)構(gòu)操作) – 即:
>無法控制對__prepare__的調(diào)用 >無法控制對創(chuàng)建的類的__init_subclass__的調(diào)用 >可以控制何時(shí)調(diào)用描述符’__set_name__
最后兩個(gè)項(xiàng)目發(fā)生在meta-meta的__call__返回之后,并且在將流程恢復(fù)到類模塊所在的模塊之前. 來源:http://www./content-1-228701.html
|