python中的元類總結:
-
元類實際上做了以下三方面的工作:
- 干涉創建類的過程
- 修改類
- 返回修改之后的類
總結一句話,動態的創建類
-
元類查找的順序:
- 首先檢查Foo中是否具有屬性metaclass?
- 如果找到,就使用metaclass定義的元類在內存中創建一個類對象。
- 如果在類定義中沒有找到這個屬性,就在模塊級別中進行查找。
- 如果還是沒有找到,就會使用父類Bar中的元類來創建類。
-
metaclass里面方法的順序:
- __new__: 用于動態創建每一個類,這樣在創建的過程中,修改類的屬性方法等,只有在類的生成是調用一次
- __init__: 這個方法在new完成后,用來給屬性和方法初始化,類生成時候調用一次
- __call__: 每次生成類的對象時候,調用一次,然后調用類自己的init函數,所以可以在__call__里面做一下生成對象時候統計
代碼示例:
# -*- coding:utf8 -*-
class Basic(type):
count = 0
def __new__(cls, name, bases, newattrs):
print "new: %r %r %r %r" % (cls, name, bases, newattrs)
return super(Basic, cls).__new__(cls, name, bases, newattrs)
def __call__(self, *args):
print "call: %r %r" % (self, args)
self.count += 1
return super(Basic, self).__call__(*args)
def __init__(cls, name, bases, newattrs):
print "init: %r %r %r %r" % (cls, name, bases, newattrs)
super(Basic, cls).__init__(name, bases, dict)
class Foo:
__metaclass__ = Basic
def __init__(self, *args, **kw):
print "init: %r %r %r" % (self, args, kw)
a = Foo('a')
print a.count
b = Foo('b')
print a.count
c = Foo('c')
print a.count
結果:
new: <class '__main__.Basic'> 'Foo' () {'__module__': '__main__', '__metaclass__': <class '__main__.Basic'>, '__init__': <function __init__ at 0x7f95aa8927d0>}
init: <class '__main__.Foo'> 'Foo' () {'__module__': '__main__', '__metaclass__': <class '__main__.Basic'>, '__init__': <function __init__ at 0x7f95aa8927d0>}
call: <class '__main__.Foo'> ('a',)
init: <__main__.Foo object at 0x7f95aa8991d0> ('a',) {}
1
call: <class '__main__.Foo'> ('b',)
init: <__main__.Foo object at 0x7f95aa899290> ('b',) {}
2
call: <class '__main__.Foo'> ('c',)
init: <__main__.Foo object at 0x7f95aa8992d0> ('c',) {}
3