【发布时间】:2018-12-19 03:43:11
【问题描述】:
我有一些来自初学者编码练习的代码:
numbers = []
i = 0
def populate(maximum, step):
while i < maximum:
numbers.append(i)
i = i + step
populate(10, 2)
堆栈跟踪失败:
Traceback (most recent call last):
File "test_python.py", line 9, in <module>
populate(10, 2)
File "test_python.py", line 5, in populate
while i < maximum:
UnboundLocalError: local variable 'i' referenced before assignment
这是我迄今为止对问题的理解......
-
i是一个 int,因此它是不可变的,numbers是一个列表并且是可变的 - 由于
i是不可变的,因此可以在超出范围时对其进行读取。但是,在它不在范围内时(即在populate函数中)覆盖它会导致UnboundLocalError - 由于
numbers是一个可变列表,附加到它不会导致覆盖,因此不会导致UnboundLocalError -
如果对
populate方法进行简单的更改,程序就会成功运行(因为i没有被覆盖)def populate(maximum, step): new_i = i while new_i < maximum: numbers.append(i) new_i = new_i + step 如果我注释掉
i = i + 1行,while 循环(显然)会永远运行,但程序不会失败。
那么我的问题是,为什么 Python 在第 5 行的 while 循环中失败,而不是第 7 行的实际问题 (i = i + 1)?这是解释器将while循环作为代码块的一些工件吗?
这段代码在正确的地方失败了:
def populate(maximum, step):
while i < maximum:
raise Exception("foo")
堆栈跟踪:
Traceback (most recent call last):
File "test_python.py", line 12, in <module>
populate(10, 2)
File "test_python.py", line 6, in populate
raise Exception("foo")
Exception: foo
另一个注意事项:这似乎只是在控制块的开头使用变量时的情况(即while i < maximum)。每种类型的控制块都会发生相同的行为:while、for、if、elif 等。
【问题讨论】:
-
这个与不可变与可变无关。如果对尚未声明的名称进行赋值
globalanywhere,Python 会创建一个作用域为包含该赋值的函数的变量。 -
“因为 i 是不可变的,所以它可以在超出范围时被读取。” 不,对象的可变性对 Python 的作用域规则没有影响。这完全无关紧要。
标签: python python-2.7 interpreter