今天发现不带__mro_entries__
的python对象可以作为基类。
例子:
class Base:
def __init__(self, *args):
self.args = args
def __repr__(self):
return f'{type(self).__name__}(*{self.args!r})'
class Delivered(Base):
pass
b = Base()
d = Delivered()
class Foo(b, d):
pass
print(type(Foo) is Delivered)
print(Foo)
True
Delivered(*('Foo', (Base(*()), Delivered(*())), {'__module__': '__main__', '__qualname__': 'Foo'}))
因此 Foo
将是 Delivered
类的实例,它不是有效类型。
我确实理解 __mro_entries__
的用例,但是使用没有 __mro_entries__
的对象作为基类的用例是什么。是 python 的错误吗?
最佳答案
TL;DR 不是错误,而是对 class
语句的极端滥用。
一个class
语句是equivalent to a call to a metaclass .缺少显式的 metaclass
关键字参数,元类必须从基类中推断出来。这里,“类”b
的“元类”是Base
,而d
的元类是Delivered
.由于每个都是通用元类 (Base
) 的非严格子类,因此选择 Delivered
作为更具体的元类。
>>> Delivered('Foo', (b, d), {})
Delivered(*('Foo', (Base(*()), Delivered(*())), {}))
Delivered
可以用作元类,因为它接受与 class
语句期望元类接受的参数相同的参数:类型名称的字符串,a父类的序列,以及用作命名空间的映射。在这种情况下,Delivered
不使用它们来创建类型;它只是打印参数。
因此,Foo
绑定(bind)到 Delivered
的实例,而不是类型。所以 Foo
是一个类,仅在它是由 class
语句生成的意义上:它绝对不是类型。
>>> issubclass(Foo, Delivered)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: issubclass() arg 1 must be a class
>>> Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Delivered' object is not callable
关于Python 基类可以是没有 __mro_entries__ 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68743079/