python3单例模式_python3实现单例模式

单例模式指确保某个类在整个系统中只存在一个实例的一种设计模式

使用单例模式的好处:

1、每个实例都会占用一定的内存资源,且初始化实例时会影响运行性能,所以当整个系统只需一个实例时,使用单例模式不仅可减少资源占用,而且因为只初始化一次,还可以加快运行性能。例如当程序通过一个类来读取配置信息,而程序多个地方需要使用配置信息,这时整个程序运行过程中只需一个实例对象即可,可减少占用内存资源,同时还可以保证程序在多处地方获取的配置信息一致。

2、使用单例模式可进行同步控制,计数器同步、程序多处读取配置信息这些情景下若只存在一个实例,即可保证一致性。

在python中,一般可使用一下4种方式实现单例模式:

1、通过模块调用

2、使用__new__方法

3、使用装饰器

4、使用元类(metaclass)

一、通过模块调用做法:将需要实现单例的类写在模块文件中,然后通过import引入该模块,即可得到单例对象。

原理:在python3中,首次导入模块文件时,会在程序目录下的__pycache__目录中生成pyc文件,之后再导入时,将直接加载pyc文件。从而实现单例。

实现代码:module_demo.py class singleton_cal: def foo(self): pass export_singleton = singleton_cal()

use_module.py from module_demo import export_singleton a = export_singleton from module_demo import export_singleton b = export_singleton print(a == b) print(id(a) == id(b))

可发现,多次调用/导入模块,使用的都是同一个实例对象

二、使用__new__方法_new__与_init__的区别:

__new\:创建实例对象时调用的构造方法

_init_:初始化方法,用于设置实例的相关属性

python创建实例时,会先调用__new__构造方法,然后使用__init__进行实例初始化。

我们可以通过__new__来影响实例的创建,从而实现单例。

实现代码:use_new.pyclass Singleton(object):

__instance = None

def __new__(cls,*args,**kwargs):

if not cls. __instance:

cls.__instance = super().__new__(cls,*args,**kwargs)

return cls.__instance

a = Singleton()

b = Singleton()

print(a == b)

print(id(a) == id(b))

上面代码中,声明了一个私有类变量__instance,当__instance不为None时,代表系统中已有实例,直接返回该实例,若__instance为None时,表示系统中还没有该类实例,则创建新实例并返回。

三、使用装饰器use_decorator.pyfrom 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 singleCls(object):

def foo(self):

pass

a = singleCls()

b = singleCls()

print(a == b)

print(id(a) == id(b))

只有当第一次调用singleCls时,装饰器才会从instances={}开始执行,之后调用singleCls时,都只执行getinstance函数,这是装饰器的特性,利用这个特性,当我们多次调用singleCls时,在getinstance函数中判断该类是否存在于instances字典中,若不存在,则创建该类实例并加入instances字典中,并返回字典中该类的实例;若存在,则直接返回字典中该类的实例。可利用该装饰器为多个类实现单例。

四、使用元类(metaclass)

元类创建了所有的类型对象(包括object对象),系统默认的元类是type。

实例,类,父类,元类的关系可表示为下图

元类中的__call方法,在已该类为元类的类创建实例时调用,例如:类A以类B为元类,当A创建实例时,B中的\call将会被调用。利用\call__可实现对实例创建的控制。

实现代码:use_metaclass.pyclass SingletonMeta(type):

__instance = None

def __call__(cls,*args,**kwargs):

if not cls.__instance:

cls.__instance = type.__call__(cls,*args,**kwargs)

return cls.__instance

class myclass(metaclass = SingletonMeta):

def foo(self):

pass

a = myclass()

b = myclass()

print(a==b)

print(id(a)==id(b))

自定义元类时,通常继承自type,声明一个私有类变量__instance保存类实例,当__instance为None时,调用type的__call__方法为类创建实例,保存到__instance并返回;若__instance不为None,则直接返回__instance,不重新创建实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值