如何确定类的元类?

Pro*_*o Q 10 python metaclass class python-3.x

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

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

jsb*_*eno 8

好吧 - 所以,一个类的元类只是它自己的"类型",可以通过type(cls)诸如之类的其他方式 给出 cls.__class__.

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

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

做的时候

class A(object):
    __metaclass__ = MyMeta
Run Code Online (Sandbox Code Playgroud)

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

考虑:

def class_pre_decorator(name, bases, namespace):
     # do something with namespace
     return type(name, bases, namespace)
Run Code Online (Sandbox Code Playgroud)

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

Python 3中没有办法猜测实际用于实例化一个类的callable,如果它没有给出使用它的其他提示(比如在类上设置一个属性):

# python 2
class A(object):
   __metaclass__ = class_pre_decorator
Run Code Online (Sandbox Code Playgroud)

在控制台上:

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

In [9]: A.__metaclass__
Out[9]: <unbound method A.class_pre_decorator>
Run Code Online (Sandbox Code Playgroud)

# Python 3
class A(metaclass=class_pre_decorator):
    pass
Run Code Online (Sandbox Code Playgroud)

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