Python闭包变量问题:解决内部函数变量引用报错及外部赋值方法
问题解答
问题1:如何从函数外部为函数内部的变量赋值?
可以通过以下几种方式实现:
- 用可变对象做容器:列表、字典这类可变对象在函数内部修改时,不会被判定为局部变量,外部直接操作该对象就能改变内部关联的值
def foo(): val = ['not changed yet'] def bar(): print(val[0]) bar() return val # 外部修改内部变量 inner_val = foo() inner_val[0] = 'changed from outside' foo() # 输出 'changed from outside' - 返回内部变量的操作接口:在外层函数返回用于读取、修改内部变量的函数,外部通过调用这些接口来操作变量
def foo(): val = 'not changed yet' def get_val(): return val def set_val(new_val): nonlocal val val = new_val def bar(): print(val) bar() return get_val, set_val get_val, set_val = foo() set_val('changed from outside') print(get_val()) # 输出 'changed from outside' - 封装为类属性:用类包裹变量和相关函数,外部通过实例对象直接访问、修改属性
class Foo: def __init__(self): self.val = 'not changed yet' def bar(self): print(self.val) obj = Foo() obj.bar() # 输出 'not changed yet' obj.val = 'changed from outside' obj.bar() # 输出 'changed from outside'
问题2:代码报错原因及解决方法
错误原因
Python的作用域规则是:如果函数内部存在对某个变量的赋值操作,Python会默认把这个变量视为该函数的局部变量。你的代码里,bar函数中有val = 'changed'的赋值语句,所以Python会将val判定为bar的局部变量。但在赋值前先执行了print(val),此时局部变量val还未定义,就会抛出local variable 'val' referenced before assignment错误。
解决方法
使用nonlocal关键字声明val是来自外层嵌套函数(foo)的变量,这样Python会去外层作用域查找该变量,同时允许在bar内修改它:
def foo() -> None: val = 'not change yet' def bar() -> None: nonlocal val # 声明val来自外层嵌套作用域 print(val) val = 'changed' print(val) bar() foo()
执行这段代码会依次输出:
not change yet changed
内容的提问来源于stack exchange,提问作者Zigatronz
相关产品推荐
相关产品推荐

