首页 > 解决方案 > 创建单例 - 如何保存实例

问题描述

当我在学习如何在 Python 中创建单例时,我们大多数人首先会遇到这种装饰器:

def singleton(class_):
    instances = {}
    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]
    return getinstance

@singleton
class MyClass(BaseClass):
    pass

虽然这个装饰器的工作方式非常直观,但让我想知道的是,当我们在“MyClass”中创建第二个对象时,这个装饰器如何检查是否已经创建了一个对象。

在“单例”的定义中,Python 检查“实例”字典。但是,它是一个局部变量:它不应该在函数运行时被销毁吗?因此,if class_ not in instances条件不应该总是为真吗?

因为我知道这种语法有效,所以我一直按原样使用它,但这让我觉得我还没有完全理解局部变量。

标签: pythonsyntaxsingletondecoratorlocal-variables

解决方案


getinstance是和的闭包。发生的事情不是对对象的引用,而是对函数的引用。在这两个名称超出范围之后,该函数保留对被引用的引用和引用的类的引用。你可以自己看看:instancesclass_MyClassclassgetinstancedictinstancesclass_

>>> type(MyClass)
<class 'function'>
>>> MyClass.__closure__[0]
<cell at 0x107877d38: type object at 0x7fe0dcc264c8>
>>> MyClass.__closure__[1]
<cell at 0x107877d68: dict object at 0x107843ab0>

元组的第一个元素__closure__是对原始类的引用;第二个元素是对实例缓存的引用。


推荐阅读