Python 单例模式
程序员文章站
2024-03-08 10:19:40
...
Python 单例模式
了解Python这么久,一直没有好好去了解一下到底什么是单例模式,今天便去深入探究一下…
单例模式,其实是一种非常简单的设计模式,简单到其实一句话就可以解释:–确保某个类只有一个实例存在。
那么,在什么情况下需要用到单例模式呢?我们就来了解一下单例模式的应用场景:
- Python的logger就是一个单例模式,用以日志记录;
- Windows的资源管理器是一个单例模式;
- 线程池,数据库连接池等资源池一般也用单例模式;
- 网站计数器等
从这些应用场景我们可以看出单例模式一般应用于:
- 资源共享的情况下,避免由于资源操作时导致的性能或损耗等,比如:日志文件。
- 控制资源的情况下,方便资源之间的互相通信,比如:线程池、数据库连接池;网站计数器。
好的,了解完这些以后,我们来看一下Python中单例模式的实现形式。
-
使用模块
Python的模块就是天然的单例模式,因为模块在第一次导入的时候,会生成.pyc文件,第二次导入时会直接加载.pyc文件,而不会再次执行模块代码。
#singleton_test.py
class Singleton_test(object):
def foo(self):
pass
singleton_test = Singleton_test()
#调用
from singleton_test import singleton_test
singleton_test.foo()
-
new
使用 new 来控制实例的创建过程
#创建一个类做对比
class Person:
pass
people1 = Person()
people2 = Person()
print(id(people1),id(people2))
>>>1836223142992 1836223143160
#通过地址可以发现创建了两个实例
#单例
class Person(object):
_instance = None
def __new__(cls, *args, **kwargs):
#r如果_instance为空证明是第一次创建实例
if cls._instance == None:
#通过父类__new__创建实例
cls._instance == object.__new__(cls)
return cls._instance
else:
#直接返回上一个对象的引用
return cls._instance
people1 = Person()
print(id(people1))
people2 = Person()
print(id(people2))
>>>140716233512976
>>>140716233512976
#创建了一个实例 people1 is people2 为 True
- 使用装饰器
装饰器可以动态的修改一个类或函数的功能,所以可以通过装饰器使某个类只能生成一个实例。
from functools import wraps
#装饰器
def person(cls):
#创建一个存放类
instance = {}
@wraps(cls)
#内部函数
def getinstance(*args,**kwargs):
#判断某个类是否存在
if cls not in instance:
#cls 作为key,cls(*args,**kwargs)作为value
instance[cls] = cls(*args,**kwargs)
return instance[cls]
return getinstance
@person
class Person(object):
pass
people1 = Person()
print(id(people1))
people2 = Person()
print(id(people2))
print(people2 is people1)
>>>2888114661584
>>>2888114661584
>>>True
-
使用元类(metaclass)
元类可以控制类的创建过程:- 拦截类的创建;
- 修改类的定义;
- 返回修改后的类
#定义单例类,因为继承type所以这个类也是元类
class Person(type):
_instance = {}
#重写call方法
def __call__(cls, *args, **kwargs):
if cls not in cls._instance:
cls._instance[cls] = super(Person, cls).__call__(*args, **kwargs)
return cls._instance[cls]
#使用Person元类创建一个类,Son这个类就是Person的实例
class Son(metaclass=Person):
pass
son1 = Son()
print(id(son1))
son2 = Son()
print(id(son2))
print(son2 is son1)
>>>1476982381816
>>>1476982381816
>>>True
上一篇: java解析excel文件的方法
下一篇: 全志A64内核编译一些错误解决方法