2

Possible Duplicate:
Python variable scope question

The Python Manual defines the scope as:

A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.

I have this program:

import random
def f():
  a = "Is the scope static?"
  if random.randint(0, 1) == 1:
    del a
  print a

There is a 50% chance that the print will fail:

>>> 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

By that, I think that there is a 50% chance that the print statement is outside the scope of 'a', but I can be wrong. What is the "correct" interpretation of scope in Python? Is the scope of a variable in Python defined statically? What is the scope of the variable "a"?

4

3 回答 3

11

名称的范围a是整个函数f,并且是纯静态的。说“有 50% 的可能性 print 语句超出了范围a”是完全不正确的。“不在范围内”并不是名称查找失败的唯一原因。

请注意您从此函数中得到的错误:

>>> 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从未存在过一样。差异的原因是因为函数的本地范围是静态的。如果函数包含对名称的赋值,则该名称的局部范围是整个函数体1。即使在第一次赋值之前,或者在你习惯于del摆脱它之后,在该函数中查找该名称将尝试获取局部变量的值。


1除非名称已被声明globalnonlocal.

于 2012-10-15T23:00:20.027 回答
3

Python遵循LEGB规则:

L: Local          # Current def
E: Enclosing      # Any enclosing def
G: Global         # Globals
B: Built-in       # Built-ins

所以对于你的问题是L

于 2012-10-15T22:17:20.033 回答
1

只有类、函数和模块在 Python 中提供范围ifwhile而其他循环/分支结构不提供。

文档

范围是静态确定动态使用的。在执行期间的任何时候,至少有三个嵌套作用域的命名空间可以直接访问:

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与在函数的其他地方使用它没有任何不同。

于 2012-10-15T22:18:44.667 回答