Python手册将范围定义为:
范围定义块中名称的可见性。如果是当地的 变量在块中定义,其范围包括该块。如果 定义发生在功能块中,范围扩展到任何块 包含在定义的内容中,除非包含的块引入 名称的不同绑定。
我有这个程序:
import random
def f():
a = "Is the scope static?"
if random.randint(0, 1) == 1:
del a
print a
打印失败的可能性为50%:
>>> f()
Is the scope static?
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in f
UnboundLocalError: local variable 'a' referenced before assignment
通过这种方式,我认为打印声明有50%的可能性超出了'a'的范围,但我可能是错的。 Python中范围的“正确”解释是什么? Python中变量的范围是静态定义的吗?变量“a”的范围是什么?
答案 0 :(得分:10)
名称a
的范围覆盖整个函数f
,并且纯粹是静态的。说“打印语句超出a
”范围的可能性为50%是完全正确的。 “不在范围内”并不是名称查找失败的唯一原因。
请注意您从此功能获得的错误:
>>> def foo():
... print a
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
NameError: global name 'a' is not defined
当你的函数执行del a
时,你得到的错误不一样。在我的foo
中,a
未在foo
的本地范围内定义,因此名称查找继续进行全局范围,其中未找到a
,因此我们关于没有全局a
的例外情况。
您得到的错误清楚地表明Python知道名称a
是f
的局部变量。但它没有价值,因为你删除了它。 (通常这只会发生,因为你在写入之前尝试读取局部变量,这就是为什么错误信息的措辞是这样的)
还请注意这种情况:
a = 3
>>> def bar():
... a = 1
... del a
... print a
...
>>> bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in bar
UnboundLocalError: local variable 'a' referenced before assignment
Python抱怨本地a
没有值。如果a
根本不在本地范围内,则会全局查找a
并找到3
:
>>> a = 8
>>> def baz():
... print a
...
>>> baz()
8
这与您从全局范围内del
事物时获得的行为不同:
>>> a = 12
>>> del a
>>> print a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
在这里你得到一个例外,好像a
从未存在过。区别的原因是,因为函数的本地范围是 static 。如果函数包含对名称的赋值,则该名称本地作用于函数体 1 的整个范围。甚至在第一次分配之前,或者在使用del
去除它之后,在该函数中查找该名称将尝试获取局部变量的值。
1 除非名称已被宣布为global
或nonlocal
。
答案 1 :(得分:3)
python遵循LEGB
规则:
L:local #current def
E:enclosing #any enclosing def
G:global #globals
B:built-in #built-ins
所以对于你的问题,它是L
。
答案 2 :(得分:1)
只有类,函数和模块在Python中提供范围,if
,while
和其他循环/分支结构不提供。
来自docs:
范围静态确定但动态使用。在执行期间的任何时候,至少有三个嵌套的作用域,其名称空间可以直接访问:
the innermost scope, which is searched first, contains the local names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
the next-to-last scope contains the current module’s global names
the outermost scope (searched last) is the namespace containing built-in names
在您的代码中,您在本地命名空间中定义a
并删除它。在del
分支中使用if
与在函数中的其他位置使用它没有任何不同。