0.背景
每种语言都有各自的单例模式,比如JAVA经典的懒汉,饿汉模式,或是double-check线程安全的单例模式等等。这里讲述两个比较好用的单例的python写法。
1. 第一种:实现__new__方法,并将一个类的实例绑定到类变量_instance上
如果对__new__不熟悉的,可以参考文章《详解Python中的__init__和__new__》,简言之,__new__是一个类静态方法,创建这个类实例的方法,而__init__是在类实例创建之后调用。所以这种单例方法与经典的类似。代码如下:
# -*- coding: utf-8 -*-
class Singleton(object):
#重写 __new__方法
def __new__(cls, *args):
if not hasattr(cls, '_instance'): #是否存在__instance变量
cls._instance = super(Singleton, cls).__new__(cls, *args) # 如果不存在,则新建一个类实例
return cls._instance
@classmethod
def get_instance(cls, *args):
return cls.__new__(cls, *args)
class MyClass(Singleton): #如果想要令MyClass变为实例,则需继承即可
pass
if __name__ == '__main__':
one = MyClass.get_instance()
two = MyClass.get_instance()
print str(one == two)
第二种:写一个装饰器函数,装饰需要单例的类,并将该类的单实例缓存下来
当调用单例类的的构造函数时,会先调用singleton函数,检查该类是否已经存在一个实例了。这种不仅是单例的一种方式,也是做缓存的一种方式,能够加快获取速度,非常经典。
# -*- coding: utf-8 -*-
from functools import wraps
def singleton(cls, *args, **kw): #装饰器函数
instances = {} # 所有的单例的实例都在这个instances字典中
@wraps(cls)
def _singleton():
if cls not in instances: # 当cls不在instances中
instances[cls] = cls(*args, **kw) # 则新建一个实例
return instances[cls] # 然后从instances中取
return _singleton
@singleton
class MyClass2(object): # 如果想要令MyClass2变为实例,则需在该类写上 “@singleton”即可,更加读者一看就明了此类是一个实例类
def __init__(self): #只有 cls不在instances中,才会调用此__init__方法
pass
if __name__ == '__main__':
one = MyClass2()
two = MyClass2()
print str(one == two)
这两种单例方式,都非常经典,第一种更容易理解,第二种更加的pythonic,按个人喜欢使用。