metaclass的学习理解
一句话概括,metaclass拦截了一般实例的创建流程,自己生成实例返回。
一般实例的创建流程
假设有个类A。
class A():
def __init_(self, name)
self.name = name
print('__init__() in A')
- 调用A.new(),创建实例实体。如果,A没有定义__new__(),会向父祖先类寻找;如果都没找到,会最后调用type.new()。
- 调用A.init(),初始化实例。
定义了metaclass后的流程
先定义一个metaclass类M。
class M(type):
def __new__(cls, *args, **kwargs):
print('this is metaclass>__new__()')
obj = type.__new__(cls, *args, **kwargs) #生成类
return obj
def __call__(cls, *args, **kwargs):
obj = cls.__new__(cls, *args, **kwargs) #生成类实例, 这里的cls是A
print('in M.__call__()')
#obj.__init__(*args, **kwargs)
return obj
定义类A,指定metaclass是M。
class A(metaclass = M):
def __init__(self, name):
self.name = name
print('__init__() in A')
输出:
this is metaclass>__new__()
可以看出,是调用了M.new()生成类A。
生成实例
a = A('ant')
输出:
in M.__call__()
可以看到,实例生成a中并没有调用A.init,而是调用了M.call。这就是在类A定义时,定义了metaclass=M的结果。
官方文档
Customizing class creation python2
Customizing class creation python3.6
- metaclass可以类,也可以时函数,返回必须是一个类。
This variable can be any callable accepting arguments for name, bases, and dict. Upon class creation, the callable is used instead of the built-in type().
- metaclass的查找顺序。
The appropriate metaclass is determined by the following precedence rules:
* If dict[‘metaclass’] exists, it is used.
* Otherwise, if there is at least one base class, its metaclass is used (this looks for a class attribute first and if not found, uses its type).
* Otherwise, if a global variable named metaclass exists, it is used.
* Otherwise, the old-style, classic metaclass (types.ClassType) is used.
官方文档总是很有帮助!