Dav*_*ean 4 python inheritance metaclass python-3.x
我试图了解当您声明一个从 python 中的父类继承的新类时实际发生的情况。
\n这是一个非常简单的代码片段:
\n# inheritance.py\nclass Foo():\n def __init__(self, *args, **kwargs):\n print("Inside foo.__init__")\n print(args)\n print(kwargs)\n\n\nclass Bar(Foo):\n pass\n\nprint("complete")\n
Run Code Online (Sandbox Code Playgroud)\n如果我运行它,就没有错误,并且输出正如我所期望的那样。
\n\xe2\x9d\xaf python inheritance.py \ncomplete\n
Run Code Online (Sandbox Code Playgroud)\n这是一个有明显错误的脚本,我继承自 的实例而Foo()
不是类Foo
# inheritance.py\nclass Foo():\n def __init__(self, *args, **kwargs):\n print("Inside foo.__init__")\n print(f"{args=}")\n print(f"{kwargs=}\\n")\n\nfoo = Foo()\nclass Bar(foo): <---- This is wrong\n pass\n\nprint("complete")\n
Run Code Online (Sandbox Code Playgroud)\n这段代码运行时不会崩溃,但是我不明白为什么Foo.__init__()
被调用两次。
这是输出:
\n\xe2\x9d\xaf python inheritance.py\nInside foo.__init__ <--- this one I expected\nargs=()\nkwargs={}\n\nInside foo.__init__ <--- What is going on here...?\nargs=('Bar', (<__main__.Foo object at 0x10f190b10>,), {'__module__': '__main__', '__qualname__': 'Bar'})\nkwargs={}\n\ncomplete\n
Run Code Online (Sandbox Code Playgroud)\n在第 8 行,我实例化了Foo()
没有参数的实例,这正是我所期望的。然而,第 9 行Foo.__init__
使用通常传递type()
来生成新类的参数进行调用。
我可以隐约看到发生了什么:class Bar(...)
是生成新类的代码,因此在某些时候type("Bar", ...)
需要调用但是:
Foo()
被Foo.__init__("Bar", <tuple>, <dict>)
调用?type("Bar", <tuple>, <dict>)
调用呢?Python 用于foo
确定要用于Bar
. 没有给出显式的元类,因此必须确定“最派生的元类”。基类的元类是它的类型;通常,这就是type
它本身。但在这种情况下,唯一的基“类”的类型foo
是Foo
,因此它成为最派生的元类。所以,
class Bar(foo):
pass
Run Code Online (Sandbox Code Playgroud)
被视为
class Bar(metaclass=Foo):
pass
Run Code Online (Sandbox Code Playgroud)
这意味着它Bar
是通过调用 Foo
创建的:
Bar = Foo('Bar', (foo,), {})
Run Code Online (Sandbox Code Playgroud)
请注意,Bar
现在是 的实例Foo
,而不是类型。是的,一条class
语句并不一定会创建一个类。
归档时间: |
|
查看次数: |
76 次 |
最近记录: |