Python中的metaclass

pythonmetaclass

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

Date: 2013-07-18 22:41:39 中國標準時間

Author:

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章