元类的引入
在Python的世界里,一切均是对象,包括函数、class;如果class是用来生成对象的,那么作为对象的class,又是由谁生成的呢?答应就是meta-class,meta-class是用来生成class的class。在python中,有两个默认的meta class,分别是经典类的types.ClassType, 新式类的type
元类生成class的过程
type(calss_name, (parent_class,),{‘function_name’:function, 'property_name':property_value})
对于形如下面的class
class Base(object): def fun_base(self): print 'this is base fun'class Foo(Base): def __init__(self): self.a = 1 def fun(self): print 'this is fun'
如果使用meta-class来生成同样的class,其过程
class Base(object): def fun_base(self): print 'this is base fun'def fun(self): print 'This is fun'c = type('Foo', (Base,), {'fun':fun, 'a':1})c1 = c()print cprint c1print type(c1)c1.fun()c1.fun_base()print c1.a
其输出为,type()的返回值是一个class,由其生成的对象c1 其类型是class Foo,c1可以调用其自己与其父类的成员函数,也可以访问自己的属性。其面向对象的所有属性与上面定义的class Foo一致
<__main__.Foo object at 0x000000000270DF28> <__main__.Foo object at 0x000000000270DF28>This is funthis is base fun1
当python的解释器遇到语句class的时候,就会寻找该class的meta clas去生成其对象,也就是class本身,其查找meta clas的过程如下:
1.class是否定义属性 __metaclass__
__metaclass__
3.class所在的模块是否定义__metaclass__
4.使用默认的metaclass:旧式类 types.ClassType;新式类 type 其实,在python的定义中,meta class不仅仅局限于type和type.ClassType,任何接受参数name,tuple,dict,返回值为class的可调用变量都可以当做meta class
This variable can be any callable accepting arguments for name, bases, and dict. Upon class creation, the callable is used instead of the built-in type().
那么借助这个定义,我们可以对type()做一定的封装,让称为meta class
我们可以定义自己的meta classclass MetaCls(type): def __new__(cls, name, bases, dict): # do customizing here return super(MetaCls, cls).__new__(cls, name, bases, dict)
我们甚至可以把一个函数变成一个meta class
def metacls_func(name, bases, dict): # do customizing here return type(name, bases, dict)
__new()__
与__init()__
在python中,__new()__
、__init()__
是与对象生成密切相关的两个magic method,前者完成对象生成过程,后者完成对象的初始化过程。
class C(object): def __new__(cls, *args, **kwargs): # cls is a class, and __new__() returns a object print '__new__ called. args is ', args, 'kwargs is ', kwargs print 'the type of cls is ', type(cls), ' the cls is ', cls c = super(C, cls).__new__(cls, *args, **kwargs) print 'the type of c is ', type(c), ' the c is ', c return c def __init__(self, *args, **kwargs): print '__init__ called. args is ', args, 'kwargs is ', kwargs print 'the type of self is ', type(self), 'the self is ', selfc1 = C(1, 2, a=3)print c1c2 = C(3, 4, b=4)print c2
其输出为
__new__ called. args is (1, 2) kwargs is {'a': 3}the type of cls isthe cls is the type of c is the c is <__main__.C object at 0x00000000026ADE48>__init__ called. args is (1, 2) kwargs is {'a': 3}the type of self is the self is <__main__.C object at 0x00000000026ADE48><__main__.C object at 0x00000000026ADE48>__new__ called. args is (3, 4) kwargs is {'b': 4}the type of cls is the cls is the type of c is the c is <__main__.C object at 0x00000000026ADE80>__init__ called. args is (3, 4) kwargs is {'b': 4}the type of self is the self is <__main__.C object at 0x00000000026ADE80><__main__.C object at 0x00000000026ADE80>
这段代码说明:
__new()__
的作用:当调用c1 = C(1, 2, a=3)
时,class
语句会查找__metaclass__
生成class C
,之后__new()__
被调用,通过调用父类的__new()__
生成对象(super(C, cls).__new__(cls, *args, **kwargs)
的返回值是一个Class C的一个对象,类型是class C)__init()__
的作用:当__new()__
返回一个对象之后,会继续调用__init()__
进行对象的初始化过程。(如果__new()__
没有返回一个对象,那么后续的__init()__
也不会被调用)cls
与self
:二者分别是__new()__
、__init()__
的参数,从上面的代码可以看出,cls
就是由metaclass type
生成的class C
,而self
就是class C
生成的对象,在两次调用中,这个对象分别就是c1 = C(1, 2, a=3) c2 = C(3, 4, b=4)
生成的c1和c2(self
和它们的地址是一致的)__new()__
与__init()__
的参数传递: 当调用对象生成语句c1 = C(1, 2, a=3)
的时候,会携带不定参数(1, 2, a=3)
,这些参数会分别被传递给__new()__
与__init()__
python的单例
可以使用metaclass与__new()__
的特性,构建python的单例模式
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self, *args, **kwargs): passs1 = Singleton()s2 = Singleton()print s1print s2print s1 == s2<__main__.Singleton object at 0x000000000278D080><__main__.Singleton object at 0x000000000278D080>True
通过增加类属性_instance记录单例对象,每次生成对象的时候,如果对象已经生成过,那么就会将第一次生成对象返回,否则才会生成一个对象,从而实现单例模式。从代码的输出也可以看到,多次生成对象,生成的对象总是同一个