Python 中类的单例实现
单例设计模式是应用开发过程中最简单的创建型的设计模式。类的单例指的是一个类只有一个实例,可以提供一个全局的访问节点,常常用于日志记录,数据库操作等等,它们的特点是资源一般只有一个,单一的访问实例可以避免同一资源的冲突。
Python中典型的单例的实现方式
#!/usr/bin/env python3
#coding:utf8
class Singleton(object):
def __new__(cls, *arg, **kw):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
def __init__(self, v):
self.v = v
print("v=", self.v)
if __name__ == "__main__":
s1 = Singleton(3)
s2 = Singleton(2)
print(s1 == s2)
print("s1.v=", s1.v)
上述代码通过重写__new__
方法实现了类的单一性,__new__
是python中一个特别的魔法方法,它的一个参数cls
代表要初始化的类,在类初始化的时候解释器自动提供,它直接返回一个初始化好的类,在上面的例子中,首先会去查找相应的类的实例_instance
是否存在,如果不存在就调用类的初始化方法生成一个新的类,super方法会返回类的一个类的定义,通过调用__new__
方法实现类的例化,例化完成后将实例保存在_instance
中,从而实现类的单一实例。
通过元类的方式实现
元类是一个类的类,也就是说类实际上是元类的实例,通过元类,我们可以实现自定义类型的定义,比如对于MyClass
的类,我们可以定义一个MyKls
的元类来控制MyClass
的行为。在python中创建类的对象的时候会调用__call__
方法实现类的初始化,因此可以通过定义__call__
方法实现对类初始化方式的控制。
class MetaSingleton(type):
_instances = {}
def __call__(cls, *args, **kw):
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, \
cls).__call__(*args, **kw)
print("Create new class")
return cls._instances[cls]
class Logger(metaclass=MetaSingleton):
def __init__(self, src):
self.src = src
print("Logger init called:", self.src)
这也是一种实现类的单例的方式,不过这种方式和之前的方式有一些差别,通过元类__call__
方法实现的单例,会直接劫持__new__
和__init__
方法,也就是类只有第一次初始化的时候会调用__init__
方法,而第一种方法实际每次初始化的时候还会重新调用新的init方法,这就是两者之前的差异,不过一般在使用单例模式时候会显式的定义一个init方法,而不用自带的__init__
方法,防止对内部的全局变量意外的修改。
装饰函数的实现方式
与元类重写__call__
的实现方式类似,实际还有一种更为简洁的单例的实现方式,就是采用装饰函数的实现方式:
def single_instance(cls, *args, **kw):
"""
A decorator to guaranteed a class only init once
"""
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
通过元类的定义我们知道类的实例化就是相当于对类的一个调用,所以可以用一个装饰函数对这个调用加以修改从而实现对类的控制。上面的这种方式就是对类在调用进行修改,从而实现类只有一个实例的效果。
最后更新于 2017-12-04 14:27:58 并被添加「」标签,已有 2119 位童鞋阅读过。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。