“nonlocal”关键字与变量有什么关系?

What does exactly "nonlocal" keyword do with a variable?

提问人:Aleksei Danli 提问时间:11/15/2022 更新时间:11/15/2022 访问量:121

问:

这是我为尝试理解“非本地”关键字的机制而制作的示例代码。 `

# 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()

` 我们在 func1() 命名空间中定义 var1。在 func2() 中调用 'nonlocal' 后,var1 会更改其 id 并开始出现在 func2() 的本地字典中。执行 func2() 后,它仍然存在于 func1() 的本地字典中。

这是否意味着一个变量可以同时存在于多个命名空间中?为什么 id(var1) 发生了变化?

我预计 var1 只会出现在 func1() 的本地字典中,而“nonlocal”关键字只会提供在 func2() 中更改它的可能性。

内存管理 范围 命名空间 python-nonlocal

评论

0赞 Joran Beasley 11/15/2022
整数是不可变的,任何赋值都将导致一个新的 ID ...非局部意味着它不在局部范围内,也不在全局范围内(尽管非局部可能会努力找到全局范围......它在封闭范围中查找变量
0赞 0x5961736972 11/15/2022
Q.这是否意味着一个变量可以同时存在于多个命名空间中?一个。非局部语句使列出的标识符引用最近封闭范围(不包括全局变量)中先前绑定的变量。Q.为什么 id(var1) 发生了变化?一个。由于整数是不可变的,因此每次重新分配它时,它都会生成一个新的 id。
0赞 juanpa.arrivillaga 11/15/2022
id在这里真的一点都无关紧要。对象的身份是否更改与此类范围问题无关
0赞 juanpa.arrivillaga 11/15/2022
请注意,它不返回本地命名空间,确切地说,它更像是一个包含本地和非本地变量的字典。但这个变量实际上存在于闭包中。locals()print(func1.__closure__)
2赞 juanpa.arrivillaga 11/15/2022
@JoranBeasley不,不是任何作业,我甚至不会说大多数作业。在给定不变性的情况下,你唯一可以说的是,如果两个整数对象具有不同的值,那么它们就具有不同的恒等式

答:

1赞 user2357112 11/15/2022 #1

locals()是一个非常奇怪的函数,它不会做任何人合理期望它做的事情,有一些奇怪的未记录的怪癖。这个特殊的怪癖恰好被记录下来,但它仍然很奇怪。一般来说,除非你真的别无选择,否则你不应该使用。locals()

返回的 dict 是locals()

  • 通常不是实际的局部变量命名空间,并且
  • 可能包含实际上不属于当前局部变量命名空间的变量

在函数内部调用时,返回的字典将包含非局部变量locals()

当在功能块中调用自由变量时,locals() 会返回自由变量,但不会在类块中调用。

这并不意味着该变量实际上同时存在于多个命名空间中。意思是很奇怪。locals()


至于 ID 更改,ID 与对象相关联,而不是与变量相关联。后面引用的整数对象是与前一个整数对象具有不同 ID 的不同对象。var1var1 += 1