python的元类
类是用来生成实例的模板,而元类则是用来生成类的模板。
在 Python(以及其它语言)中,类本身就是可以被传递和自省的对象。正如前面所讲到的,既然可以用类作为模板来生成对象,那么用什么 作为模板来生成类呢?答案当然是 元类(metaclass)。
python 2.2+以后提供了一个称为type的特殊类,它是一个类工厂。
使用type创建新类:
>>> X = type('X', (), {'foo': lambda self: 'foo'}) >>> X, X().foo() (<class '__main__.X'>, 'foo')
X就是type创建的类。
可以用来使用type的子类,来创建新类:
1 class ChattType(type): 2 def __new__(cls, name, bases, dct): # __new__函数创建类 3 # 在__new__方法里,cls是ChattType类本身 4 # name是类的名称,字符串 5 # bases是类的基类,一个tuple 6 # dct是附件到类上的属性和方法,是一个字典 7 8 print "Allocating memory for class", name 9 print "cls is: ", cls 10 print "name is: ", name 11 print "bases is: ", bases 12 print "dct is: ", dct 13 print 14 return type.__new__(cls, name, bases, dct) # 创建类 15 16 def __init__(cls, name, bases, dct): # __init__函数初始化类 17 # 在__init__方法里,cls是已经创建好的类 18 # name, bases, dct属性和__new__方法相同 19 20 print "Initing class", name 21 print "cls is: ", cls 22 print "name is: ", name 23 print "bases is: ", bases 24 print "dct is: ", dct 25 print 26 super(ChattType, cls).__init__(name, bases, dct) 27 28 def some_func(cls): 29 print "cls is: ", cls 30 print 31 # 在这里,cls是已经生成好的类 32 # 将类方法附件到生成的类上 33 return "i am some_func in metaclass." 34 35 X = ChattType('X', (), {'foo': lambda self: 'foo'}) 36 37 # 创建好的X类 38 print X 39 print 40 41 # 类X的some_func方法 42 print X.some_func() 43 print 44 45 # 类X的实例的foo方法 46 print X().foo() 47 print 48 49 # 调用类X的实例的some_func方法会报错!!! 50 print X().some_func()
下面是运行结果:
Allocating memory for class X cls is: <class '__main__.ChattType'> name is: X bases is: () dct is: {'foo': <function <lambda> at 0x7f4f54b96668>} Initing class X cls is: <class '__main__.X'> name is: X bases is: () dct is: {'foo': <function <lambda> at 0x7f4f54b96668>} <class '__main__.X'> cls is: <class '__main__.X'> i am some_func in metaclass. foo Traceback (most recent call last): File "meta_class.py", line 53, in <module> print X().some_func() AttributeError: 'X' object has no attribute 'some_func'
注意:
在__new__方法中,第一个参数cls表示的元类的子类本身,就是ChattType。
而在__init__方法中,第一个参数cls表示已经创建好的类。
但是像下面这种情况下,在类中使用__new__则情况不同:
class t(object):
# __new__函数创建实例 def __new__(cls, *args, **kwargs): print "cls is: ", cls print "args is: ", args print "kwargs is: ", kwargs #return super(t, cls).__new__(cls, *args, **kwargs) return object.__new__(cls, *args, **kwargs)
# __init__函数初始化实例 def __init__(self): print "init"
运行结果:
cls is: <class '__main__.t'> args is: () kwargs is: {} init
在类的__new__方法里,cls参数是类本身。