gpt4 book ai didi

python - Python 中 `global` 变量的意外行为

转载 作者:行者123 更新时间:2023-11-28 19:34:18 26 4
gpt4 key购买 nike

prev, prev_re = '', (None) # these are globals

def find(h, p='', re=None):
print h, p, re
#global prev, prev_re
if p == '' and prev == h: return prev_re
prev, prev_re = h, re
return re
print find ("abc")

导致此错误:

    if p == '' and prev == h: return prev_re
UnboundLocalError: local variable 'prev' referenced before assignment
$

但是如果我注释掉find的最后一行,

prev, prev_re = '', (None)

def find(h, p='', re=None):
print h, p, re
#global prev, prev_re
if p == '' and prev == h: return prev_re
#prev, prev_re = h, re
return re
print find ("abc")

代码按预期正确运行,没有错误。

我的问题是为什么在第一种情况下它没有找到全局变量 prev,为什么在第二种情况下它确实在 if 中找到了全局变量 -条件?

编辑:请帮助我理解环境结构的细节,理解为什么解释器找不到变量。

最佳答案

问题与解决方案

正如 MAK 所提到的,prev 被视为本地,因为您为其分配了值(在检查值之后)。解决方案是将这两个变量显式声明为全局变量:

prev, prev_re = '', (None) # these are globals

def find(h, p='', re=None):
global prev, prev_re
print h, p, re
#global prev, prev_re # basically what you have done before commenting this
if p == '' and prev == h: return prev_re
prev, prev_re = h, re
return re
print find ("abc")

问题的答案

why in the first case it does not find the global variable prev

它找到了它,但随后它找到了前面没有 global 语句的赋值。因此,该变量被视为本地。取消注释 global 行,它将被修复。或者使用不同的变量进行局部赋值。您还可以将该值保存为函数的属性(函数也是对象!)。

why in the second case it does find the global variable in the if-condition

它将它视为全局变量(因为您只读取它而没有在函数内定义它,所以它不会被局部变量遮蔽)。

更多阅读

当提到此行为时,您询问了文档中的位置。我没有找到任何地方明确说明错误的含义以及为什么会发生这种特定情况,但是有 very good explanation of the execution model这可能就足够了:

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

If the global statement occurs within a block, all uses of the name specified in the statement refer to the binding of that name in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module __builtin__. The global namespace is searched first. If the name is not found there, the builtins namespace is searched. The global statement must precede all uses of the name.

所以基本上:

  • 如果赋值发生在特定函数内,变量将被视为本地,除非...
  • 如果变量的使用前面有global 语句,则变量被视为local
  • 如果没有赋值,首先在局部命名空间中查找变量,然后在全局命名空间中查找变量,然后在__builtin__模块中查找,

另请注意,Python 3 有 nonlocal 语句告诉解释器该变量来自外部作用域(不是当前作用域,但不一定是全局作用域)。

关于python - Python 中 `global` 变量的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14063877/

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