在函数外声明的变量

Bog*_*dan 43 python

可能重复:
在赋值之前引用的python local var中的赋值错误
之前引用

好吧,我只是试着看看变量范围如何工作并在以下情况下运行.全部从终端跑:

x = 1
def inc():
    x += 5

inc()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in inc
UnboundLocalError: local variable 'x' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

所以我思考得很好也许我的方法无法访问x,所以我尝试了:

def inc():
    print(x)

1
Run Code Online (Sandbox Code Playgroud)

这样可行.现在我知道我可以这样做:

 def inc():
     global x
     x += 1
Run Code Online (Sandbox Code Playgroud)

这会奏效.但我的问题是为什么第一个例子失败了.我的意思是我希望自从print(x)工作以来x在函数内可见,那么为什么x + = 5失败?

Lou*_*uis 38

不同于采用"真实"词法范围的语言,Python的选择让特定的"命名空间"变量,无论是global,nonlocal或本地.可以说,让开发人员有意识地编写这样的命名空间代码更加明确,因此更容易理解.我认为这种复杂性使得语言更加笨拙,但我想这完全归功于个人偏好.

以下是一些例子global: -

>>> global_var = 5
>>> def fn():
...     print(global_var)
... 
>>> fn()
5
>>> def fn_2():
...     global_var += 2
...     print(global_var)
... 
>>> fn_2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn_2
UnboundLocalError: local variable 'global_var' referenced before assignment
>>> def fn_3():
...     global global_var
...     global_var += 2
...     print(global_var)
... 
>>> fn_3()
7
Run Code Online (Sandbox Code Playgroud)

相同的模式也可以应用于nonlocal变量,但此关键字仅适用于后面的Python版本.

如果您想知道,nonlocal在变量不是全局变量但不在函数定义范围内的情况下使用它.例如,a def中的a def,这是一种常见的情况,部分原因是缺少多语句lambdas.虽然在早期的Pythons中有一个黑客可以绕过这个功能的缺乏,我依旧记得它涉及使用单个元素列表......

请注意,写入变量是需要这些关键字的地方.只是阅读它们并不含糊,因此不需要.除非你的内部def使用与外部变量名称相同的变量名称,否则应该避免诚实.

  • 在Python中,仅在函数内部引用的变量是隐式全局的。如果在函数体内的任何位置为变量赋值,则假定该变量是局部变量,除非显式声明为全局变量。有关更多信息,请参阅此链接:http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value (2认同)

unu*_*tbu 21

当Python解析一个函数时,它会记录何时进行变量赋值.当存在赋值时,它默认假定该变量是局部变量.要声明赋值引用全局变量,必须使用global声明.

当您访问函数中的变量时,将使用LEGB作用域规则查找其值.


所以,第一个例子

  x = 1
  def inc():
      x += 5
  inc()
Run Code Online (Sandbox Code Playgroud)

产生一个UnboundLocalError因为Python确定x内部inc是一个局部变量,

x在第二个例子中访问工作时

 def inc():
    print x
Run Code Online (Sandbox Code Playgroud)

因为在这里,根据LEGB规则,Python x在本地范围内查找,找不到它,然后在扩展范围内查找它,仍然找不到它,最后在全局范围内成功查找它.

  • 在Python中,仅在函数内部引用的变量是隐式全局的。如果在函数体内的任何位置为变量赋值,则假定该变量是局部变量,除非显式声明为全局变量。有关更多信息,请参阅此链接:http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value (3认同)

wim*_*wim 8

定义函数时决定函数的本地名称:

>>> x = 1
>>> def inc():
...     x += 5
...     
>>> inc.__code__.co_varnames
('x',)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,x存在于本地名称空间中.执行x += 5需要预先存在的值x(对于整数,它就像x = x + 5),并且这在函数调用时失败,因为本地名称是未绑定的 - 这正是异常UnboundLocalError被命名的原因.

比较其他版本,其中x不是局部变量,因此可以在全局范围内解析:

>>> def incg():
...    print(x)
...    
>>> incg.__code__.co_varnames
()
Run Code Online (Sandbox Code Playgroud)

常见问题中的类似问题:http: //docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value