未绑定的变量和名称

2022-01-14 00:00:00 python variables namespaces

问题描述

根据python参考手册我们有

当根本找不到名称时,会引发 NameError 异常.如果该名称指的是尚未绑定的局部变量,a引发 UnboundLocalError 异常.UnboundLocalError 是一个子类的名称错误.

When a name is not found at all, a NameError exception is raised. If the name refers to a local variable that has not been bound, a UnboundLocalError exception is raised. UnboundLocalError is a subclass of NameError.

我不明白什么时候抛出 UnboundLocalError?因为

I don't to understand when the UnboundLocalError is thrown? Because

Python 缺少声明并允许发生名称绑定操作代码块内的任何位置.

Python lacks declarations and allows name binding operations to occur anywhere within a code block.

那么我们怎样才能声明一个变量,而不是初始化她呢?

So how we can declare a variable, but not to initialize her?


解决方案

你可以引用一个没有分配的名字:

You can refer to a name without having assigned to it:

>>> foobar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foobar' is not defined

这里 foobar 被引用,但从未被分配到.这会引发 NameError 因为名称从未绑定.

Here foobar is being referred to, but was never assigned to. This raises a NameError because the name was never bound.

更微妙的是,这里没有发生分配,因为执行的行永远不会运行:

More subtly, here assignment is not happening because the line that does is never run:

>>> def foo():
...     if False:
...         spam = 'eggs'
...     print spam
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in foo
UnboundLocalError: local variable 'spam' referenced before assignment

因为 spam = 'eggs' 永远不会执行,所以 print spam 会引发 UnboudLocalError.

Because spam = 'eggs' is never executed, print spam raises an UnboudLocalError.

请注意,Python 中没有任何地方声明过.您绑定或不绑定,声明不是语言的一部分.

Note that nowhere in Python is a name ever declared. You bind or don't bind, declaration is not part of the language.

相反,binding 用于确定名称的范围;绑定操作包括赋值、用于 for 循环的名称、函数参数、导入语句、在 except 子句中保存捕获的异常的名称、上下文管理器的名称一个 with 语句所有的绑定名称.

Instead, binding is used to determine the scope of a name; binding operations include assignment, names used for a for loop, function parameters, import statements, name to hold a caught exception in an except clause, the name for a context manager in a with statement all bind names.

如果名称绑定在范围内(例如在函数中),则它是本地名称,除非您使用 global 语句(或 nonlocal 语句在 Python 3 中)将名称显式标记为全局(或闭包).

If a name is bound in a scope (such as in a function) then it is a local name, unless you use a global statement (or a nonlocal statement in Python 3) to explicitly mark the name as a global (or a closure) instead.

所以下面是一个错误:

>>> foo = None
>>> def bar():
...     if False:
...         foo = 'spam'
...     print foo
... 
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in bar
UnboundLocalError: local variable 'foo' referenced before assignment

因为 foo 被 somewhere 绑定在 bar 函数范围内.但是如果您将 foo 标记为全局,则该函数可以工作:

because foo is being bound somewhere in the bar function scope. But if you mark foo as a global, the function works:

>>> foo = None
>>> def bar():
...     global foo
...     if False:
...         foo = 'spam'
...     print foo
... 
>>> bar()
None

因为现在 Python 编译器知道您希望 foo 改为全局变量.

because now the Python compiler knows you wanted foo to be a global instead.

所有这些都记录在 命名和绑定部分 Python 参考文档.

This is all documented in the Naming and Binding section of the Python reference documentation.

相关文章