Python 基类可以是没有 __mro_entries__ 的对象

标签 python python-3.x

今天发现不带__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/

相关文章:

python - 如何避免Python中的错误导致循环中断?

python-3.x - 如何用python提取HTML文档的 'alt'值?

python-3.x - 按特定条件聚合和分组

python - 注释不存在的 dict 字段不应该产生错误吗?

python - 删除列表中的元组,然后将平均值分配给删除的元组

python - Heroku 上的 Django 和 Postgresql - 无法将主机名 "db"转换为地址 : Name or service not known

python - 打印可能存在也可能不存在的嵌套字典值

python - 排序()返回无

python - 谁能解释 tf.random_normal 和 tf.truncated_normal 形状参数?

python - django celery 击败 DBAccessError