python中的元類(lèi)總結(jié):
-
元類(lèi)實(shí)際上做了以下三方面的工作:
- 干涉創(chuàng)建類(lèi)的過(guò)程
- 修改類(lèi)
- 返回修改之后的類(lèi)
總結(jié)一句話,動(dòng)態(tài)的創(chuàng)建類(lèi)
-
元類(lèi)查找的順序:
- 首先檢查Foo中是否具有屬性metaclass倦炒?
- 如果找到,就使用metaclass定義的元類(lèi)在內(nèi)存中創(chuàng)建一個(gè)類(lèi)對(duì)象明棍。
- 如果在類(lèi)定義中沒(méi)有找到這個(gè)屬性弄息,就在模塊級(jí)別中進(jìn)行查找蜜葱。
- 如果還是沒(méi)有找到钠右,就會(huì)使用父類(lèi)Bar中的元類(lèi)來(lái)創(chuàng)建類(lèi)邪意。
-
metaclass里面方法的順序:
- __new__: 用于動(dòng)態(tài)創(chuàng)建每一個(gè)類(lèi),這樣在創(chuàng)建的過(guò)程中,修改類(lèi)的屬性方法等,只有在類(lèi)的生成是調(diào)用一次
- __init__: 這個(gè)方法在new完成后,用來(lái)給屬性和方法初始化,類(lèi)生成時(shí)候調(diào)用一次
- __call__: 每次生成類(lèi)的對(duì)象時(shí)候,調(diào)用一次,然后調(diào)用類(lèi)自己的init函數(shù),所以可以在__call__里面做一下生成對(duì)象時(shí)候統(tǒng)計(jì)
代碼示例:
# -*- 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
結(jié)果:
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