在Python的元类中创建类的实例是否安全?

时间:2015-05-06 18:00:01

标签: python metaclass

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

Python data model docs声音就像他们为正常的类实例创建案例编写的那样,我不确定规则在元类中发生时会有多么微妙的差异。

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

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

在元数据构建它的时候,在哪些点(如果有的话)构造Foo的实例是安全的,还有什么样的警告?

我怀疑的是,如果Foo继承了其他类,或者是子类,而其他类都有自己的元类,那么在任何元类方法中调用cls()都会调用它 - 尚未完成的类对象。这是真的吗?

1 个答案:

答案 0 :(得分:0)

  

我怀疑的是,如果Foo继承了其他类,或者是子类,而其他类都有自己的元类,那么在任何元类方法中调用cls()都会调用它。完成的类对象。这是真的吗?

确实如此,在元类的__new__中,它的__init__还没有被调用。你的元类有一个__init__,就像任何子类一样,所以你应该确保首先调用它。所以我不会尝试创建一个尚未完全实例化的类的实例。

您可能要做的一件事是从__init__内手动调用元类的__new__。但您必须在__init__中设置一个标记或内容,以确保该类不会__init__'两次。可能还有一种更聪明的方式,我现在还没想到。