【问题标题】:How can I set the metaclass when calling `type`?调用 type 时如何设置元类?
【发布时间】:2023-02-22 17:50:37
【问题描述】:

我正在尝试解决元类冲突:

>>> class A(B, C):
...   pass
...
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

为此,我想设置我使用 type 内置函数创建的类的元类。在课堂陈述中,我会这样做:

def merged(*parents):
  return type("meta", tuple(type(p) for p in parents), {})

class A(B, C, metaclass=merged(B, C)):
  pass

来自docs

提供给三参数形式的关键字参数被传递给适当的元类机制(通常是__init_subclass__()),其方式与类定义中的关键字相同(除了元类) 会。

事实上,以下内容仍然提出相同的TypeError

def merged(*parents)
A = type("A", (B, C), {}, metaclass=merged(B, C))

那我怎样才能传递元类呢?

【问题讨论】:

  • 到底是做什么的“试图防止元类混淆的情况”意思是?当你说“不起作用”具体发生了什么,给一个minimal reproducible example - 如果有错误,例如,这就是下一个人可能正在搜索的内容。
  • 我将包括一个解释元类混淆的参考,并包括引发的典型 TypeError :)
  • @jonrsharpe 在看到它漂浮在我再也找不到的空灵引用中后,我将“元类混淆”一词牢记在心,所以我将其改编为错误声明中所见的“元类冲突”:)

标签: python-3.x metaclass


【解决方案1】:

object是类的基类,type是元类的基类。这意味着继承自object 的对象在调用时将生成实例,继承自type 的对象将在调用时生成类。

您的 merged 函数已经采用 object-继承类,并通过使用他们的 type-继承元类,使用 type 的第一个参数形式进行检查。这意味着从 merged 生成的类型本身就是一个元类;显然,因为您随后将其传递给metaclass=

总之,您可以调用此元类,就像调用type 一样,以生成元类merged(B, C) 的类:

metaA = merged(B, C)
A = metaA("A", (B, C), {})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多