2011-07-03 11 views
9

Me pregunto si es posible que un cierre en Python manipule variables en su espacio de nombres. Puede llamar a esto efectos secundarios porque el estado está siendo modificado fuera del cierre mismo. Me gustaría hacer algo como estoCierre de Python con efectos secundarios

def closureMaker(): 
    x = 0 
    def closure(): 
    x+=1 
    print x 
    return closure 

a = closureMaker() 
a() 
1 
a() 
2 

Obviamente lo que espero hacer es más complicado, pero este ejemplo ilustra lo que estoy hablando.

+0

Me marcar este como un duplicado de otra pregunta, excepto las otras preguntas realmente deben marcarse un duplicado de éste; esta pregunta es bastante simple y al grano y está bien escrita. Pero también vea http://stackoverflow.com/questions/141642/what-limitations-have-closures-in-python-compared-to-language-x-closures – ninjagecko

+0

¿Entonces no hay forma de combinar dos o más preguntas? ; p –

Respuesta

17

No puede hacer exactamente eso en Python 2.x, pero puede usar un truco para obtener el mismo efecto: use un objeto mutable como una lista.

def closureMaker(): 
    x = [0] 
    def closure(): 
     x[0] += 1 
     print x[0] 
    return closure 

También puede hacer x un objeto con un atributo con nombre, o un diccionario. Esto puede ser más legible que una lista, especialmente si tiene más de una de esas variables para modificar.

En Python 3.x, solo necesita agregar nonlocal x a su función interna. Esto hace que las asignaciones a x vayan al ámbito externo.

+0

Por favor, explique por qué? Estoy tratando de encontrar algo sobre esto en los documentos de Python. –

+1

@ André: PEP 3104 es informativo, si es técnico: http://www.python.org/dev/peps/pep-3104/ –

+0

Para mí, parece que ** debe ** funcionar de cualquier manera. Acabo de leer [esto] (http://docs.python.org/reference/executionmodel.html#naming-and-binding): * "Si la definición ocurre en un bloque de funciones, el alcance se extiende a cualquier bloque contenido dentro del definiendo uno, a menos que un bloque contenido introduzca un enlace diferente para el nombre. "* –

Cuestiones relacionadas