new实现单例
new至少要有一个参数cls,代表要实例化的类,new方法负责创建一个实例对象,在对象被创建的时候调用该方法它是一个类方法,new方法负责创建一个实例对象,在对象被创建的时候调用该方法它是一个类方法。new方法在返回一个实例之后,会自动的调用init方法,对实例进行初始化。如果new方法不返回值,或者返回的不是实例,那么它就不会自动的去调用init方法。此参数在实例化时由Python解释器自动提供
代码语言:javascript复制class Singleton(object):
def __new__(cls, *args, **kwargs):
print cls,'xxxx'
if not hasattr(cls,"_instance"):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
元类实现单例
代码语言:javascript复制class Singleton(type):
def __init__(self, *args, **kwargs):
print "__init__"
self.__instance = None
super(Singleton,self).__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
print "__call__"
if self.__instance is None:
self.__instance = super(Singleton,self).__call__(*args, **kwargs)
return self.__instance
class Foo(object):
__metaclass__ = Singleton #在代码执行到这里的时候,元类中的__new__方法和__init__方法其实已经被执行了,而不是在Foo实例化的时候执行。且仅会执行一次。只有再需要对原类做变动时才需要写new方法
为了更好理解上面单例,注意下面两种写法
代码语言:javascript复制class UpperAttrMetaClass(type):
def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
print 'xxxxxxx'
uppercase_attr = {}
for name, value in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = value
else:
uppercase_attr[name] = value
return type.__new__(upperattr_metaclass,future_class_name, future_class_parents, uppercase_attr)#返回一个对象,但同时这个对象是一个类
def __init__(upperattr_metaclass,*args, **kwargs):
print 'init'
upperattr_metaclass.__instance = None
super(UpperAttrMetaClass,upperattr_metaclass).__init__(*args, **kwargs)
def myprint(self, param):
print param,'xxxxx'
def __call__(upperattr_metaclass,*args, **kwargs):
print 'call'
# return upperattr_metaclass
if upperattr_metaclass.__instance is None:
upperattr_metaclass.__instance = super(UpperAttrMetaClass,upperattr_metaclass ).__call__(*args, **kwargs)
return upperattr_metaclass.__instance
下面两种写法 ,
代码语言:javascript复制class Test(object):
__metaclass__ = UpperAttrMetaClass
def __call__(self):
print 'test call'
def __new__(cls, *args, **kwargs):
print 'test new'
return super(Test, cls).__new__(cls,*args, **kwargs)
def __init__(self):
print 'test init'
def myprint(self, param):
print param
aaaa = 22222
代码语言:javascript复制class Test(object):
def __call__(self):
print 'test call'
def myprint(self, param):
print param
aaaa = 22222
Test = UpperAttrMetaClass('Test', (object,), {'myprint':Test().myprint, '__call__':Test().__call__, 'aaaa':Test().aaaa})
这里我们重写了call方法,一开始不理解
代码语言:javascript复制super(UpperAttrMetaClass,upperattr_metaclass ).__call__(*args, **kwargs)
为什么能得到实例,如果我们不重写call方法,Test()将得到实例对象,那么重写的话,重写的格式就是这样,在Test类中重写new,init方法这时被调用。
代码语言:javascript复制t = Test()
t.MYPRINT('xxx')
t2 = Test()
print t
print t2.AAAA
print Test()