Python基类可以是没有_mro_项的对象__

2024-04-28 02:23:59 发布

您现在位置:Python中文网/ 问答频道 /正文

今天,我发现不带__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的一个bug吗


Tags: 对象selfbasefoodeftypeargspass
1条回答
网友
1楼 · 发布于 2024-04-28 02:23:59

TL;DR不是一个bug,而是对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语句期望元类接受的参数相同的参数:类型名称的字符串、父类序列和用作命名空间的映射。在这种情况下,Delivered不使用它们来创建类型;它只是打印参数

因此,Foo被绑定到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

相关问题 更多 >