Ir al contenido principal

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.
Actualizado 11 sept 2025  · 8 min de lectura

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 bound

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 literal

True = "yes"  # cannot assign to a keyword
# SyntaxError: cannot assign to True

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.

def show_order_id():
    order_id = 42
    print("inside function:", order_id)

show_order_id()
print("outside function:", order_id)  # NameError

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)

def price_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 function
    return int(amount_cents * (1 - discount_rate))

# UnboundLocalError: cannot access local variable 'discount_rate' where it is not associated with a value

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.

def make_step_counter():
    count = 0  # enclosing scope for 'increment'

    def increment():
        nonlocal count  # rebind the 'count' in the nearest enclosing function
        count += 1
        return count

    return increment

step = make_step_counter()
print(step())  # 1
print(step())  # 2

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"

def greet_city(city_name):
    print(greeting, city_name)  # reads global

def set_greeting(new_greeting):
    global greeting
    greeting = new_greeting     # rebinds global

greet_city("Nairobi")  # Hello Nairobi
set_greeting("Hi")
greet_city("Nairobi")  # Hi Nairobi

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' constructor
list("abc")          # TypeError: 'list' object is not callable
del list             # fix by deleting the shadowing name

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.

if True:
    status = "ready"
print(status)  # "ready"

for i in range(3):
    pass
print(i)  # 2 (the last value from the loop)

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" in globals() or "x" in locals())  # False

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.08

def configure_tax(rate):
    global tax_rate
    tax_rate = float(rate)

def total_with_tax(cents):
    return int(cents * (1 + tax_rate))

configure_tax(0.10)
print(total_with_tax(1000))  # 1100

Usando el nonlocal Palabra clave

Utiliza nonlocal 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.

def make_accumulator(start=0):
    total = start
    def add(amount):
        nonlocal total
        total += amount
        return total
    return add

acc = make_accumulator()
print(acc(5))   # 5
print(acc(10))  # 15

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:

def probe():
    project = "alpha"
    snap1 = locals()
    snap1["project"] = "beta"  # edits the snapshot only
    observed = project         # still "alpha"
    snap2 = locals()           # new snapshot
    return snap1["project"], observed, snap2["project"]

print(probe())  # ('beta', 'alpha', 'alpha')

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.


Sejal Jaiswal's photo
Author
Sejal Jaiswal
LinkedIn

Llevo varios sombreros: Desarrollador de Software, Programador, Científico de Datos, Desarrollador de Inteligencia de Negocio, Propietario de Producto

Temas

Más información sobre Python

Curso

Introducción a Python

4 h
6.5M
Domina los fundamentos del análisis de datos con Python en cuatro horas y descubre sus paquetes más usados.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado

Tutorial

Funciones lambda de Python: Guía para principiantes

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.
Mark Pedigo's photo

Mark Pedigo

Python

Tutorial

Comprender la regresión logística en el tutorial de Python

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.
Avinash Navlani's photo

Avinash Navlani

Tutorial

Tutorial de módulos de Python: Importarlos, escribirlos y utilizarlos

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!

Nishant Kumar

Tutorial

Programación orientada a objetos (POO) en Python: Tutorial

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!
Théo Vanderheyden's photo

Théo Vanderheyden

Tutorial

Declaración de caso de cambio en Python: Guía para principiantes

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.
Matt Crabtree's photo

Matt Crabtree

Tutorial

Tutorial de Python sobre conjuntos y teoría de conjuntos

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.
DataCamp Team's photo

DataCamp Team

Ver másVer más