El ámbito de las variables en Python y la regla `LEGB` explicados
Aprende qué son los ámbitos de las variables y familiarízate con la regla «LEGB». También te encontrarás con situaciones en las que podrás ver las palabras clave globales y no locales en acción.
Ver «nombre no definido» o «variable local referenciada antes de la asignación» justo después de escribir unas pocas líneas es frustrante. El código parece correcto, pero Python no está de acuerdo. La causa principal es casi siempre el ámbito: dónde es visible un nombre y a qué objeto se refiere en ese momento. Una vez que comprendas la búsqueda de nombres en Python, que a menudo se resume como la regla LEGB, estos errores se vuelven predecibles y fáciles de solucionar. En este tutorial, explicaré paso a paso las variables y los ámbitos en Python.
¿Qué es una variable?
Una variable es un nombre vinculado a un objeto. En Python, se crea un enlace con el operador de asignación =. Los nombres no se escriben; pueden apuntar a cualquier objeto (cadena, entero, lista, función, etc.).
customer_name ="Ava Torres"
order_count =1
total_cents =1+2*300# evaluated first, then boundCon la tecnología de
Sigue estas reglas y convenciones al nombrar variables para evitar errores de sintaxis y errores sutiles.
Utiliza solo letras, dígitos y guiones bajos; los nombres no pueden comenzar con un dígito.
No utilices palabras clave como « True », « for » o « class » como nombres.
Evita ocultar funciones integradas como list, dict, sum o max.
Es preferible utilizar « snake_case » por motivos de legibilidad (PEP 8).
Estos ejemplos muestran lo que no se debe hacer y los errores que genera Python:
first string value ="First string"# spaces not allowed# SyntaxError: invalid syntax
1st_value =10# cannot start with a digit# SyntaxError: invalid decimal literalTrue="yes"# cannot assign to a keyword# SyntaxError: cannot assign to TrueCon la tecnología de
Cómo funciona el ámbito en Python (LEGB)
El ámbito es la región del código en la que un nombre es visible. Cuando utilizas un nombre, Python lo busca en este orden (LEGB):
Local: el ámbito de la función actual.
Encerrar: cualquier ámbito de función externo (para funciones anidadas).
Global: el nivel superior del módulo (espacio de nombres del módulo).
Integrado: nombres definidos por Python en builtins (por ejemplo, len, print).
Los nombres residen en espacios de nombres (piensa en diccionarios que asignan nombres a objetos). El ámbito se refiere a los espacios de nombres que Python consulta para resolver un nombre en un punto determinado del código.
Ámbito local
Los nombres asignados dentro de una función son locales para esa función, a menos que se declare lo contrario. No son visibles fuera de la función.
defshow_order_id():
order_id =42print("inside function:", order_id)
show_order_id()print("outside function:", order_id)# NameErrorCon la tecnología de
Python decide el ámbito en tiempo de compilación. Si una función asigna un nombre en cualquier parte de su cuerpo, todos los usos de ese nombre en la función se tratan como locales, lo que da lugar a un error común de « UnboundLocalError » (nombre no definido) cuando se lee antes de asignar:
discount_rate =0.10# module-level (global)defprice_with_discount(amount_cents):print("configured discount:", discount_rate)# looks local because of the assignment below
discount_rate =0.20# assignment makes 'discount_rate' local in this functionreturnint(amount_cents *(1- discount_rate))# UnboundLocalError: cannot access local variable 'discount_rate' where it is not associated with a valueCon la tecnología de
Para utilizar el nombre a nivel de módulo en la función, evita asignarle un valor o márcalo como « global » (se explica más adelante).
Ámbito de aplicación (cerramientos)
Las funciones anidadas pueden ver los nombres de la función que las envuelve inmediatamente. Para volver a vincular un nombre de este tipo (no solo leerlo), decláralo como nonlocal.
defmake_step_counter():
count =0# enclosing scope for 'increment'defincrement():nonlocal count # rebind the 'count' in the nearest enclosing function
count +=1return count
return increment
step = make_step_counter()print(step())# 1print(step())# 2Con la tecnología de
Sin nonlocal, asignar a count dentro de increment() crearía un nuevo nombre local y dejaría el count externo sin cambios.
Ámbito global
Los nombres asignados en el nivel superior de un módulo residen en el espacio de nombres global del módulo. Cualquier función puede leerlos. Para asignar un nombre a nivel de módulo desde dentro de una función, decláralo como global.
greeting ="Hello"defgreet_city(city_name):print(greeting, city_name)# reads globaldefset_greeting(new_greeting):global greeting
greeting = new_greeting # rebinds global
greet_city("Nairobi")# Hello Nairobi
set_greeting("Hi")
greet_city("Nairobi")# Hi NairobiCon la tecnología de
Utiliza global con moderación. Es preferible pasar valores como parámetros y devolver resultados para que el código sea comprobable y predecible.
Ámbito integrado (y una nota sobre las palabras clave)
El ámbito integrado contiene nombres como len, print y Exception. Evita sombrearlos, o perderás el acceso al integrado para ese ámbito.
list=[1,2,3]# shadows the built-in 'list' constructorlist("abc")# TypeError: 'list' object is not callabledellist# fix by deleting the shadowing nameCon la tecnología de
Las palabras clave (como if, for, def) forman parte de la sintaxis de Python, no del espacio de nombres integrado, y nunca pueden utilizarse como identificadores.
Bloques, bucles y comprensiones
Las sentencias de bloque y las comprensiones de Python tienen comportamientos de ámbito específicos que a menudo sorprenden a los programadores que provienen de otros lenguajes.
No hay ámbito de bloque para if/for/while/with
Las asignaciones dentro de estos bloques afectan al ámbito que los contiene (función o módulo). Las variables de bucle también permanecen definidas después de que finaliza el bucle.
ifTrue:
status ="ready"print(status)# "ready"for i inrange(3):passprint(i)# 2 (the last value from the loop)Con la tecnología de
Las comprensiones aíslan su variable de iteración.
Las comprensiones de listas, diccionarios y conjuntos tienen su propio ámbito local para las variables de bucle. La variable de iteración no se filtra en el ámbito circundante.
numbers =[1,2,3][x for x in numbers]print("x"inglobals()or"x"inlocals())# FalseCon la tecnología de
Python 3.12 (PEP 709) incorporó comprensiones en línea para aumentar la velocidad y preservar este aislamiento; sigues obteniendo variables de bucle claras y sin fugas con una ejecución más rápida.
Usando el global Palabra clave
Declara un nombre como « global » dentro de una función cuando necesites volver a vincular una variable a nivel de módulo. Coloca la declaración cerca de la parte superior de la función para que quede claro qué variable estás modificando.
tax_rate =0.08defconfigure_tax(rate):global tax_rate
tax_rate =float(rate)deftotal_with_tax(cents):returnint(cents *(1+ tax_rate))
configure_tax(0.10)print(total_with_tax(1000))# 1100Con la tecnología de
Usando el nonlocalPalabra clave
Utilizanonlocal para volver a vincular un nombre desde el ámbito de función más cercano que lo engloba. Esto es habitual en los cierres que mantienen el estado.
defmake_accumulator(start=0):
total = start
defadd(amount):nonlocal total
total += amount
return total
return add
acc = make_accumulator()print(acc(5))# 5print(acc(10))# 15Con la tecnología de
Usar nonlocal para un nombre no definido en una función envolvente es un error de tipo « SyntaxError ». Si el nombre es global, utiliza global en su lugar.
locals() y globals() en 2025
Las funcionesson útiles para la inspección y la depuración, no para actualizar variables. A partir de Python 3.13 (PEP 667), cada llamada a locals() en una función devuelve una instantánea independiente. Editar esa instantánea no cambia los datos locales reales. He confirmado este comportamiento ejecutando el siguiente fragmento de código en Python 3.13:
defprobe():
project ="alpha"
snap1 =locals()
snap1["project"]="beta"# edits the snapshot only
observed = project # still "alpha"
snap2 =locals()# new snapshotreturn snap1["project"], observed, snap2["project"]print(probe())# ('beta', 'alpha', 'alpha')Con la tecnología de
Utiliza globals() de forma similar para el espacio de nombres del módulo. Al escribir código de aplicación, es mejor utilizar parámetros y valores de retorno explícitos en lugar de búsquedas dinámicas.
Errores comunes y cómo solucionarlos
Estos errores representan la mayoría de los errores relacionados con el alcance que veo en la práctica.
UnboundLocalError de asignar en una función: Python trata un nombre como local si se asigna en cualquier parte de la funció. Mueve la lectura después de la asignación, cambia el nombre o añade global/no local según corresponda.
Esperando ámbito de bloque: Los nombres asignados en if/for/while/with ( ) persisten en el ámbito que los contiene. Utiliza funciones auxiliares más estrictas para limitar el alcance.
Sombras integradas:Evita nombres de identificadores como «list», «dict», «sum», «id» o «min». Elige nombres descriptivos como « customer_list » o « min_allowed ».
Olvidar nonlocal en los cierres: Si deseas actualizar una variable de función externa, declárala como no local. De lo contrario, se crea una nueva variable local y el valor externo no cambia.
Confusión entre palabras clave y funciones integradas: Las palabras clave (sintaxis) no pueden utilizarse como nombres, en ningún caso. Los elementos integrados pueden ocultarse, pero no deberían hacerlo.
Mejores prácticas para mantener un alcance sencillo
Estos hábitos facilitan la lectura, las pruebas y la depuración del código.
Da prioridad a las funciones pequeñas y específicas. Define las variables en el ámbito más restringido posible.
Pasar datos entrantes y salientes a través de parámetros y valores de retorno. Minimizar el estado a nivel de módulo.
Utiliza los cierres de forma intencionada. Documenta qué nombre externo captura la función anidaday utiliza nonlocal cuando realmente necesites volver a vincular.
Eligenombres descriptivosy que no den lugar a conflictos. Un guión bajo inicial (por ejemplo, _cache) indica uso interno.
Tratadlocals()/globals() como diagnósticos de solo lectura, no como un mecanismo de configuración.
Conclusión
Python resuelve los nombres buscando en los ámbitos Local → Enclosing → Global → Built-in. Comprender ese orden —y cuándo utilizar global o no local— elimina errores comunes como NameError y UnboundLocalError. Mantén las variables en el ámbito más pequeño posible, evita ocultar las funciones integradas y utiliza los cierres de forma deliberada. Con ese modelo mental, tus funciones se comportan de manera predecible y el ámbito deja de ser una fuente de sorpresas.
Aprende sobre las funciones lambda de Python, su finalidad y cuándo utilizarlas. Incluye ejemplos prácticos y mejores prácticas para una implementación eficaz.
Aprende sobre la regresión logística, sus propiedades básicas, y construye un modelo de machine learning sobre una aplicación del mundo real en Python.
Aprende a crear e importar módulos de Python. ¡Descubre las mejores prácticas, ejemplos y consejos para escribir código Python reutilizable, organizado y eficiente!
Aborda los fundamentos de la Programación Orientada a Objetos (POO) en Python: explora las clases, los objetos, los métodos de instancia, los atributos y ¡mucho más!
Explora el match-case de Python: una guía sobre su sintaxis, aplicaciones en ciencia de datos, ML, y un análisis comparativo con el switch-case tradicional.
Aprende sobre los conjuntos en Python: qué son, cómo crearlos, cuándo usarlos, funciones incorporadas y su relación con las operaciones de la teoría de conjuntos.
Ver «nombre no definido» o «variable local referenciada antes de la asignación» justo después de escribir unas pocas líneas es frustrante. El código parece correcto, pero Python no está de acuerdo. La causa principal es casi siempre el ámbito: dónde es visible un nombre y a qué objeto se refiere en ese momento. Una vez que comprendas la búsqueda de nombres en Python, que a menudo se resume como la regla LEGB, estos errores se vuelven predecibles y fáciles de solucionar. En este tutorial, explicaré paso a paso las variables y los ámbitos en Python.
¿Qué es una variable?
Una variable es un nombre vinculado a un objeto. En Python, se crea un enlace con el operador de asignación
=. Los nombres no se escriben; pueden apuntar a cualquier objeto (cadena, entero, lista, función, etc.).Sigue estas reglas y convenciones al nombrar variables para evitar errores de sintaxis y errores sutiles.
True», «for» o «class» como nombres.list,dict,sumomax.snake_case» por motivos de legibilidad (PEP 8).Estos ejemplos muestran lo que no se debe hacer y los errores que genera Python:
Cómo funciona el ámbito en Python (
LEGB)El ámbito es la región del código en la que un nombre es visible. Cuando utilizas un nombre, Python lo busca en este orden (LEGB):
builtins(por ejemplo,len,print).Los nombres residen en espacios de nombres (piensa en diccionarios que asignan nombres a objetos). El ámbito se refiere a los espacios de nombres que Python consulta para resolver un nombre en un punto determinado del código.
Ámbito local
Los nombres asignados dentro de una función son locales para esa función, a menos que se declare lo contrario. No son visibles fuera de la función.
Python decide el ámbito en tiempo de compilación. Si una función asigna un nombre en cualquier parte de su cuerpo, todos los usos de ese nombre en la función se tratan como locales, lo que da lugar a un error común de «
UnboundLocalError» (nombre no definido) cuando se lee antes de asignar:Para utilizar el nombre a nivel de módulo en la función, evita asignarle un valor o márcalo como «
global» (se explica más adelante).Ámbito de aplicación (cerramientos)
Las funciones anidadas pueden ver los nombres de la función que las envuelve inmediatamente. Para volver a vincular un nombre de este tipo (no solo leerlo), decláralo como
nonlocal.Sin
nonlocal, asignar acountdentro deincrement()crearía un nuevo nombre local y dejaría elcountexterno sin cambios.Ámbito global
Los nombres asignados en el nivel superior de un módulo residen en el espacio de nombres global del módulo. Cualquier función puede leerlos. Para asignar un nombre a nivel de módulo desde dentro de una función, decláralo como
global.Utiliza
globalcon moderación. Es preferible pasar valores como parámetros y devolver resultados para que el código sea comprobable y predecible.Ámbito integrado (y una nota sobre las palabras clave)
El ámbito integrado contiene nombres como
len,printyException. Evita sombrearlos, o perderás el acceso al integrado para ese ámbito.Las palabras clave (como
if,for,def) forman parte de la sintaxis de Python, no del espacio de nombres integrado, y nunca pueden utilizarse como identificadores.Bloques, bucles y comprensiones
Las sentencias de bloque y las comprensiones de Python tienen comportamientos de ámbito específicos que a menudo sorprenden a los programadores que provienen de otros lenguajes.
No hay ámbito de bloque para
if/for/while/withLas asignaciones dentro de estos bloques afectan al ámbito que los contiene (función o módulo). Las variables de bucle también permanecen definidas después de que finaliza el bucle.
Las comprensiones aíslan su variable de iteración.
Las comprensiones de listas, diccionarios y conjuntos tienen su propio ámbito local para las variables de bucle. La variable de iteración no se filtra en el ámbito circundante.
Python 3.12 (PEP 709) incorporó comprensiones en línea para aumentar la velocidad y preservar este aislamiento; sigues obteniendo variables de bucle claras y sin fugas con una ejecución más rápida.
Usando el
globalPalabra claveDeclara un nombre como «
global» dentro de una función cuando necesites volver a vincular una variable a nivel de módulo. Coloca la declaración cerca de la parte superior de la función para que quede claro qué variable estás modificando.Usando el
nonlocalPalabra claveUtiliza
nonlocalpara volver a vincular un nombre desde el ámbito de función más cercano que lo engloba. Esto es habitual en los cierres que mantienen el estado.Usar
nonlocalpara un nombre no definido en una función envolvente es un error de tipo «SyntaxError». Si el nombre es global, utilizaglobalen su lugar.locals()yglobals()en 2025Las funcionesson útiles para la inspección y la depuración, no para actualizar variables. A partir de Python 3.13 (PEP 667), cada llamada a locals() en una función devuelve una instantánea independiente. Editar esa instantánea no cambia los datos locales reales. He confirmado este comportamiento ejecutando el siguiente fragmento de código en Python 3.13:
Utiliza
globals()de forma similar para el espacio de nombres del módulo. Al escribir código de aplicación, es mejor utilizar parámetros y valores de retorno explícitos en lugar de búsquedas dinámicas.Errores comunes y cómo solucionarlos
Estos errores representan la mayoría de los errores relacionados con el alcance que veo en la práctica.
UnboundLocalErrorde asignar en una función: Python trata un nombre como local si se asigna en cualquier parte de la funció. Mueve la lectura después de la asignación, cambia el nombre o añade global/no local según corresponda.customer_list» o «min_allowed».nonlocalen los cierres: Si deseas actualizar una variable de función externa, declárala como no local. De lo contrario, se crea una nueva variable local y el valor externo no cambia.Mejores prácticas para mantener un alcance sencillo
Estos hábitos facilitan la lectura, las pruebas y la depuración del código.
_cache) indica uso interno.Conclusión
Python resuelve los nombres buscando en los ámbitos Local → Enclosing → Global → Built-in. Comprender ese orden —y cuándo utilizar global o no local— elimina errores comunes como
NameErroryUnboundLocalError. Mantén las variables en el ámbito más pequeño posible, evita ocultar las funciones integradas y utiliza los cierres de forma deliberada. Con ese modelo mental, tus funciones se comportan de manera predecible y el ámbito deja de ser una fuente de sorpresas.