Python中nonlocal关键字的作用及变量ID变化等疑问
Python中nonlocal关键字的作用及机制解析
一、nonlocal的核心作用
nonlocal关键字的核心用途是让嵌套的内层函数能够修改外层函数(非全局)作用域中的变量。如果不用nonlocal,内层函数里直接给外层同名变量赋值时,Python会默认把它当成一个新的局部变量,不会影响外层的变量;而加了nonlocal声明后,内层函数就会绑定到外层最近的那个同名变量,获得修改它的权限。
二、解析你的代码现象
先看你写的示例代码:
# Outer fuction def func1(): var1 = 2 print("---ID of var1 in func1---") print(id(var1)) print(locals()) # Inner function def func2(): nonlocal var1 var1 += 1 print("---ID of var1 in func2---") print(id(var1)) print(locals()) # Call inner function func2() print("---ID of var1 in func1 after func2 execution---") print(id(var1)) print(locals()) func1()
1. 为什么var1的ID会变化?
这和Python的不可变类型特性有关:整数是不可变对象,一旦创建就不能修改其值。var1 += 1这句代码的实际逻辑是:
- 先取出当前var1指向的整数对象(值为2)
- 计算
2 + 1得到一个全新的整数对象(值为3) - 让var1这个引用重新指向这个新对象
所以前后的ID自然不一样。如果换成可变类型(比如列表),修改内部元素而不是重新赋值,ID就不会变:
def func1(): var1 = [2] print("ID in func1:", id(var1)) def func2(): nonlocal var1 var1.append(1) # 修改列表内部,不改变引用 print("ID in func2:", id(var1)) func2() print("ID after func2:", id(var1)) func1() # 输出的三个ID完全相同
2. 变量是否同时存在于多个命名空间?
不是的。func2的locals()里出现var1,是因为nonlocal声明让func2的局部作用域绑定了对func1中var1的引用,而不是创建了一个新变量。
本质上,func1里的var1是外层作用域的变量,nonlocal让func2可以直接操作这个变量:当你在func2里修改var1时,其实是直接修改func1作用域里的那个变量的引用(因为不可变类型重新赋值)。func2的locals()显示var1,只是因为这个变量在func2的作用域里可见并可操作,所以会被包含在它的局部字典中,但变量的“归属”还是func1的外层作用域,并没有同时存在多个独立的var1变量。
内容的提问来源于stack exchange,提问作者Aleksei Danli
相关产品推荐
相关产品推荐

