旧式类、新式类和元类

Posted

技术标签:

【中文标题】旧式类、新式类和元类【英文标题】:Old-style classes, new-style classes and metaclasses 【发布时间】:2012-05-16 17:09:18 【问题描述】:

在 Python 2.x 中,所有新样式的类都隐式或显式地继承自 object。然后看看这个:

>>> class M(type):
...     pass
...
>>> class A:
...     __metaclass__ = M
...
>>> class B:
...     pass
...
>>> a = A()
>>> b = B()
>>> type(A)
<class '__main__.M'>
>>> type(a)
<class '__main__.A'>

这是否意味着A 是一个新式类?但是A 无论如何都不会继承自object,对吧?

>>> type(B)
<class 'classobj'>
>>> type(b)
<type 'instance'>

好的,B 是经典课程,不是吗?

>>> isinstance(A, object)
True
>>> isinstance(B, object)
True

为什么AB 的实例都是object 的实例?

如果Bobject 的一个实例,那么type(B) 就不会是classobj,对吧?

【问题讨论】:

您不应该将__slots__ 放在这个问题中。这完全是另一个问题。 @ChrisMorgan,是的,我刚刚意识到这一点。 A 是一个新样式类,因为 '新样式类是使用 type()' 构造的,并且您已将它的元类设置为 type。旧式类使用types.ClassType @jamylak,如你所见,A 没有继承自object,但我仍然在A 中使用__metaclass__,这样可以吗?因为我想,__metaclass__ 只能用于继承自 object 的类,对吧? __metaclass__ 用于每个类。每个类都有一个构建它的元类。 【参考方案1】:

关于元类,您可以在此处阅读:http://docs.python.org/reference/datamodel.html#customizing-class-creation。通常,元类旨在与新样式类一起使用。当你写:

class M(type):
    pass

你使用:

class C:
    __metaclass__ = M

您将创建一个新样式对象,因为定义了 M 的方式(默认实现使用type 来创建一个新样式类)。您始终可以实现自己的元类,该元类将使用 types.ClassType 创建旧式类。

【讨论】:

【参考方案2】:

关于插槽你可以在这里阅读http://docs.python.org/release/2.5.2/ref/slots.html,一个片段:

默认情况下,新旧类的实例都有一个用于属性存储的字典。

对于新式类,您可以添加__slots__,则不会创建每个对象的字典。

【讨论】:

以上是关于旧式类、新式类和元类的主要内容,如果未能解决你的问题,请参考以下文章

Python学习 Day14 python 类和元类(metaclass)的理解和简单运用

复习打卡--0819元类和内存管理

类和元类

单例类和元类

Python基础入门自学——12--new方法和元类

python 元类的简单解释