1 回答

TA貢獻1808條經驗 獲得超4個贊
請記住,裝飾器語法只是函數應用程序:
class Par:
def __init_subclass__(...):
...
Par = add_hello_world(Par)
最初綁定到Par定義的類__init_subclass__;內部定義的新類add_hello_world沒有,這就是裝飾后名稱Par所指的類,以及您要繼承的類。
順便說一句,您仍然可以Par通過__init__.
顯式調用裝飾器:
class Par:
def __init_subclass__(self, *args, **kwargs):
must_have = "foo"
if must_have not in list(self.__dict__.keys()):
raise AttributeError(f"Must have {must_have}")
def __init__(self):
pass
Foo = Par # Keep this for confirmation
Par = add_hello_world(Par)
我們可以確認閉包保留了對原始類的引用:
>>> Par.__init__.__closure__[0].cell_contents
<class '__main__.Par'>
>>> Par.__init__.__closure__[0].cell_contents is Par
False
>>> Par.__init__.__closure__[0].cell_contents is Foo
True
如果您確實嘗試對其進行子類化,您將得到預期的錯誤:
>>> class Bar(Par.__init__.__closure__[0].cell_contents):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tmp.py", line 16, in __init_subclass__
raise AttributeError(f"Must have {must_have}")
AttributeError: Must have foo
添加回答
舉報