You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:10:24