Python 单例模式

Python 单例模式

了解Python这么久,一直没有好好去了解一下到底什么是单例模式,今天便去深入探究一下…

单例模式,其实是一种非常简单的设计模式,简单到其实一句话就可以解释:–确保某个类只有一个实例存在。

那么,在什么情况下需要用到单例模式呢?我们就来了解一下单例模式的应用场景:

  • Python的logger就是一个单例模式,用以日志记录;
  • Windows的资源管理器是一个单例模式;
  • 线程池,数据库连接池等资源池一般也用单例模式;
  • 网站计数器等

从这些应用场景我们可以看出单例模式一般应用于:

  • 资源共享的情况下,避免由于资源操作时导致的性能或损耗等,比如:日志文件。
  • 控制资源的情况下,方便资源之间的互相通信,比如:线程池、数据库连接池;网站计数器。

好的,了解完这些以后,我们来看一下Python中单例模式的实现形式。

  1. 使用模块

    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()
  1. 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):
        #如果_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
  1. 使用装饰器
    装饰器可以动态的修改一个类或函数的功能,所以可以通过装饰器使某个类只能生成一个实例。
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值