Regla LEGB — es la regla de búsqueda de espacios de nombres (scoping) en Python. La abreviatura se traduce como:
len, list, etc.).Cuando Python encuentra una variable, primero busca localmente, luego en las funciones anidadas, después en el área global del módulo y, finalmente, en el espacio de nombres de los objetos incorporados:
def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer() # 'local'
Si dentro de inner() se quita la asignación a x, Python tomará x del scope externo (outer). Si no hay variable allí, buscará globalmente, luego en los incorporados.
¿Cómo cambiaría el comportamiento de la función si olvidas declarar
nonlocaloglobalal modificar una variable de nivel externo?
Respuesta:
Si intentas modificar una variable del scope externo dentro de una función anidada sin declarar nonlocal (o global, si la variable está en el módulo), Python creará una nueva variable local sin modificar la externa.
Ejemplo:
x = 10 def foo(): x = 20 # Esta es una nueva x local, la global no se cambia foo() print(x) # 10
Para cambiar la x global:
def foo(): global x x = 20
Con las variables de la función externa — utiliza nonlocal.
Historia 1
En un proyecto educativo, se utilizaron funciones anidadas para contar el número de llamadas. El desarrollador escribió:
def counter(): count = 0 def inc(): count += 1 return count return inc
Pero surgió un UnboundLocalError, porque count dentro de inc() se consideraba nuevo (se creaba un count local). Solución: declarar count como nonlocal.
Historia 2
En una aplicación web, querían modificar globalmente la caché definida:
cache = {} def add_to_cache(key, value): cache[key] = value
Sin embargo, si dentro de la función intentaran sobrescribir completamente cache, por ejemplo cache = {key: value}, esto crearía un nuevo cache local, no relacionado con el global, debido a la falta de global cache.
Historia 3
En un gran sistema ETL, hubo un error: los programadores dejaron la variable result sin inicialización explícita dentro de la función, esperando que se tomara del scope externo. Pero después de varias iteraciones, el resultado empezó a desajustarse, ya que se estaba haciendo result += value, y no result = result + value (sin nonlocal/global) — y result se inicializaba de nuevo en cada llamada.