• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

技术篇–每日一篇0x4-python单例模式

Python admin 1年前 (2018-03-21) 621次浏览 0个评论 扫描二维码

方法一:使用装饰器

装饰器维护一个字典对象 instances,缓存了所有单例类,只要单例不存在则创建,已经存在直接返回该实例对象。

def singleton(cls):
    instances = {}
    #看到有人在这有疑问,为啥 instances 会有缓存功能?函数调用结束时所有变量不是释放?
    #正解:只有程序运行结束时退出才会释放所有资源,函数运行时会创建一个函数作用域,instances 就是在当前函数
    #singleton 作用域内,此处调用了两次,因此在第二次判断的时候 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

foo1 = Foo()
foo2 = Foo()

print foo1 is foo2

方法二:使用基类

__new__是真正创建实例对象的方法,所以重写基类的__new__方法,以此来保证创建对象的时候只生成一个实例

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance


class Foo(Singleton):
    pass

foo1 = Foo()
foo2 = Foo()

print foo1 is foo2  # True

方法三:使用元类

元类(参考:深刻理解 Python 中的元类)是用于创建类对象的类,类对象创建实例对象时一定会调用__call__方法,因此在调用__call__时候保证始终只创建一个实例即可,type是 python 中的一个元类。

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance


class Foo(object):
    __metaclass__ = Singleton


foo1 = Foo()
foo2 = Foo()

print foo1 is foo2  # True

转载自 https://foofish.net/python_singleton.html 并且适当修改注释


Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明技术篇–每日一篇 0x4-python 单例模式
喜欢 (0)
admin
关于作者:
互联网行业码农一枚/业余铲屎官/数码影音爱好者/二次元

您必须 登录 才能发表评论!