Python中__closure__相关:wrapper内为何无法使用klass变量?
为什么在wrapper函数中使用
klass变量会触发UnboundLocalError? 这个问题的核心是Python的变量作用域规则,我来给你拆解清楚:
1. Python如何判定变量的作用域
当你在一个函数内部对某个变量进行赋值操作时,Python会默认把这个变量标记为该函数的局部变量——哪怕外层作用域已经存在同名变量。这时候,函数内部所有对该变量的引用,都会优先指向这个局部变量,而不是外层的变量。
2. 第一段代码的问题分析
看你第一段代码里的wrapper函数:
def wrapper(*args, **kwargs): if not klass: # 这里引用了klass klass = type(obj) # 这里对klass进行了赋值 return self.func(klass, *args, **kwargs)
因为wrapper里有klass = type(obj)这个赋值操作,Python会把klass认定为wrapper的局部变量。但你在赋值之前,先执行了if not klass:——这时候局部的klass还没有被定义(没有赋值),自然就抛出了UnboundLocalError: local variable 'klass' referenced before assignment。
3. 第二段代码为什么能正常运行
再看修改后的代码:
def __get__(self, obj, klass=None): if not klass: klass = type(obj) # 赋值操作在wrapper外面的__get__作用域 def wrapper(*args, **kwargs): return self.func(klass, *args, **kwargs) # 这里只是引用klass,没有赋值 return wrapper
这里klass的赋值操作是在__get__方法的作用域里完成的,wrapper函数内部只是引用这个变量,没有任何赋值操作。根据Python的作用域规则,当函数内部没有对变量赋值时,会向上查找外层作用域的同名变量,所以wrapper会正确使用__get__里已经赋值好的klass,不会出现错误。
一个简化的例子辅助理解
你可以试试运行这段代码,会触发和你第一段代码一样的错误:
outer_var = 10 def outer(): def inner(): if outer_var > 5: outer_var = 20 # 赋值操作让outer_var变成inner的局部变量 print(outer_var) inner() outer()
而如果把赋值移到inner外面,就能正常运行:
outer_var = 10 def outer(): if outer_var > 5: outer_var = 20 def inner(): print(outer_var) inner() outer()
内容的提问来源于stack exchange,提问作者Tide
相关产品推荐
相关产品推荐

