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執行的,-之後的代碼是創建實例執行的。