如何确定类的元类?

时间:2017-05-08 17:25:47

标签: python python-3.x class metaclass

我有一个类对象cls。我想知道它的元类。我该怎么做?

(如果我想知道它的父类,我会做cls.__mro__。是否有这样的东西来获取元类?)

1 个答案:

答案 0 :(得分:5)

好的 - 所以,一个类的元类只是它自己的“类型”,可以由它给出 type(cls)以及其他方式,例如cls.__class__

在Python 3.x中没有进一步的歧义 - 因为创建元类的语法只是将它作为命令参数传递给类声明语句。

但是,用于在Python 2.x中创建元类的语法会产生值得注意的副作用。

做完

class A(object):
    __metaclass__ = MyMeta

__metaclass__属性设置为实际类中的值,即使实际的元类是另一个

考虑:

def class_pre_decorator(name, bases, namespace):
     # do something with namespace
     return type(name, bases, namespace)

这是一个可调用的,可以在Python 2和3的元类声明中使用 - 它是有效的。解析后,两种情况下的实际元类都只是type。但是,在Python 2.x中,cls.__metaclass__将指向可调用的class_pre_decorator,即使是强大的type(cls)也会返回type,这是正确的元类。(请注意,使用callables这样,当类进一步子类化时,它们将不会被用于agian)

如果Python没有提供其他提示(比如在类上设置属性),那么Python 3中没有办法猜测实际用于实例化类的可调用对象是什么:

# python 2
class A(object):
   __metaclass__ = class_pre_decorator

在控制台上:

In [8]: type(A)
Out[8]: type

In [9]: A.__metaclass__
Out[9]: <unbound method A.class_pre_decorator>

# Python 3
class A(metaclass=class_pre_decorator):
    pass

尝试阅读A.__metaclass__只会引发一个AttributeError。