变量“a”的范围是什么?

时间:2012-10-15 22:12:31

标签: python

  

可能重复:
  Python variable scope question

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”的范围是什么?

3 个答案:

答案 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知道名称af的局部变量。但它没有价值,因为你删除了它。 (通常这只会发生,因为你在写入之前尝试读取局部变量,这就是为什么错误信息的措辞是这样的)

还请注意这种情况:

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 除非名称已被宣布为globalnonlocal

答案 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中提供范围,ifwhile和其他循环/分支结构不提供。

来自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与在函数中的其他位置使用它没有任何不同。