简要记录Python3中的metaclass。注意本文是基于new-style class的。Python3中所有class都是new-style class,Python2则不同:Python2.2以前根本不支持new-style class,而从Python2.2开始,虽然支持但需要显示地声明。
一切皆对象 (1)
在Python中,一切都是对象,比如: int, 3, 自定义类的实例foo,以及自定义类Foo,所以下面的语句都打印True:
1 | print(isinstance(3, object)) |
Foo是对象,那么它的class是什么呢?答案是metaclass:默认情况下,Foo是metaclass type的实例,我们也可以自定义metaclass,见第2节。

图1
如图所示:
foois an instance of classFoo.Foois an instance of thetypemetaclass.typeis also an instance of thetypemetaclass, so it is an instance of itself.
自定义metaclass (2)
先看这段代码:
1 | #!/usr/bin/python3 |
用图形表示:

图2
当python解析器遇见Foo()语句时:
- 调用
Foo的metaclass的__call__,即调用type.__call__,注意:不是`Foo.call. Foo.__call__调用:Foo.__new__Foo.__init__
当python解析器遇见Bar()语句时:
- 调用
Bar的metaclass的__call__,即调用Meta.__call__,注意:不是`Bar.call. Meta.__call__调用:Bar.__new__Bar.__init__
注意区分object-class的从属关系和class-class的继承关系:
- 找
__call__时,沿着object-class的从属关系往上走。 - 找
__new__和__init__时才进入继承领域,沿着class-class的继承关系往上走。
所以,上面代码的输出是:
1 | Meta.__new__ enter |
上面重点解释了foo和bar的创建过程。但不是说一切皆对象吗?Foo和Bar本身是怎么创建的呢?注意main enter之前还有两行输出,它们就是创建Bar的过程,其实和创建实例的过程一样:
- 先调用
Bar的class的metaclass的__call__:沿着object-class的从属关系往上走,Bar的class是Meta(就是Bar的metaclass),Meta的metaclass是type,所以这一步调用type.__call__,什么也没有打印。 type.__call__调用:Meta.__new__Meta.__init__
这里注意class的class就是它的metclass;这应该也是meta一词的来源。
另外,Foo的的metaclass是type,我们没有机会在它里面添加打印语句,所以Foo的创建什么都没打印。
通过type动态创建class (3)
下面两种方式是等价的:
1 | def plus(self, i): |
1 | class Foo: |