详解python单例模式与metaclass
单例模式的实现方式 将类实例绑定到类变量上 class Singleton(object): _instance = None def __new__(cls,*args): if not isinstance(cls._instance,cls): cls._instance = super(Singleton,cls).__new__(cls,*args) return cls._instance 但是子类在继承后可以重写__new__以失去单例特性 class D(Singleton): def __new__(cls,*args): return super(D,*args) 使用装饰器实现 def singleton(_cls): inst = {} def getinstance(*args,**kwargs): if _cls not in inst: inst[_cls] = _cls(*args,**kwargs) return inst[_cls] return getinstance @singleton class MyClass(object): pass 问题是这样装饰以后返回的不是类而是函数,当然你可以singleton里定义一个类来解决问题,但这样就显得很麻烦了 使用__metaclass__,这个方式最推荐 class Singleton(type): _inst = {} def __call__(cls,*args,**kwargs): if cls not in cls._inst: cls._inst[cls] = super(Singleton,cls).__call__(*args) return cls._inst[cls] class MyClass(object): __metaclass__ = Singleton metaclass 元类就是用来创建类的东西,可以简单把元类称为“类工厂”,类是元类的实例。type就是Python的内建元类,type也是自己的元类,任何一个类 >>> type(MyClass) type >>> type(type) type python在创建类MyClass的过程中,会在类的定义中寻找__metaclass__,如果存在则用其创建类MyClass,否则使用内建的type来创建类。对于类有继承的情况,如果当前类没有找到,会继续在父类中寻找__metaclass__,直到所有父类中都没有找到才使用type创建类。 查看type的定义, type(object) -> the object's type 所以利用type定义一个类的元类,可以用函数返回一个上面第二种定义的对象,也可以继承type并重写其中的方法。 直接使用type生成的对象作为元类,函数作用是使属性变为大写 def update_(name,dct): attrs = ((name,value) for name,value in dct.items() if not name.startswith('__')) uppercase_attr = {name.upper(): value for name,value in attrs} return type(name,uppercase_attr) class Singleton(object): __metaclass__ = update_ abc = 2 d = Singleton() print d.ABC # 2 上一节中,单例模式元类实现用的是类继承方式,而对于第一种__new__的方式,本质上调用的是type.__new__,不过使用super能使继承更清晰一些并避免一些问题 这里简单说明一下,__new__是在__init__前调用的方法,会创建对象并返回,而__init__则是用传入的参数将对象初始化。看一下type中这两者以及__call__的实现 def __init__(cls,what,bases=None,dict=None): # known special case of type.__init__ """ type(object) -> the object's type type(name,dict) -> a new type # (copied from class doc) """ pass @staticmethod # known case of __new__ def __new__(S,*more): # real signature unknown; restored from __doc__ """ T.__new__(S,...) -> a new object with type S,a subtype of T """ pass def __call__(self,*more): # real signature unknown; restored from __doc__ """ x.__call__(...) <==> x(...) """ pass 前面提到类相当于元类的实例化,再联系创建单例模式时使用的函数,用的是__call__,其实用三种magic method中任何一种都是可以的,来看一下使用元类时各方法的调用情况 class Basic(type): def __new__(cls,name,newattrs): print "new: %r %r %r %r" % (cls,newattrs) return super(Basic,newattrs) def __call__(self,*args): print "call: %r %r" % (self,args) return super(Basic,self).__call__(*args) def __init__(cls,newattrs): print "init: %r %r %r %r" % (cls,newattrs) super(Basic,cls).__init__(name,dict) class Foo: __metaclass__ = Basic def __init__(self,**kw): print "init: %r %r %r" % (self,args,kw) a = Foo('a') b = Foo('b') 结果 new: <class '__main__.Basic'> 'Foo' () {'__module__': '__main__','__metaclass__': <class '__main__.Basic'>,'__init__': <function init at 0x106fd5320>} init: <class '__main__.Foo'> 'Foo' () {'__module__': '__main__','__init__': <function init at 0x106fd5320>} call: <class '__main__.Foo'> ('a',) init: <__main__.Foo object at 0x106fee990> ('a',) {} call: <class '__main__.Foo'> ('b',) init: <__main__.Foo object at 0x106feea50> ('b',) {} 元类的__init__和__new__只在创建类Foo调用了一次,而创建Foo的实例时,每次都会调用元类的__call__方法 以上就是本文的全部内容,对python单例模式与metaclass进行了描述,希望对大家的学习有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |