在 Python 的元 class 中创建 class 的实例安全吗?

Is it safe to create an instance of a class in its metaclass in Python?

在 metaclass 构造函数(__new____init__)中创建 class 的实例有多安全?我对 Python 2.7 特别感兴趣,但也欢迎 Python 3 的功能。

Python data model docs 听起来像是为正常的 class 实例创建案例编写的,我不确定规则在元 class.

例如,假设我有这样的代码:

class Meta(type):
  NEWED = []
  INITED_BEFORE = []
  INITED_AFTER = []
  def __new__(meta, name, bases, dict):
    cls = super(Meta, meta).__new__(meta, name, bases, dict)
    instance = cls()
    Meta.NEWED.append(instance)
    return cls

  def __init__(cls, name, bases, dict):
    Meta.INITED_BEFORE.append(cls())
    super(Meta, cls).__init__(name, bases, dict)
    Meta.INITED_AFTER.append(cls())

class Foo(object):
  __metaclass__ = Meta

在 metaclass 构建 Foo 的实例时,在哪些点(如果有的话)构建它是安全的,有哪些注意事项?

我的一个怀疑是,如果 Foo 继承了其他 classes,或者被子classed,而其他 classes 有自己的 metaclass,然后在任何 metaclass 方法中调用 cls() 将在尚未完成的 class 对象上调用它。是真的吗?

One suspicion I have is that, if Foo inherited other classes, or was subclassed, and those other classes had their own metaclass, then calling cls() in any of the metaclass methods would be calling it on a not-yet-finished class object. Is that true?

的确如此,在元class 的__new__ 中,它的__init__ 还没有被调用。你的 metaclass 有一个 __init__,任何 subclass 也可能有,所以你应该确保先调用它。所以我不会尝试创建尚未完全实例化的 class 的实例。

您可能会做的一件事是从 __new__ 中手动调用元 class 的 __init__。但是你必须在 __init__ 中设置一个标志或其他东西,以确保 class 不会被 __init__ 两次。可能还有更聪明的方法,我现在还没有想到。