Python nested scopes with dynamic features

给你一囗甜甜゛ 提交于 2019-12-03 17:22:43

问题


Need help with understanding the following sentence from PEP 227 and the Python Language Reference

If a variable is referenced in an enclosed scope, it is an error to delete the name. The compiler will raise a SyntaxError for 'del name'.

Lack of examples caused I couldn't reproduce an error at compile time, so an explanation with examples is highly desirable.


回答1:


The following raises the execption:

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

because the spam variable is being used in the enclosed scope of bar:

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

Python detects that spam is being referenced in bar but does not assign anything to that variable, so it looks it up in the surrounding scope of foo. It is assigned there, making the del spam statement a syntax error.

This limitation was removed in Python 3.2; you are now responsible for not deleting nested variables yourself; you'll get a runtime error (NameError) instead:

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



回答2:


An example can be this one:

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

Basically it means you can't delete variables that are used in inner blocks(in that case the genexp).

Note that this apply for python <= 2.7.x and python < 3.2. In python3.2 it's it does not raise syntax error:

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

See this link for the whole story of the change.

I think the python3.2 semanthics is more correct because if you write the same code outside a function it works:

#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

While putting the same code into a function, not only changes exception but the error is at compile time.



来源:https://stackoverflow.com/questions/12338713/python-nested-scopes-with-dynamic-features

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!