有编写代码时,有时为了在模块间传递数据,偷个懒,就使用全局变量。
一时使用一时爽,使用多了,有点担心。如果代码规模增大,并且有多个文件的时候,全局变量就会使代码变得混乱。你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某个地方被做了怎样的操作。
在这种情况下,假如一个类,只生成一个实例,那么无论初始化在哪个模块,整个程序运行期间,只一个类的实例,相当于是全局变量的功效,这就是单例模式,它是众多设计模式的一种。
Python 中实现单例的方法有很多,这里给出几种较为简单的方法。
方法一,自己定义类的创建函数,显式地调用它
In [1]: class SingleDemoClass(object):
...: def __init__(self):
...: pass
...:
...: @classmethod
...: def instance(cls):
...: key = '__instance__'
...: if hasattr(cls, key):
...: return getattr(cls, key)
...: else:
...: instance = SingleDemoClass()
...: setattr(cls, key, instance)
...: return instance
...:
In [2]: a = SingleDemoClass.instance()
In [3]: b = SingleDemoClass.instance()
In [4]: id(a) == id(b)
Out[4]: True
方法二、使用函数装饰器实现单例
In [5]: def singleton(cls):
...: _instance = {}
...:
...: def inner():
...: if cls not in _instance:
...: _instance[cls] = cls()
...: return _instance[cls]
...: return inner
...:
...: @singleton
...: class Cls(object):
...: def __init__(self):
...: pass
...:
...: cls1 = Cls()
...: cls2 = Cls()
...: print(id(cls1) == id(cls2))
True
方法三、使用类装饰器实现单例
In [6]: class Singleton(object):
...: def __init__(self, cls):
...: self._cls = cls
...: self._instance = {}
...: def __call__(self):
...: if self._cls not in self._instance:
...: self._instance[self._cls] = self._cls()
...: return self._instance[self._cls]
...:
...: @Singleton
...: class Cls2(object):
...: def __init__(self):
...: pass
...:
...: cls1 = Cls2()
...: cls2 = Cls2()
...: print(id(cls1) == id(cls2))
True
方法四、使用 new 关键字实现单例模式
In [7]: class Single(object):
...: _instance = None
...: def __new__(cls, *args, **kw):
...: if cls._instance is None:
...: cls._instance = object.__new__(cls, *args, **kw)
...: return cls._instance
...: def __init__(self):
...: pass
...:
...: single1 = Single()
...: single2 = Single()
...: print(id(single1) == id(single2))
True
方法五、使用 metaclass 实现单例模式
In [8]: class Singleton(type):
...: _instances = {}
...: def __call__(cls, *args, **kwargs):
...: if cls not in cls._instances:
...: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
...: return cls._instances[cls]
...:
...: class Cls4(metaclass=Singleton):
...: pass
...:
...: cls1 = Cls4()
...: cls2 = Cls4()
...: print(id(cls1) == id(cls2))
True
以上希望对你有所帮助。
关注公众号 somenzz,和你一起学习 Python。
网友评论