单例在python中,闭包不在装饰器内部工作

时间:2012-04-14 23:10:32

标签: python singleton closures decorator

当我在python中观看有关单身人士的一些代码时,我决定自己编写。

这是我的第一个代码:

def singleton(cls):
    instance = False
    def constructor(*args,**kwargs):
        if not instance:
            instance = cls(*args,**kwargs)
        return instance
    return constructor

但是当我测试它时,解释器告诉我'if'必须在if条件下使用之前声明,最后我想出如下:

def singleton(cls):
    cls._instance = False
    def constructor(*args,**kwargs):
        if not cls._instance:
            cls._instance = cls(*args,**kwargs)
        return cls._instance
    return constructor

它按预期工作:

>>> @singleton
>>> class A: pass
>>> a=A()
>>> id(a)
33479456
>>> b=A()
>>> id(b)
33479456

为什么第一个例子的闭包不起作用。

编辑:错误是

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "singleton.py", line 4, in constructor
    if not instance:
UnboundLocalError: local variable 'instance' referenced before assignment

2 个答案:

答案 0 :(得分:3)

您的第一次关闭无效,因为在constructor功能中,您已分配到instance。这使instance成为constructor内的本地名称,并在分配之前访问了该本地名称。

在Python 3中,您可以使用nonlocal instance来声明instance的范围。在Python 2中,您无法根据需要访问该instance外部名称。

此外,单身人士在Python中并不常见。为什么不一次实例化你的课程?为什么试图欺骗Python的行为与它不同?或者创建一个工厂函数来生成要使用的实例?

答案 1 :(得分:0)

Closure-variables在Python中是只读的,因此当您尝试将值赋给实例时,Python无法执行此操作。错误消息有点误导,因为声明了实例,它只是在闭包内部不可写。