为什么我在下面的第三个代码中出错,但在前两个代码中却没有?我正在使用 Python 3.6.0、Anaconda 4.3.1(64 位)Jupyter。
代码 1:
c = 100
def fib():
c = 20
a = c
print ("a in fib", a)
print ("c in fib", c)
fib()
print ("c", c)
代码 1 的输出:
a in fib 20
c in fib 20
c 100
代码 2:
c = 100
def fib():
a = c
print ("a in fib", a)
print ("c in fib", c)
fib()
print ("c", c)
代码 2 的输出:
a in fib 100
c in fib 100
c 100
代码 3:
c = 100
def fib():
a = c
print ("a in fib", a)
print ("c in fib", c)
c = 20
fib()
print ("c", c)
代码 3 的输出:
UnboundLocalError Traceback (most recent call last)
<ipython-input-42-d6affa26dc65> in <module>()
7
8
----> 9 fib()
10 print ("c", c)
<ipython-input-42-d6affa26dc65> in fib()
1 c = 100
2 def fib():
----> 3 a = c
4 print ("a in fib", a)
5 print ("c in fib", c)
UnboundLocalError: local variable 'c' referenced before assignment
最佳答案
这种行为称为词法作用域。这里是官方的相关部分Python docs (强调我的):
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.
而对于"name binding operations"的定义(再次强调我的):
Names refer to objects. Names are introduced by name binding operations.
The following constructs bind names: formal parameters to functions,
import
statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers if occurring in an assignment,for
loop header, or afteras
in awith
statement orexcept
clause. Theimport
statement of the formfrom ... import *
binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level.A target occurring in a
del
statement is also considered bound for this purpose (though the actual semantics are to unbind the name).
因此,在您的第 3 个代码示例中, block 末尾的 c = 20
通过“如果出现在赋值中则为标识符的目标”子句作为名称绑定(bind)操作。这使得该函数中出现的所有 c
都引用 local 变量 c
。但是,在运行时,您的代码首先命中 a = c
行。由于 c
实际上尚未在本地范围内定义,因此您会得到异常。
在第一个 block 中,您在尝试引用它之前在本地定义了 c
,所以没有问题。
在第二种情况下,您不会在函数内对 c
执行任何名称绑定(bind)操作,因此 Python 假定您需要外部定义。
至于为什么它以这种方式工作,请参阅 this question :
The rationale for lexical scoping is not just for performance (full lexical scoping including closures actually has a performance cost, see the funcarg problems), it's for simplicity and reliability. While it may be surprising when first learning the language, the rules are actually dead simple so an experienced programmer can instantly tell which use of an identifier refers to which scope. One can understand functions in isolation, as execution isn't affected by who calls this functions and how they decided to name their variables.
关于Python - 在先前已在全局范围内查找的函数内重新分配名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43231598/