具有动态功能的Python嵌套作用域



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

如果在封闭的范围中引用了变量,则对于删除名称。编译器将引发"del"的SyntaxErrorname’。

由于缺少示例,我无法在编译时重现错误,因此非常希望用示例进行解释。

以下引发执行选项:

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检测到spambar中被引用,但没有为该变量赋值,因此它在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

例如:

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

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

最新更新