Python Python 装饰器的变量作用域?

花菜 · May 24, 2021 · Last by 花菜 replied at May 24, 2021 · 3119 hits

装饰器单例

def singleton(cls):
...     instances = {}
...     def getinstance(*args, **kw):
...         if cls not in instances:
...             instances[cls] = cls(*args, **kw)
...         return instances[cls]
...     return getinstance
... 
... @singleton
... class MyClass:
...   pass
... 
c = MyClass()
c1 = MyClass()
type(c)
<class '__main__.MyClass'>
type(c1)
<class '__main__.MyClass'>
id(c)
4358766264
id(c1)
4358766264

singletoninstances已经超出了原函数的作用域,在getinstance函数中还能使用,这是闭包的特性。

instances从字典类型改成None,会出现报错在 local 变量中不到instances

def singleton1(cls):
...     instances = None
...     def getinstance(*args, **kw):
...         if instances is None:
...             instances = cls(*args, **kw)
...         return instances
...     return getinstance
... 
... @singleton1
... class MyClass1:
...   pass
... 
mc1 = MyClass1() 
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 4, in getinstance
UnboundLocalError: local variable 'instances' referenced before assignment

这是为什么?希望大佬说说

共收到 1 条回复 时间 点赞
花菜 #1 · May 24, 2021 Author

感谢微信群各位大佬的回答

总结一下,在闭包中赋值引用类型的变量(例子 1),是不需要加 nolocal,因为对变量的引用不会改变。

(例子 2)对于非引用类型,重新赋值会使变量的引用改变了,相当操作局部变量。需要加上 nolcal 使查找变量的范围往上提,否则会出现找不到变量的错误。

花菜 关闭了讨论 24 May 11:43
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up