Python 多继承下 metaclass 优先级
在 Python 里面,class 也是一个对象,它是 type 实例化后生成的对象。 我们一般用如下的代码来定义一个类。
class ClassA(object):
def method1(self):
pass
@classmethod
def method2(cls):
pass
实际上 class
这个关键字是类似语法糖一样的东西。 上面的 class 定义等价为
def method1(self):
pass
@classmethod
def method2(cls):
pass
attrs = {
'method1': method1,
'method2': method2,
}
ClassA = type('ClassA', (object,), attrs)
type
的三个参数分别为:
-
类的名字(
ClassA.__name__
中存储的名字), -
继承的父类(可以是多个父类),
-
类的所有属性(类的各种方法和属性)。
以上是一个未指定 __metaclass__
的 class 的生成过程。
但是在 ORM 的代码中,经常可以看到类似这样的写法
class MetaA(type):
def __new__(cls, name, bases, attrs):
# some work
new_class = xxx
return new_class
class ClassB(object):
__metaclass__ = MetaA
def create_xxx(self):
pass
在 ClassB
的属性中,比之前多了一个 __metaclass__
的属性。__metaclass__
是做什么用的呢?
我们先把这个类用 type(name, bases, attrs)
的方式重新写下。
class MetaA(type):
def __new__(cls, name, bases, attrs):
# some work
new_class = xxx
return new_class
def create_xxx(self):
pass
attrs = {
'create_xxx': create_xxx,
}
ClassB = MetaA('ClassB', (object,), attrs)
__metaclass__
的属性就是替换 type
的。 __metaclass__
的默认值就是 type
。
那如果子类从指定了 __metaclass__
的父类继承,而子类未指定 __metaclass__
会怎么样呢?
class ClassC(ClassB):
pass
通过实现,我们可以得知 ClassC
会用 ClassB
的 __metaclass__
属性来生成自己。
Important
|
当一个类自己没有定义 |
我们还有有一个疑问:
如果父类指定了 __metaclass__
, 父类的父类也指定了 __metaclass__
;或者父类继承了多个父类,
这多个父类都有自己的 __metaclass__
,那会发生什么情况?
对于这一点,Python 对 __metaclass__
有一个限制, 就是一个类的 __metaclass__
和它所有父类的所有 __metaclass__
必须有继承关系或者是同一个 (参考Python源码) 。
在这个基础上,真实使用的 __metaclass__
是继承链的最底端,既是最子类的那个 metaclass。
Important
|
一个类的 |