gpt4 book ai didi

函数内部的 Python 全局关键字可见性

转载 作者:太空宇宙 更新时间:2023-11-03 23:53:31 25 4
gpt4 key购买 nike

当我错误地运行 CODE1 时,我正在检查 global 关键字如何为项目工作,它的工作方式出乎我的意料。 global 关键字在函数中生效,即使它不在执行部分(即在 if 条件不为真时)。

我一直在四处寻找有关 python 中的全局关键字的问题,但找不到对此的答复。我看到了:Python global keyword behavior , global keyword in python , Using global variables in a function

最有趣的是这个(但我不确定):Python global keyword

下面显示了我使用的代码的三个最小可重现示例:

CODE1(带全局关键字):

a = 0
def my_function():
b=2
if b==0:
print("first if")
global a
if b==2:
print("second if")
a = 2
print("func -> a", a)
print("func -> b", b)

if __name__ == '__main__':
my_function()
print("main -> a", a)

结果:

second if
func -> a 2
func -> b 2
main -> a 2

CODE2(没有全局关键字):

a = 0
def my_function():
b=2
if b==0:
print("first if")
if b==2:
print("second if")
a = 2
print("func -> a", a)
print("func -> b", b)

if __name__ == '__main__':
my_function()
print("main -> a", a)

结果:

second if
func -> a 2
func -> b 2
main -> a 0

CODE3(带全局关键字,但反转 if 语句):

a = 0
def my_function():
b=2
if b==2:
print("second if")
a = 2
print("func -> a", a)
print("func -> b", b)
if b==0:
print("first if")
global a

if __name__ == '__main__':
my_function()
print("main -> a", a)

结果:

  File "global_var_test.py", line 18
global a
^
SyntaxError: name 'a' is used prior to global declaration

可以看出,if b==0: 始终为 False 而 if b==2: 始终为 True(打印确认)。我希望 CODE1 给出与 CODE2 相同的结果,因为 global a 在第一个示例中不会被执行,所以它与省略它是一样的。但它给出了一个令人难以置信的结果,其中 global 关键字仍然生效并且全局变量 a 更改为值 2。在此之后,我用 CODE3 进行了测试,认为 global 关键字在所有函数中都是可见的,无论其位置如何,并且那么 CODE3 应该给出与 CODE1 相同的结果。我又错了,它就像要执行 global a 一样(然后在分配之后引发异常)。

然后,我的最后一个问题是:¿ global 关键字是否(可能还有其他关键字,如 nonlocal 等)按照编写的顺序在代码中具有可见性,但独立于什么正在执行?

请帮我澄清一下。

最佳答案

我的 answer on this question可能有助于理解此处的一些技术细节,尽管这是一个略有不同的问题。

简而言之,正如您发现的那样,Python 编译器基本上会根据变量在函数内部的首次使用方式来确定变量的范围; this 不考虑控制语句等细节,所以如果它在看到 global 语句之前碰巧遇到像 a = 2 这样的赋值,它会决定 a 是局部变量。如果你尝试反转代码(你没有给出一个非常像这样的例子)这样编译器恰好看到 global 语句 first 它会起作用(尽管仍然是错误的代码):

a = 0
def my_function():
b=2
if b==2:
print("second if")
global a
print("func -> a", a)
print("func -> b", b)
if b==0:
print("first if")
a = 2

因此,出于实用/技术以及文体目的,您应该始终在函数的开头而不是其他任何地方声明global(或nonlocal)变量。

我不确定这是语言要求还是 CPython 的细节;这将是一个有趣的后续问题。

更新:是的,这是语言规范要求;见https://docs.python.org/3/reference/simple_stmts.html#grammar-token-global-stmt

Names listed in a global statement must not be used in the same code block textually preceding that global statement.

此处textually preceding 只是指代码的文本,而不考虑周围的细节,例如控制语句。这是因为 global 实际上是对 parser 的指令,它根据它第一次看到该变量的使用方式来确定该变量是具有局部绑定(bind)还是全局绑定(bind)。尽管在实现细节方面可能仍然不完全准确;例如CPython builds a symbol table对于代码模块,作为对从解析器返回的 AST 的单独传递。因此,代码的文本顺序也会影响遍历 AST 中节点的顺序。例如。您可以在 the visitor for global statements 中查看错误消息的来源.

关于函数内部的 Python 全局关键字可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58592318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com