Python 中的单例模式
Posted 皮皮虾打怪兽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 中的单例模式相关的知识,希望对你有一定的参考价值。
1.什么是单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。单例模式能控制一个类只能产生一个对象。
2.为什么需要单例模式
-
当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
-
当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
3.单例模式应用场景
-
Python的logger就是一个单例模式,用以日志记录
-
Windows的资源管理器是一个单例模式
-
线程池,数据库连接池等资源池一般也用单例模式
-
网站计数器
4.在 Python 中,实现单例模式的四种方式:
-
使用模块
- 使用装饰器(decorator)
-
使用 __new__
-
使用元类
4.1 使用模块
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
如果我们真的想要一个单例类,可以考虑这样做:
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
将上面的代码保存在文件 mysingleton.py 中,然后这样使用:
from mysingleton import my_singleton
my_singleton.foo()
4.2 使用装饰器
装饰器维护一个字典对象instances,缓存了所有单例类,只要单例不存在则创建,已经存在直接返回该实例对象。
我们定义一个装饰器 singleton,它返回了一个内部函数 wrapper,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。
使用装饰器实现单例模式的代码如下:
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo(object):
pass
4.3 使用__new__
__new__方法: __new__()方法用于定义创建对象时执行的操作
object类中的__new__()方法完成对象创建过程中的内存空间申请,对象属性初始化等一系列的操作。__new__是真正创建实例对象时用到的方法,所以重写基类的__new__方法,以此来保证创建对象的时候只生成一个实例。
注意事项:
1.__new__()方法创建对象时自动运行。
2.覆盖object类中的__new__方法后创建对象 将执行覆盖后的方法。
注意事项:
__new__()方法仅仅是python开放出来给用户干预创建对象时的一个操作入口,该方法并不是直接完成分配内存、创建对象的操作,创建对象的操作由python底层统一管理。
使用__new__方法实现单例模式的代码如下:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kw):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
pass
foo1 = MyClass()
foo2 = MyClass()
print(foo1)
print(foo2)
4.4 使用元类
元类是用于创建类对象的类,类对象创建实例对象时一定会调用__call__方法,因此在调用__call__时候保证始终只创建一个实例即可,type是python中的一个元类。
元类(metaclass)可以控制类的创建过程,它主要做三件事:
拦截类的创建
修改类的定义
返回修改后的类
使用元类实现单例模式的代码如下:
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]
# Python2
# class MyClass(object):
# __metaclass__ = Singleton
# Python3
class MyClass(metaclass=Singleton):
pass
foo1 = MyClass()
foo2 = MyClass()
print(foo1)
print(foo2)
以上是关于Python 中的单例模式的主要内容,如果未能解决你的问题,请参考以下文章