python中的单例,闭包在decorator中不起作用
当我在看一些关于python中singleton的代码时,我决定自己写 这是我的第一个代码:python中的单例,闭包在decorator中不起作用,python,singleton,closures,decorator,Python,Singleton,Closures,Decorator,当我在看一些关于python中singleton的代码时,我决定自己写 这是我的第一个代码: def singleton(cls): instance = False def constructor(*args,**kwargs): if not instance: instance = cls(*args,**kwargs) return instance return constructor 但是当我测试它时,
def singleton(cls):
instance = False
def constructor(*args,**kwargs):
if not instance:
instance = cls(*args,**kwargs)
return instance
return constructor
但是当我测试它时,解释器告诉我在if条件下使用之前必须声明“instance”,最后我决定按如下方式执行:
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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
构造函数中第4行的文件“singleton.py”
如果没有,请举例说明:
UnboundLocalError:赋值前引用的局部变量“实例”
在Python中,闭包变量是只读的,所以当您试图将值分配给实例时,Python无法做到这一点。错误消息有点误导性,因为声明了实例,它只是在闭包中不可写。您的第一个闭包不起作用,因为在构造函数中,您分配给实例
。这使得实例
成为构造函数
中的本地名称,并且您在将该本地名称分配给之前访问了该名称
在Python3中,可以使用非本地实例
来声明实例
的范围。在Python2中,您不能按照自己的意愿访问外部实例名称
此外,单例在Python中是不常见的。为什么不只实例化一次类呢?为什么要试图欺骗Python,使其行为与实际不同?或者创建一个工厂函数来生成要使用的实例?啊,刚刚看到了您的更新。事实证明,错误消息一点也不误导:-)闭包变量不是只读的,正如OP所发现的那样,它们很难修改。我真的认为它们不可能修改吗?在Python2中,是否有可能以某种尴尬的方式为闭包变量指定一个新值?@AHM您将修改一个对象和指向一个名称混为一谈。他可以在非本地范围内执行instance=[]
,然后在本地范围内执行instance.append(1)
,对其进行修改,而不会出现任何问题。它实际上是把名字指向另一个不同的物体。好的,是的。我意识到了这一点,只是没有正确地表达自己。有一段时间,我认为有一种神秘的方法可以从Python 2中的Python 3中获取非本地关键字之类的功能。一种解决方法是使用object属性将值写入或不使用Singleton!:)另见和