13

需要帮助理解PEP 227Python 语言参考中的以下句子

如果在封闭范围内引用了变量,则删除该名称是错误的。编译器将为“del name”引发 SyntaxError。

缺少示例导致我无法在编译时重现错误,因此非常需要使用示例进行解释。

4

2 回答 2

18

以下引发了执行:

def foo():
    spam = 'eggs'
    def bar():
        print spam
    del spam

因为该spam变量正在以下范围内使用bar

>>> def foo():
...     spam = 'eggs'
...     def bar():
...         print spam
...     del spam
... 
SyntaxError: can not delete variable 'spam' referenced in nested scope

Python 检测到它spam正在被引用,bar但没有为该变量分配任何东西,因此它在foo. 它分配在那里,使del spam语句成为语法错误。

这个限制在 Python 3.2 中被移除;您现在有责任自己不删除嵌套变量;你会得到一个运行时错误(NameError)而不是:

>>> def foo():
...     spam = 'eggs'
...     def bar():
...         print(spam)
...     del spam
...     bar()
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in foo
  File "<stdin>", line 4, in bar
NameError: free variable 'spam' referenced before assignment in enclosing scope
于 2012-09-09T11:45:23.737 回答
5

一个例子可以是这个:

>>> def outer():
...     x = 0
...     y = (x for i in range(10))
...     del x
... 
SyntaxError: can not delete variable 'x' referenced in nested scope

基本上这意味着您不能删除内部块中使用的变量(在这种情况下是 genexp)。

请注意,这适用于 python <= 2.7.x 和 python < 3.2。在 python3.2 中,它不会引发语法错误:

>>> def outer():
...     x = 0
...     y = (x for i in range(10))
...     del x
... 
>>> 

有关更改的全部内容,请参阅链接。

我认为 python3.2 语​​义更正确,因为如果你在函数之外编写相同的代码,它就可以工作:

#python2.7
>>> x = 0
>>> y = (x for i in range(10))
>>> del x
>>> y.next()     #this is what I'd expect: NameError at Runtime
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
NameError: global name 'x' is not defined

将相同的代码放入函数中时,不仅会更改异常,而且会在编译时出现错误。

于 2012-09-09T11:46:29.907 回答