nonlocal - Python declaración no local
python multiple global variables (9)
ayuda (''no local'') La declaración
nonlocal
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
La declaración
nonlocal
hace que los identificadores enumerados se refieran a variables previamente vinculadas en el ámbito envolvente más cercano. Esto es importante porque el comportamiento predeterminado para el enlace es buscar primero en el espacio de nombres local. La declaración permite que el código encapsulado vuelva a vincular las variables fuera del alcance local, además del alcance global (módulo).Los nombres listados en una declaración
nonlocal
, a diferencia de los listados en una declaraciónglobal
, deben referirse a enlaces preexistentes en un ámbito adjunto (el ámbito en el que se debe crear un nuevo enlace no se puede determinar de manera inequívoca).Los nombres que aparecen en una declaración no
nonlocal
no deben coincidir con los enlaces preexistentes en el ámbito local.Ver también:
PEP 3104 - Acceso a nombres en ámbitos externos
La especificación para la declaraciónnonlocal
.Temas de ayuda relacionados: global, NOMBRES
Fuente: Referencia del lenguaje Python
¿Qué hace la declaración no nonlocal
Python (en Python 3.0 y versiones posteriores)?
No hay documentación en el sitio web oficial de Python y la help("nonlocal")
tampoco funciona.
@ooboo:
Toma el "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 el alcance léxico.
Si no especifica no nonlocal
pero hace x = 7
, creará una nueva variable local "x". Si especifica nonlocal
, encontrará el "más cercano" "x" y se lo 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 felizmente ignorará todas las otras "x", excepto la más externa. Extraño.
Cita de la referencia de Python 3 :
La declaración no local hace que los identificadores enumerados se refieran a variables previamente vinculadas en el ámbito envolvente más cercano, excluyendo las globales.
Como se dijo en la referencia, en el caso de varias funciones anidadas, solo se modifica la variable en la función de cierre más cercana:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print(''Inner x has been modified'')
x = 1
inner()
if x == 3: print(''Outer x has been modified'')
x = 0
outer()
if x == 3: print(''Global x has been modified'')
# Inner x has been modified
La variable "más cercana" puede estar a varios niveles de distancia:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print(''Outer x has been modified'')
x = 0
outer()
if x == 3: print(''Global x has been modified'')
# Outer x has been modified
Pero no puede ser una variable global:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print(''Global x has been modified'')
# SyntaxError: no binding for nonlocal ''x'' found
Compara esto, sin usar 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, usando nonlocal
, donde inner()
x
inner()
ahora también es la x
outer()
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 tuviéramos que usar
global
, enlazaríamosx
con el valor "global" adecuado:
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
En resumen, le permite asignar valores a una variable en un ámbito externo (pero no global). Ver PEP 3104 para todos los detalles sangrientos.
Mi comprensión personal de la declaración "no local" (y disculpe porque soy nuevo en Python y en Programación en general) es que "no local" es una forma de usar la funcionalidad Global dentro de las funciones iteradas en lugar del cuerpo del código en sí. . Una declaración global entre funciones si lo desea.
Una búsqueda en Google de "python nonlocal" mostró 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 puedes hacer con esto. El generador de contador se puede reescribir para usar esto de modo que se parezca más a los idiomas de idiomas con cierres.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
Obviamente, podrías escribir esto como un generador, como:
def counter_generator():
count = 0
while True:
count += 1
yield count
Pero si bien esta es una pitón perfectamente idiomática, parece que la primera versión sería un poco más obvia para los principiantes. El uso correcto de los generadores, al llamar a la función devuelta, es un punto de confusión común. La primera versión devuelve explícitamente una función.
con funciones internas "no locales" (es decir, funciones internas anidadas) se puede obtener permiso de lectura y " escritura " para esa variable específica de la función principal externa . Y no local se puede usar solo dentro de las funciones internas, por ejemplo:
a = 10
def Outer(msg):
a = 20
b = 30
def Inner():
c = 50
d = 60
print("MU LCL =",locals())
nonlocal a
a = 100
ans = a+c
print("Hello from Inner",ans)
print("value of a Inner : ",a)
Inner()
print("value of a Outer : ",a)
res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
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)