【发布时间】:2021-03-01 22:41:51
【问题描述】:
我在 Python 3.8 中遇到了一个奇怪的类继承案例。
我可以通过从一个本身不是type 的实例继承来创建一个类。在那种情况下,我预计会出现 TypeError,但事实并非如此。
class B:
def __new__(cls, *args, **kwargs):
print(args, kwargs)
return super().__new__(cls)
b = B() # prints: () {}
class A(b): # I expected a TypeError here
x = "foo"
# prints: ('A', (<__main__.B object at 0x7f32bd102390>,),
# {'__module__': '__main__', '__qualname__': 'A', 'x': 'foo'}) {}
print(A) # <__main__.B object at 0x7f20556c93d0>
print(isinstance(A, B)) # True
print(isinstance(A, type)) # False
看起来当我将B() 作为A 的基础时,然后B 被用作元类。
我的理解正确吗?为什么会这样?而且我似乎找不到任何关于这种行为的信息,它是记录在案的还是特定于 cPython 的实现怪癖?
【问题讨论】:
-
好像在你的代码末尾调用
A()sn-p raisesTypeError: 'B' object is not callable -
@JakeLevi 是的,这是因为 A 最终成为 B 的实例而不是类型......由于某些语义原因,我看不到。
-
另外,如果我注释掉您对
B的定义并用class B: pass替换它,那么class A(b):行将引发TypeError: B() takes no arguments,正如您所料。因此,我猜您的问题的答案与__new__特殊方法的行为有关,您可以在此处阅读更多信息:docs.python.org/3/reference/datamodel.html#object.__new__
标签: python python-3.x class inheritance metaclass