🏭 Si construyes una planta química, lo ideal sería aislarla del mundo exterior para evitar fugas de productos químicos. Se podría decir que este edificio tiene su propio ambiente: un microclima separado del entorno externo.
En programación, este tipo de aislamiento se llama ámbito de visibilidad. En esta lección, hablaremos sobre los entornos en Python, cómo se dividen y cómo afectan el funcionamiento del código.
Ámbitos de visibilidad
Desde el punto de vista del entorno, los programas en Python se dividen en dos ámbitos de visibilidad:
- Global (externo)
- Local (interno)
Todo lo que creamos fuera de funciones, estructuras condicionales (if), bucles y otros bloques de código pertenece al ámbito global:
age = 29
def multiply(num):
x = 10
return num * x
result = True
En este caso, age, la función multiply() y result tienen un ámbito global.
Dentro de la función multiply(), la variable x tiene un ámbito local. Solo existe dentro de la función, lo que significa que no podemos acceder a x desde fuera:
def multiply(num):
x = 10
return num * x
print(x) # NameError: name 'x' is not defined
Aquí print(x) se ejecuta en el ámbito global, pero x no fue definida globalmente, por lo que Python lanza un NameError.
Si declaramos x como una variable global antes de la función, el resultado cambia:
x = 55
def multiply(num):
x = 10
return num * x
print(x) # 55
Ahora x existe en el ámbito global, pero el x dentro de multiply() sigue siendo local. Ambos son variables diferentes, aunque tengan el mismo nombre.
En Python, las variables locales no pueden accederse desde fuera, pero ¿qué pasa con las globales? Para entender esto, veamos la regla LEGB.
LEGB
Python busca nombres de variables siguiendo la regla LEGB, que se basa en los distintos ámbitos de visibilidad:
L- Local (Local): Variables dentro de una función, definidas en su cuerpo. Se crean en el momento de la ejecución de la función y desaparecen cuando la función termina.E- Enclosing (Encerrado): Se aplica a funciones anidadas. La función interna puede acceder a las variables de la función externa.G- Global (Global): Variables definidas fuera de cualquier función. Son accesibles en todo el código, excepto cuando hay una variable local con el mismo nombre dentro de una función.B- Built-in (Incorporado): Variables y funciones predefinidas en Python, comoprint(),len(),int(), etc.
⏬ Ejemplo de búsqueda de nombres con LEGB:
a = 42
def find():
def inner_find():
print(a)
# Invocamos la función interna
inner_find()
find() # => 42
Aquí, inner_find() busca a primero en su ámbito local. Como no la encuentra, sube al ámbito de find(), luego al global, donde finalmente la encuentra.
Sin embargo, si intentamos modificar a dentro de inner_find(), obtenemos un error:
a = 42
def find():
def inner_find():
print(a)
a = 5
inner_find()
find() # UnboundLocalError: local variable 'a' referenced before assignment
El error ocurre porque en inner_find() intentamos imprimir a antes de asignarle un valor. Python trata a a como una variable local dentro de la función porque la estamos redefiniendo, y aún no tiene un valor asignado cuando intentamos acceder a ella.
global y nonlocal
Python permite modificar el ámbito de las variables con las palabras clave global y nonlocal.
globalpermite modificar una variable global desde dentro de una función.
x = 42
def change():
global x
x = 12 # Modifica la variable global
change()
print(x) # 12
nonlocalpermite modificar variables de una función externa dentro de una función interna.
def outer():
x = 42
def inner():
nonlocal x # Modificamos la variable de la función externa
print('Nonlocal x =', x)
x = 12
inner()
print('New x =', x)
outer()
# Nonlocal x = 42
# New x = 12
⚠️ Evita usar global siempre que sea posible. Las variables globales pueden hacer que el código sea más difícil de mantener y depurar. Es mejor usar ámbitos locales y encapsular variables dentro de funciones o clases.
Closures
Un closure (cierre) es una función que conserva el acceso a las variables del entorno en el que fue definida, incluso después de que dicho entorno haya finalizado.
⏬ Ejemplo:
def create_print():
name = "King"
def print_name():
print(name)
return print_name
my_print = create_print()
my_print() # King
Aquí, create_print() define name y una función interna print_name(), que usa name. Cuando ejecutamos create_print(), nos devuelve print_name(), que aún recuerda la variable name, aunque la función create_print() ya terminó su ejecución.
Esto es posible porque la función interna "encierra" el valor de name, creando un cierre.
Resumen
- Python maneja variables a través de diferentes ámbitos de visibilidad: local, global, encerrado e incorporado.
- Usa la regla LEGB para buscar nombres de variables.
- Las palabras clave global y nonlocal permiten modificar variables en diferentes ámbitos, pero deben usarse con cuidado.
- Los cierres permiten a las funciones recordar el entorno donde fueron definidas, lo que las hace muy útiles para escribir código más modular y reutilizable.
Si entiendes bien estos conceptos, podrás escribir código más limpio, organizado y eficiente en Python.
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.