单例模式是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,当你希望在整个系统中,某个类只出现一个实例时,单例对象就能排上用场
在python中,我们可以用多种方法来实现单例模式:使用模块、使用__new__、使用装饰器、使用元类(metaclass),共享属性。
使用模块
其实python的模块就是纯天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,而不会再次执行模块代码。因为,我们只需要把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做
# singleTon.py class Animal(object): def eat(self): print('eating...') a=Animal()
将上面的代码保存在文件singleTon.py中,然后这样使用:
# my_funcs.py from singleTon import a a.eat()
使用__new__
为了使类只能出现一个实例,我们使用__new__来控制实例的创建过程
# 单例模式基于__new__ class Animal(object): _instance=None def __new__(cls,*args,**kw): if not cls._instance: cls._instance=super(Animal,cls).__new__(cls,*args,**kw) #构建一个实例对象 return cls._instance # 测试 dog=Animal() cat=Animal() print(id(dog)) print(id(cat))
在上面的代码中,我们将类的实例和一个类变量_instance关联起来,如果cls._instance为None则创建实例,否则直接返回cls._instance
使用装饰器
装饰器可以动态的修改一个类或函数的功能。这里我们可以使用装饰器来装饰某个类,使其只能生成一个实例
# 单例模式基于装饰器 from functools import wraps def singleton(cls): instances={} @wraps(cls) def getinstance(*args,**kwargs): if cls not in instances: instances[cls]=cls(*args,**kwargs) return instances[cls] return getinstance @singleton class Animal(object): def eat(self): print('eating...')
使用metaclass
元类可以控制类的创建过程,它主要完成拦截类的创建、修改类的定义,然后返回修改后的类
# 单例模式基于元类 class Singleton(type): _instance={} def __call__(cls,*args,**kwargs): if cls not in cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance[cls] class Myclass(metaclass=Singleton): pass
共享属性
创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法
class Singleton(object): _state = {} def __new__(cls, *args, **kwargs): obj = super(Singleton,cls).__new__(cls) obj.__dict__ = cls._state return obj class Myclass(Singleton): pass