<?xml version="1.0" encoding="gb2312"?>
pythonmetaclass
Table of Contents
1 Python中的metaclass
metaclass翻译元类,即用来创建类的类。 在文档中的解释为
The class of a class. Class definitions create a class name, a class dictionary, and a list of base classes. The metaclass is responsible for taking those three arguments and creating the class. Most object oriented programming languages provide a default implementation. What makes Python special is that it is possible to create custom metaclasses. Most users never need this tool, but when the need arises, metaclasses can provide powerful, elegant solutions. They have been used for logging attribute access, adding thread-safety, tracking object creation, implementing singletons, and many other tasks.
1.1 metaclass的执行顺序
如:
class Test(metaclass=Meta): pass
如果Meta和Test都有实现_new_和_init_函数,其直行顺序为Meta._new__, Meta._init__, Test._new__, Test._init__
看下面的例子:
class Meta(type): def __init__(self, name, bases, ns, **kwds): print('Meta.init', type(self), self) def __new__(self, name, bases, ns, **kwds): print('Meta.new', type(self), self, name, bases, ns, kwds) # type(self) = <class 'type'>, self = <class '__main__.Meta'> # name = 'Test', bases = (object,)父类集合, ns = 类Test数据字典, kwds = ret = super().__new__(self,name, bases, dict(ns)) print('after Meta.new', type(ret), ret) # type(ret) = Meta, ret = Test # 类Meta,值Test return ret print('*'*20) class Test(object, metaclass=Meta): a = 1 def __init__(self): self.b = 2 print('Test.init', type(self), self) # type(self) = class Test, self = object Test def __new__(self, *args, **kwds): print('Test.new', type(self), self) # type(self) = Meta, self = Test 用Meta创建Test ret = super().__new__(self) # super() = object print('after Test.new', type(ret), ret) # type(ret) = class Test, ret = object Test return ret print('-'*20) t = Test() print(type(t), t) print('='*20)
通过代码注释,大概知道了代码中各个变量的取值。在运行代码前,试试画出各个打印部分的顺序。上面已经说过Meta._new__, Meta._init__, Test._new__, Test._init_,那么*,-,=几行标志的顺序呢? 下面看执行结果:
******************** Meta.new <class 'type'> <class '__main__.Meta'> <class 'str'> (<class 'object'>,) {'a': 1, '__qualname__': 'Test', '__init__': <function Test.__init__ at 0x01E0A078>, '__module__': '__main__', '__new__': <function Test.__new__ at 0x01E0A0C0>} {} after Meta.new <class '__main__.Meta'> <class '__main__.Test'> Meta.init <class '__main__.Meta'> <class '__main__.Test'> -------------------- Test.new <class '__main__.Meta'> <class '__main__.Test'> after Test.new <class '__main__.Test'> <__main__.Test object at 0x01DF3E70> Test.init <class '__main__.Test'> <__main__.Test object at 0x01DF3E70> <class '__main__.Test'> <__main__.Test object at 0x01DF3E70> ====================
从直行接过看,*在最先打印,而-打印在Meta直行后,可以看出,-之前的代码是创建class执行的,-之后的代码是创建实例执行的。