2009-08-11 6 views
174

¿Qué hace la instrucción Python nonlocal (en Python 3.0 y posterior)?declaración no local de Python

No hay documentación en el sitio web oficial de Python y help("nonlocal") tampoco funciona.

+4

Tome un vistazo a esta pregunta: http://stackoverflow.com/questions/1414304/local-functions-in -python –

+12

Aquí está la documentación oficial del sitio web de Python para nonlocal: http://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement (esta documentación ha estado disponible desde Python 3.0, por lo que la afirmación del OP que no hay documentación oficial incorrecta) – wkschwartz

+3

'" No hay documentación para lo no local ".' En realidad, puede hacer' help (keyword_in_string) 'para documentaciones en Python 3 y superiores – ytpillai

Respuesta

254

Compare esto, sin necesidad de utilizar nonlocal:

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 1 
# global: 0 

Para esto, utilizando nonlocal, donde inner() 's x es ahora también outer()' s x:

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     nonlocal x 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 2 
# global: 0 

Si nos fueron a usar global, sería obligar x al valor adecuadamente "global":

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     global x 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 1 
# global: 2 
+25

¿Cómo es eso diferente de x global? – ooboo

+36

Es muy similar, pero tenga en cuenta que la x externa no es global en el ejemplo sino que se define en la función externa. – Anon

+0

por lo que le permite hacer clases internas que hacen referencia a vars externos, como java? –

64

En resumen, le permite asignar valores a una variable en un ámbito externo (pero no global). Ver PEP 3104 para todos los detalles sangrientos.

29

Una búsqueda en Google de "python nonlocal" apareció la Propuesta, PEP 3104, que describe completamente la sintaxis y el razonamiento detrás de la declaración. en resumen, funciona exactamente de la misma manera que la declaración global, excepto que se usa para referirse a variables que no son globales ni locales para la función.

Aquí hay un breve ejemplo de lo que puede hacer con esto. El generador de contador puede reescribirse para usarlo de modo que se parezca más a las expresiones idiomáticas de los idiomas con cierres.

def make_counter(): 
    count = 0 
    def counter(): 
     nonlocal count 
     count += 1 
     return count 
    return counter 

Obviamente, se podría escribir esto como un generador, como:

def counter_generator(): 
    count = 0 
    while True: 
     count += 1 
     yield count 

Pero si bien esto es pitón perfectamente idiomática, parece que la primera versión sería un poco más evidente para los principiantes . Usar correctamente generadores, llamando a la función devuelta, es un punto común de confusión. La primera versión devuelve explícitamente una función.

+1

Estaba seguro de que eso es lo que hace la palabra clave 'global': funciona en entornos superiores hasta que alcanza una variable con ese nombre.una variable x podría declararse a nivel de módulo, dentro de una clase, luego por separado en una función dentro de esta clase y luego en una función interna de esa función, ¿cómo sabe a qué x referirse? – ooboo

+4

lo que pasa con global es que solo funciona para variables globales. no puede ver las variables en un ámbito cerrado, no global. – SingleNegationElimination

+0

Probé el make_counter, pero no devuelve un generador sino una función. ¿Hay alguna manera de devolver un generador para luego poder iterar sobre él? – Dejell

11

@ooboo:

toma el que "más cercano" al punto de referencia en el código fuente. Esto se denomina "Alcance léxico" y es estándar desde hace más de 40 años.

Los miembros de la clase de Python están realmente en un diccionario llamado __dict__ y nunca serán alcanzados por alcance léxico.

Si no especifica nonlocal pero lo hace x = 7, creará una nueva variable local "x". Si especifica nonlocal, encontrará la "x" más cercana y la asignará. Si especifica nonlocal y no hay una "x", le dará un mensaje de error.

La palabra clave global siempre me ha parecido extraña, ya que ignorará felizmente todas las demás "x", excepto la más externa. Extraño.

2

Mi comprensión personal de la declaración "no local" (y discúlpeme ya que soy nuevo en Python y Programación en general) es que la "no local" es una forma de utilizar la funcionalidad Global dentro de funciones iteradas en lugar del cuerpo del código en sí. Una declaración global entre funciones si lo desea.

13

ayuda ('no local') El nonlocal comunicado


nonlocal_stmt ::= "nonlocal" identifier ("," identifier)* 

La declaración nonlocal hace que los identificadores listados para referirse a variables previamente con destino en el ámbito de inclusión más cercano. Esto es importante porque el comportamiento predeterminado para el enlace es buscar primero el espacio de nombres local . La instrucción permite que el código encapsulado vuelva a enlazar variables fuera del alcance local además del alcance global (módulo).

nombres que figuran en un comunicado nonlocal, a diferencia de las enumeradas en una declaración global, hay que referirse a la pre-existentes fijaciones en un ámbito de inclusión (del ámbito en el que un nuevo enlace se debe crear no se puede determinar de forma inequívoca) .

Los nombres enumerados en una declaración nonlocal no deben colisionar con los enlaces existentes anteriores al en el ámbito local.

Consulte también:

PEP 3104 - acceso a los nombres en Outer Scopes
La especificación para la declaración nonlocal.

temas de ayuda relacionados: globales, espacios de nombres

Fuente: Python Language Reference

+5

Aprende algo nuevo todos los días. No tenía idea de que pudieras usar 'help()' en las palabras clave (y ahora mi mente está quemada: 'help()' sin argumentos va _interactive_). –

1
a = 0 #1. global variable with respect to every function in program 

def f(): 
    a = 0   #2. nonlocal with respect to function g 
    def g(): 
     nonlocal a 
     a=a+1 
     print("The value of 'a' using nonlocal is ", a) 
    def h(): 
     global a    #3. using global variable 
     a=a+5 
     print("The value of a using global is ", a) 
    def i(): 
     a = 0    #4. variable separated from all others 
     print("The value of 'a' inside a function is ", a) 

    g() 
    h() 
    i() 
print("The value of 'a' global before any function", a) 
f() 
print("The value of 'a' global after using function f ", a) 
Cuestiones relacionadas