ProgramaciónDesarrollador de Python

¿Qué es la 'regla LEGB' en Python? ¿Cómo funciona al buscar el nombre de una variable? Proporcione ejemplos de situaciones donde una comprensión incorrecta de esta regla conduce a errores no triviales.

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Regla LEGB — es la regla de búsqueda de espacios de nombres (scoping) en Python. La abreviatura se traduce como:

  • Local — espacio de nombres local (dentro de la función);
  • Enclosing — espacios de nombres de todas las funciones anidadas;
  • Global — espacio de módulos (variables globales);
  • Builtin — nombres incorporados de Python (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.


Pregunta capciosa.

¿Cómo cambiaría el comportamiento de la función si olvidas declarar nonlocal o global al 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.


Ejemplos de errores reales debido al desconocimiento de los matices del tema.


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.