Ámbitos nesteds de Python con características dinámicas

Necesita ayuda para comprender la siguiente oración de PEP 227 y la Referencia del lenguaje Python

Si se hace referencia a una variable en un ámbito cerrado, es un error eliminar el nombre. El comstackdor generará un SyntaxError para ‘del name’.

La falta de ejemplos causó que no pudiera reproducir un error en el momento de la comstackción, por lo que una explicación con ejemplos es altamente deseable.

Lo siguiente plantea la exección:

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

porque la variable de spam se está utilizando en el ámbito de bar adjunto:

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

Python detecta que se hace referencia al spam en la bar pero no asigna nada a esa variable, por lo que lo busca en el ámbito circundante de foo . Se asigna allí, lo que hace que la statement del spam un error de syntax.

Esta limitación fue eliminada en Python 3.2; ahora es responsable de no eliminar las variables anidadas usted mismo; obtendrá un error de tiempo de ejecución ( NameError ) en su lugar:

 >>> def foo(): ... spam = 'eggs' ... def bar(): ... print(spam) ... del spam ... bar() ... >>> foo() Traceback (most recent call last): File "", line 1, in  File "", line 6, in foo File "", line 4, in bar NameError: free variable 'spam' referenced before assignment in enclosing scope 

Un ejemplo puede ser éste:

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

Básicamente, significa que no se pueden eliminar las variables que se usan en bloques internos (en ese caso, el genexp).

Tenga en cuenta que esto se aplica a python <= 2.7.xy python <3.2. En python3.2 es que no genera un error de sintaxis:

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

Vea este enlace para toda la historia del cambio.

Creo que la semántica de python3.2 es más correcta porque si escribes el mismo código fuera de una función, funciona:

 #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 "", line 1, in  File "", line 1, in  NameError: global name 'x' is not defined 

Al colocar el mismo código en una función, no solo cambia la excepción, sino que el error se produce en el momento de la comstackción.