1. Scope y Variables
2. Funciones vs Procedimientos
3. Ámbito Anidado

Ámbito y Procedimientos

Para construir programas más grandes y robustos, es vital entender dónde "viven" y "mueren" nuestros datos, y qué tipo de bloques de código construimos para procesarlos.

Inicializando Motor de Python... (Espera un momento)

1. El Ámbito (Scope) y las Variables

Repasemos lo que ya sabemos: cuando declaramos una variable dentro de un bloque def, esa variable nace y muere exclusivamente allí adentro. Fuera de la función, es como si nunca hubiera existido. A esto lo conocemos como Variable Local.

El Ámbito (Scope) es justamente eso: la región o "contexto" del código donde una variable existe y desde donde puede ser leída o modificada.

Variables Globales y la palabra `global`

Si creamos una variable en la raíz de nuestro programa (afuera de cualquier def), estamos creando una Variable Global. Todo el programa puede verla.

El problema: Si dentro de una función intentas modificar esa variable global, Python creerá por defecto que quieres crear una nueva variable local con el mismo nombre. Para decirle a la computadora "No crees una nueva, quiero alterar la global", usamos la instrucción global.

Actividad 1

Contador de Intentos

En el siguiente simulador de seguridad, cada vez que se llama a registrar_fallo(), la variable intentos debe aumentar en 1. Modifica el código utilizando global para que no lance un error (UnboundLocalError).

2. Funciones vs. Procedimientos

Hasta ahora, hemos llamado "funciones" a todos los bloques de código que definimos con def. Sin embargo, en Ciencias de la Computación existe una distinción técnica muy importante dependiendo de qué hace ese bloque al finalizar.

La diferencia fundamental:
Un Procedimiento es un bloque de código que realiza una tarea específica pero no devuelve un valor directamente (carece de la instrucción return). Su propósito es ejecutar acciones, como modificar variables globales o procesar parámetros externos.

Una Función, en cambio, procesa datos y siempre devuelve un resultado utilizando return. No debería alterar el exterior directamente.

El Procedimiento

Modifica una variable global destinada a guardar el resultado, pero no retorna nada al lugar donde fue invocado.

num_1 = 4
num_2 = 3
resultado = None

def suma_proc(valor_1, valor_2):
    global resultado
    resultado = valor_1 + valor_2

suma_proc(num_1, num_2)
print(resultado) # Imprime 7

La Función

Calcula el valor y lo devuelve directamente usando return. El resultado se guarda desde afuera.

num_1 = 4
num_2 = 3

def suma_func(valor_1, valor_2):
    return valor_1 + valor_2

resultado = suma_func(num_1, num_2)
print(resultado) # Imprime 7
Buenas Prácticas de Software:
Si bien es posible programar un bloque que realice acciones (modifique globales) y que además devuelva un valor con return, hacer ambas cosas a la vez se considera una mala práctica. Dificulta la lectura del código y el rastreo de errores. ¡Diseña tu bloque como Función o como Procedimiento, pero no ambos!
Actividad 2

Construyendo un Procedimiento

Convierte este código en un procedimiento puro. Modifica la variable global estado_sistema desde adentro usando global.

3. Ámbito Anidado y nonlocal

En Python es completamente válido crear funciones dentro de otras funciones. Al hacer esto, se genera un ámbito intermedio (Ámbito Anidado). Existen variables que son locales para la "función madre", pero desde el punto de vista de la "función hija", no son ni locales ni globales.

Para indicarle a la función interna que queremos modificar la variable de su función contenedora, utilizamos la palabra reservada nonlocal.

# 1. Ámbito Global
variable_global = 10

def procedimiento_madre():
    # 2. Ámbito Local de la madre (No es local para la hija)
    variable_intermedia = 20
    
    def procedimiento_hija():
        global variable_global
        nonlocal variable_intermedia
        
        # Ahora podemos modificarlas sin crear variables nuevas
        variable_global = 100
        variable_intermedia = 200
Actividad 3

Laboratorio de Ámbitos

Analiza el siguiente código extraído de la teoría. Ejecútalo y observa qué valores se imprimen al final. Presta mucha atención a la indentación y al flujo de llamadas.