En Python, el scope (o ámbito) de una variable determina dónde puedes acceder a ella y cómo se resuelven los nombres cuando los usas en tu código. Imagina el scope como las “habitaciones” de una casa: algunas variables solo existen en una habitación específica (local), mientras que otras están disponibles en toda la casa (global). Para resolver conflictos o búsquedas de nombres, Python sigue la regla LEGB, un acrónimo que significa Local, Enclosing, Global y Built-in. Esta regla es fundamental para evitar errores comunes y escribir código predecible. En este capítulo, exploraremos estos conceptos de manera profunda, comenzando por lo básico y avanzando paso a paso, para que termines dominando cómo Python “encuentra” las variables en diferentes contextos. Recuerda, entender el scope no es solo memorizar reglas: es comprender cómo fluye el control en tu programa.
Entendiendo el Scope en Python: ¿Dónde Viven Tus Variables?
Comencemos con lo esencial. El scope define la visibilidad de una variable. En Python, no todas las variables son accesibles desde cualquier parte de tu código; esto previene colisiones accidentales y mantiene el orden. Piensa en una variable como un objeto en una caja: si la caja está en tu habitación (scope local), no puedes usarla desde la cocina (otro scope) a menos que la declares explícitamente como accesible desde allí.
Hay dos scopes principales que exploraremos: local y global. Un scope local se crea dentro de una función y solo existe mientras esa función se ejecuta. Un scope global abarca todo el módulo (archivo de código) y es accesible desde cualquier función, siempre y cuando no sea sobrescrita localmente.
Veamos un ejemplo simple para ilustrar esto. Crea un archivo llamado scope_basico.py y ejecútalo con python scope_basico.py en tu terminal. Aquí está el código:
# Variable global: accesible en todo el módulo
mensaje_global = "¡Hola desde el scope global!"
def saludar():
# Variable local: solo accesible dentro de esta función
mensaje_local = "¡Hola desde el scope local!"
print(mensaje_local) # Imprime la variable local
print(mensaje_global) # Accede a la variable global sin problemas
# Llamamos a la función
saludar()
# Intentamos acceder a la variable local fuera de la función (esto fallará)
# print(mensaje_local) # Descomenta esto para ver un NameError
print(mensaje_global) # Esto funciona, ya que es global
PythonEn este ejemplo, mensaje_local solo “vive” dentro de saludar(). Si intentas usarla fuera, Python lanza un NameError porque no la encuentra en el scope global. Por el contrario, mensaje_global es visible en todas partes. Ejecuta el código y observa: la función imprime ambos mensajes, pero fuera de ella, solo el global está disponible. Esta distinción es crucial; ignórala, y tu código se llenará de errores sutiles.
Ahora, profundicemos. ¿Qué pasa si defines una variable con el mismo nombre en scopes diferentes? Python prioriza el scope local. Es como si la variable local “eclipsara” a la global temporalmente. Modifiquemos nuestro ejemplo (guárdalo en el mismo archivo y ejecútalo de nuevo):
# Variable global
x = 10
def modificar():
# Variable local con el mismo nombre: eclipsa la global dentro de esta función
x = 20
print("Dentro de la función:", x) # Imprime 20 (local)
modificar()
print("Fuera de la función:", x) # Imprime 10 (global, no se modificó)
PythonAquí, la x local no afecta a la global. Si quieres modificar la global desde dentro de una función, usa la palabra clave global. Actualiza el código así:
# Variable global
x = 10
def modificar_global():
global x # Declaramos que usaremos la variable global
x = 20 # Ahora modificamos la global
print("Dentro de la función:", x) # Imprime 20
modificar_global()
print("Fuera de la función:", x) # Imprime 20 (global modificada)
PythonCon global, le dices a Python: “No crees una local; usa la que ya existe en el scope global”. Úsalo con precaución, ya que modifica estado compartido y puede complicar el debugging. Recuerda, un buen programador minimiza el uso de globals para mantener el código modular.
La Regla LEGB: Cómo Python Busca Nombres Paso a Paso
Ahora que dominas locales y globales, introduzcamos la regla LEGB. Esta es la secuencia que Python sigue para resolver un nombre de variable cuando lo usas. No es arbitraria; es un orden lógico que empieza por lo más cercano y va hacia lo más amplio. Desglosémosla:
- L (Local): Primero, busca en el scope local de la función actual.
- E (Enclosing): Si no lo encuentra, mira en los scopes de funciones que encierran a la actual (por ejemplo, en funciones anidadas simples).
- G (Global): Luego, en el scope global del módulo.
- B (Built-in): Finalmente, en los nombres incorporados de Python (como
printolen).
Esta regla es como buscar un libro: revisas tu escritorio (local), luego la habitación (enclosing), la casa (global) y, por último, la biblioteca pública (built-in).
Veamos un ejemplo con funciones anidadas para ilustrar E (Enclosing). Crea legb_ejemplo.py y ejecútalo con python legb_ejemplo.py:
# Scope global
global_var = "Global"
def outer():
# Scope enclosing (para la función inner)
enclosing_var = "Enclosing"
def inner():
# Scope local
local_var = "Local"
print(local_var) # Encuentra Local (L)
print(enclosing_var) # No en L, encuentra en E
print(global_var) # No en L ni E, encuentra en G
print(len) # No en L, E ni G; encuentra en B (built-in)
inner()
outer()
PythonEjecuta esto y verás que Python resuelve cada variable siguiendo LEGB estrictamente. Si no hay coincidencia en ninguno, obtienes un NameError.
¿Qué pasa si quieres modificar una variable en el scope enclosing desde una función inner? Aquí introducimos superficialmente nonlocal: úsala para indicar que no es local ni global, sino del enclosing. Ejemplo rápido (agrega al archivo anterior):
def outer_nonlocal():
enclosing_var = "Enclosing inicial"
def inner_nonlocal():
nonlocal enclosing_var # Accede y modifica la del enclosing
enclosing_var = "Modificada"
print(enclosing_var) # Imprime "Modificada"
inner_nonlocal()
print(enclosing_var) # Imprime "Modificada" (cambiada)
outer_nonlocal()
Pythonnonlocal es útil en escenarios anidados simples, pero no lo abuses; mantén tus funciones lo más independientes posible.
Errores Comunes y Mejores Prácticas en Scope
Incluso programadores experimentados tropiezan con el scope. Un error común es asumir que una variable local es global, lo que lleva a NameError. Otro es modificar globals accidentalmente, causando efectos colaterales impredecibles.
Mejores prácticas: Prefiere variables locales para encapsular lógica. Usa globals solo para constantes (como configuraciones). Siempre declara global o nonlocal explícitamente si necesitas acceder a scopes superiores. Y recuerda LEGB en el debugging: cuando algo no se resuelva, pregúntate: “¿En qué orden busca Python?”
Practica estos conceptos variando los ejemplos. Modifica nombres, agrega prints y observa. Dominar el scope te hace un programador más preciso y confiable.
Resumen del Capítulo
- Scope básico: Las variables locales existen solo dentro de funciones; las globales, en todo el módulo. Usa
globalpara modificarlas desde funciones. - Regla LEGB: Python resuelve nombres en orden: Local (función actual), Enclosing (funciones anidadas), Global (módulo) y Built-in (funciones de Python como
print). - Ejemplos prácticos: Aprendimos a ejecutar código con
python archivo.py, vimos eclipsado de variables y modificación conglobalynonlocal(introducido superficialmente). - Mejores prácticas: Minimiza globals, declara accesos explícitamente y usa LEGB para depurar errores de nombres.
- Dominio final: Con analogías como “habitaciones” y ejemplos paso a paso, ahora entiendes cómo Python maneja la visibilidad de variables para escribir código robusto.