碰到一个 classmethod
中闭包的局部变量问题, 很有趣。
先来看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from functools import wrapsclass A () : ctx = {} @classmethod def cm_decorator (cls, value) : def inner (fn) : print("locals: " , locals()) @wraps(fn) def wrapper (*args, **kwargs) : kwargs["value" ] = value return fn(*args, **kwargs) return wrapper return inner @A.cm_decorator("1") def test (*args, **kwargs) : print(args, kwargs) test()
执行结果:
1 2 3 > python3 test1.py locals: {'fn' : <function test at 0x103320598>, 'value' : '1' } () {'value' : '1' }
OK, 意料之中, 如果把 wrapper
中的 kwargs["value"] = value
去掉会是怎样的呢? 去掉后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from functools import wrapsclass A () : ctx = {} @classmethod def cm_decorator (cls, value) : def inner (fn) : print("locals: " , locals()) @wraps(fn) def wrapper (*args, **kwargs) : return fn(*args, **kwargs) return wrapper return inner @A.cm_decorator("1") def test (*args, **kwargs) : print(args, kwargs) test()
运行结果:
1 2 3 > python3 test2.py locals: {'fn' : <function test at 0x103c05598>} () {}
一眼就能发现, 之前的 value
没有了,
TODO 再看下面这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from functools import wrapsclass A () : ctx = {} @classmethod def cm_decorator (cls, value) : def inner (fn) : print("locals: " , locals()) @wraps(fn) def wrapper (*args, **kwargs) : ctx = cls.ctx if ctx.get("value" ): value = ctx["value" ] else : ctx["value" ] = value return fn(*args, **kwargs) return wrapper return inner @A.cm_decorator("1") def test (*args, **kwargs) : print(args, kwargs) test()
输出:
1 2 3 4 5 6 7 8 > python3 test2.py locals: {'fn' : <function test at 0x103405598>, 'cls' : <class '__main__.A' >} Traceback (most recent call last): File "/Users/heaven/test/2.py" , line 27, in <module> test () File "/Users/heaven/test/2.py" , line 17, in wrapper kwargs["value" ] = value UnboundLocalError: local variable 'value' referenced before assignment
Related Issues not found
Please contact @heavenlwf to initialize the comment