如何确定一个类的元类?

25

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

(如果我想知道它的父类,我会使用 cls.__mro__。是否有类似的方法可以获取元类?)


6
只需输入 type(cls) - vaultah
@Jim 在我看来,一个好的答案应该解释为什么类对象的类型是它所创建的元类。 - vaultah
如果 OP 的问题改成了实际上询问“为什么”而不是“如何”,那么 @vaultah 可以肯定地重新打开它。就目前情况而言,我个人认为它不应该被重新打开。如果您仍然认为有必要重新打开,请随意这样做。 - Dimitris Fasarakis Hilliard
Python中的一切都是对象。类也是对象。每个对象都有一个与之关联的类,可以通过type(myobject)来获取它。元类只是一个类的类。 - hello world
有关类别化的特定问题,在之前的重复问题中可能没有涉及,即使有涉及,寻找元类的人也不会自动搜索“查找对象类型” - 解释这两个问题相同的文本应该在回答这个问题时加以说明。(这就是为什么我要求重新开放它的原因) - jsbueno
1个回答

19

好的- 那么,一个类的元类只是它自己的 "类型",并且可以通过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。(请注意,以这种方式使用可调用函数时,当类进一步派生时它们不会再次使用)

在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异常。


我认为你的最后一个例子不是很清楚。由于在Python 2和3之间指定元类的语法变化,class_pre_decorator 不是 class A(object)的元类——在Python 3中定义类的__metaclass__属性对使用哪个元类没有影响(无论它是什么类型的值,可调用或不可调用)。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接