首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

python单例实现及注意事项

什么是单例

单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

Python的单例实现有三种方式,最不同的就是通过 __new__ 魔法方法来实现,这种方式类似与PHP中的单例的实现。除此之外还可以通过装饰器以及元类实现单例

1. 通过___new___实现单例

class Instance():

_instance = None

def __init__(self):

print('初始化')

def __new__(cls):

if not cls._instance:

cls._instance = super().__new__(cls)

return cls._instance

a = Instance()

c = Instance()

print(id(a))

print(id(c))

代码执行打印结果:

从打印的结果可以看出,这种方式实现的单例会调用__init__魔术方法多次,但是最总实例化的对象的指针id是同一个,表明他们指向同一个对象。

2. 通过装饰器实现单例(推荐)

既然是通过装饰器实现单例,那我们就必须先定义一个装饰器函数:

def singleton(cls):

instances = {}

def getinstance(*args, **kwargs):

if cls not in instances:

instances[cls] = cls(*args, **kwargs)

return instances[cls]

return getinstance

这个装饰器,我们可以把它封装到某个公共文件中,以提高单例装饰器的复用性。

接着就可以在任意类上面使用装饰器来表明这是一个单例即可,具体代码方式如下:

@singleton

class MyClass:

def __init__(self):

print('初始化')

a = MyClass()

b = MyClass()

print(id(a))

print(id(b))

上述代码执行打印结果如下:

从上面的结果就可以看出,实例化的对象a及b的内存地址id是相同的,表示他们是同一个对象。此外,这种方式实现的单例只会调用一次 __init__ 魔术方法,这是与第一种方式实现的单例完全不同。

3. 通过元类实现单例

元类方式结合了第一种和装饰器的两种方式。只不过装饰器变成了一个基类,具体代码如下:

class Singleton(type):

_instances = {}

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

if cls not in cls._instances:

cls._instances[cls] = super().__call__(*args, **kwargs)

return cls._instances[cls]

关于这个基类,我们可以和装饰器一样封装到一个公共的文件中。

子类如果想要实现单例,就必须继承 Singleton 这个基类,并且是以元类的方式继承。具体实现方式如下:

class MyClass(metaclass=Singleton):

def __init__(self):

print('初始化')

a = MyClass()

b = MyClass()

print(id(a))

print(id(b))

上述代码执行的结果如下:

执行结果和装饰器的一致,没有什么区别。但是日常工作我个人建议大家还是使用装饰器来实现单例,毕竟自己实现的类可能需要继承其他类,如果以元类的方式实现,就会显得代码比较臃肿,我个人不太喜欢。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OiIggb21LRySocoGM4f6zHTA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券