Ámbito de variables en Python, clausuras y la regla LEGB
Esta lección es una traducción del original en inglés.Read in EnglishAvisar de un error de traducción
Imagina una casa con varias habitaciones. Cada habitación tiene sus propios objetos: una lámpara en la mesita de noche del dormitorio, un cuchillo en el cajón de la cocina. Puedes usar lo que hay en la habitación en la que estás, y puedes salir al pasillo a buscar algo compartido. Pero no puedes meter la mano en la habitación cerrada de otra persona sin abrir antes la puerta.
Las variables de Python funcionan igual. Cada variable vive en un ámbito (scope): una región concreta de tu código donde esa variable existe y se puede usar. Entender el ámbito es la clave para escribir funciones limpias que no se pisen los datos unas a otras por accidente.
En este tutorial aprenderás los cuatro niveles de ámbito de Python (la regla LEGB), cómo usar las palabras clave global y nonlocal, y cómo las clausuras (closures) permiten que las funciones internas recuerden valores de la función que las contiene. Al terminar, podrás depurar con confianza los errores de "variable no encontrada" más confusos.
¿Qué es el ámbito local?
Cuando creas una variable dentro de una función, solo existe dentro de esa función. Esto se llama ámbito local. Es como una habitación privada: nada de fuera de la función puede ver ni tocar esa variable.
Hello from inside!
La variable message se crea dentro de greet(), así que es local a esa función. Cuando greet() termina, message desaparece. Si intentas usarla fuera, Python lanza un NameError.
Cada llamada a una función crea un conjunto nuevo de variables locales. No se conservan de una llamada a otra:
x is 1 x is 1 x is 1
¿Qué es el ámbito global?
Una variable creada fuera de cualquier función vive en el ámbito global. Es como un objeto en el pasillo de tu casa: todas las habitaciones pueden verlo.
Language: Python Welcome to Python!
Las dos funciones pueden leer la variable global language. Pero ¿qué pasa si intentas cambiarla dentro de una función?
(sin salida)
Esto falla con un UnboundLocalError. Python ve counter = ... dentro de la función y supone que counter es una variable local. Pero luego el lado derecho intenta leer counter antes de que tenga un valor local. Python se confunde.
La regla LEGB: cómo encuentra Python las variables
Cuando usas el nombre de una variable, Python busca en cuatro lugares, en un orden concreto. Esto se conoce como la regla LEGB:
print, len, range.Python los revisa en orden: primero L, luego E, luego G y por último B. Se detiene en la primera coincidencia. Si no encuentra nada en ninguno, obtienes un NameError.
local x enclosing x global x
Cada print(x) encuentra una x distinta porque busca desde su propio ámbito hacia afuera. La función interna encuentra primero su x local y deja de buscar.
La palabra clave global
Si necesitas modificar una variable global desde dentro de una función, tienes que indicárselo a Python de forma explícita con la palabra clave global. Es como conseguir una llave especial para salir al pasillo y cambiar las cosas de sitio.
Score is now 10 Score is now 35 Score is now 40 Final score: 40
La declaración global score le dice a Python: "No estoy creando una variable local nueva. Quiero usar la global". Ahora la asignación score = score + points funciona correctamente.
total = 0
def add(n):
global total
total = total + n
add(5)
add(3)
print(total) # 8def add(current, n):
return current + n
total = 0
total = add(total, 5)
total = add(total, 3)
print(total) # 8Ámbito envolvente y clausuras
Cuando defines una función dentro de otra, la función interna puede acceder a las variables de la función externa. El ámbito de esa función externa se llama ámbito envolvente (enclosing scope): la "E" de LEGB.
Hello, Alice! Hello, Bob! Howdy, Alice!
Aquí pasa algo notable. make_greeting("Hello") termina de ejecutarse y devuelve la función interna greet. Normalmente, la variable local greeting se destruiría. ¡Pero la función interna todavía la necesita!
Python mantiene viva greeting porque greet hace referencia a ella. Esta combinación de una función y las variables que recuerda de su ámbito envolvente se llama clausura (closure).
Las clausuras sirven para crear funciones especializadas. Aquí tienes un ejemplo práctico, una fábrica de multiplicadores:
10 15 200
La palabra clave nonlocal
Igual que global te permite modificar variables globales, nonlocal te permite modificar variables del ámbito envolvente. Sin ella, asignar un valor a la variable crearía una variable local nueva.
1 2 3
Sin nonlocal count, la línea count = count + 1 fallaría con un UnboundLocalError, el mismo problema que vimos con las globales. La palabra clave nonlocal le dice a Python que busque la variable un ámbito más afuera.
Este patrón es muy potente. La variable count queda completamente oculta para el mundo exterior. Ningún código fuera de make_counter puede acceder a ella ni manipularla. Es una forma de encapsulamiento: mantener los datos privados.
Errores de ámbito comunes y cómo corregirlos
Estos son los errores de ámbito con los que más se tropieza al programar en Python. Conocer estos patrones te ahorrará horas de depuración.
Error 1: ocultar una variable global
Inside: ['date'] Outside: ['apple', 'banana', 'cherry']
El items = [] de dentro de la función crea una variable local totalmente nueva que oculta a la global (en inglés se llama shadowing). La lista global items nunca se modifica. Esto suele ser un error.
Error 2: UnboundLocalError por mezclar lectura y escritura
(sin salida)
Python revisa todo el cuerpo de la función antes de ejecutarla. Si ve cualquier asignación a total, marca total como local en toda la función. Después, la línea print(total) intenta leer una variable local que todavía no tiene valor.
Ejercicios de práctica
Es hora de poner en práctica el ámbito y las clausuras. Estos ejercicios van desde leer el ámbito hasta construir tus propias clausuras.
Lee este código con atención y predice lo que imprime. Después escribe una sola instrucción print() que muestre exactamente ese resultado.
x = 10
def foo():
x = 20
print(x)
foo()
print(x)Imprime los dos números en líneas separadas, exactamente como los mostraría el código de arriba.
Este código intenta incrementar un contador global, pero falla con un UnboundLocalError. Corrígelo para que la salida sea:
1
2
3Escribe una función llamada make_greeter que reciba una cadena greeting como argumento y devuelva una función nueva. La función devuelta debe recibir un argumento name e imprimir el saludo con el nombre.
Por ejemplo:
hello = make_greeter("Hello")
hello("World")Debe imprimir: Hello, World!
La prueba hará estas llamadas:
hi = make_greeter("Hi")
hi("Alice")
hi("Bob")Salida esperada:
Hi, Alice!
Hi, Bob!Escribe una función llamada make_counter que reciba un valor start y devuelva una función. Cada vez que se llame a la función devuelta, debe imprimir la cuenta actual y luego aumentarla en 1.
La prueba hará estas llamadas:
c = make_counter(1)
c()
c()
c()Salida esperada:
1
2
3Escribe una función llamada make_averager que devuelva una función. Cada vez que se llame a la función devuelta con un número, debe imprimir el promedio acumulado de todos los números recibidos hasta ese momento.
El promedio acumulado es la suma de todos los números dividida entre la cantidad de números.
La prueba hará estas llamadas:
avg = make_averager()
avg(10)
avg(20)
avg(30)Salida esperada:
10.0
15.0
20.0Pista: la función necesita recordar tanto la suma total como la cantidad de números.
Resumen
Lo que ya sabes sobre el ámbito en Python:
| Concepto | Qué significa |
|---|---|
| Ámbito local | Variables creadas dentro de una función; solo existen ahí |
| Ámbito global | Variables creadas en el nivel del módulo; visibles en todas partes |
| Regla LEGB | Python busca en Local, Enclosing, Global y Built-in, en ese orden |
Palabra clave global | Permite que una función modifique una variable del nivel del módulo |
| Ámbito envolvente | Las variables de una función externa, accesibles desde las funciones internas |
| Clausura | Una función que recuerda variables de su ámbito envolvente |
Palabra clave nonlocal | Permite que una función interna modifique una variable del ámbito envolvente |
La regla de oro: prefiere pasar argumentos y devolver valores antes que usar global o nonlocal. Las clausuras son la única excepción en la que el ámbito envolvente brilla: te permiten crear funciones especializadas con estado privado.
¿Qué sigue?
Ahora que entiendes el ámbito y las clausuras, puedes pasar a la [recursión](/python/python-recursion), donde las funciones se llaman a sí mismas. Entender el ámbito es esencial para la recursión, porque cada llamada recursiva tiene su propio ámbito local.