Clase 4
Funciones Lambda y
Programación modular
Clase 4 Contenido de la clase
1. Correspondencia de parámetros
2. Parámetros mutables e inmutables
Funciones 3. Funciones que retornan más de un valor
Lambda y 4. Funciones Lambda
Programa- a. map
ción b. filter
modular
c. reduce
5. Módulos
6. Paquetes
Correspondencia de parámetros
Parámetros Formales con Valores por Omisión: En Python, puedes asignar valores por
omisión a los parámetros formales de una función. Esto permite que la función se ejecute
incluso si algunos argumentos no se proporcionan.
def saludo(nombre="Estudiante"):
print(f"Hola, {nombre}!")
saludo() # Hola, Estudiante!
saludo(“Pablo") # Hola, Pablo!
Parámetros Reales Pasados por Nombre: Al invocar una función, puedes pasar los
argumentos nombrándolos explícitamente, lo que mejora la claridad y flexibilidad.
def datos_persona(nombre, edad, ciudad):
print(f"{nombre} tiene {edad} años y vive en {ciudad}.")
datos_persona(edad=30, ciudad="Buenos Aires", nombre="Ana")
# Salida: Ana tiene 30 años y vive en Buenos Aires.
Parámetros mutables e inmutables
En Python, los tipos de datos como enteros (int), flotantes (float) y cadenas (str) son
inmutables, lo que significa que no permiten modificar el valor del objeto original.
Cuando se realiza una operación que “modifica” su valor, en realidad se crea un
nuevo objeto con el nuevo valor, y la variable pasa a referenciar ese nuevo objeto.
En cambio, las listas (list), diccionarios (dict) y conjuntos (set) son mutables, es decir
que sí permiten cambiar el contenido del objeto sin crear uno nuevo: la variable
sigue apuntando al mismo objeto que ha sido modificado internamente.
# Parámetros inmutables # Parámetros mutables
nombre = "Juan" dias = ['Lun', 'Mar', 'Mie']
print(nombre, id(nombre)) print(dias, id(dias))
nombre = "Luciana" dias.append('Jue')
print(nombre, id(nombre)) print(dias, id(dias))
Juan 2369614861904 ['Lun', 'Mar', 'Mie'] 2369611749632
Luciana 2369614862240 ['Lun', 'Mar', 'Mie', 'Jue'] 2369611749632
Parámetros mutables e inmutables
Demostración de la mutabilidad / inmutabilidad
def incrementar_numero(numero):
def agregar_elemento(lista, elemento):
numero += 1
lista.append(elemento)
return numero
nombres = ['Juan', 'Ana', 'Luis']
edad = 55
print(id(nombres)) # Misma referencia
print(id(edad)) # Distinta referencia
agregar_elemento(nombres, 'Luciana')
print(edad)
print(nombres)
edad = incrementar_numero(edad)
print(id(nombres)) # Misma referencia
print(id(edad)) # Distinta referencia
print()
print(edad)
['Juan', 'Ana', 'Luis'] 55
2203886541056 140714913906808
['Juan', 'Ana', 'Luis', 'Luciana'] 56
2203886541056 140714913906840
Funciones que retornan más de un valor
En Python, las funciones pueden retornar múltiples valores separados por comas.
Estos valores se pueden capturar en múltiples variables o en una tupla.
def operaciones(a, b):
suma = a + b
resta = a - b
return suma, resta
resultado_suma, resultado_resta = operaciones(5, 3)
print(resultado_suma) # 8
print(resultado_resta) # 2
Funciones Lambda
• Se definen con la palabra clave lambda.
• Funciones anónimas
• Útiles para operaciones pequeñas y rápidas
• Se pueden combinar con funciones como map, filter y reduce.
lambda parâmetros: expression.
Función tradicional convertida en función lambda:
def suma(a,b): # lambda parámetros: expresión
return a + b sumaLambda = lambda a, b: a + b
print(suma(2, 3)) # 5 print(sumaLambda(2, 3)) # 5
Funciones Lambda: map, filter y reduce
• map: aplica una función a todos los elementos de un iterable y devuelve un nuevo
iterable con los resultados. Sintaxis:
map(funcion, iterable)
numeros = [1, 2, 3, 4, 5]
duplicados = list(map(lambda x: x * 2, numeros))
print(duplicados) # [2, 4, 6, 8, 10]
Usando map junto con lambda: lambda x: x * 2 duplicamos cada número en la lista. Esta
función toma un número x y devuelve x multiplicado por 2. La función map aplica esta función
lambda a cada elemento de la lista numeros, creando un nuevo iterable con los resultados.
Luego convertimos este iterable en una lista utilizando list() y finalmente, imprimimos la lista
resultante.
Funciones Lambda: map, filter y reduce
• filter: aplica una función a todos los elementos de un iterable y devuelve un
nuevo iterable con los elementos que cumplen la condición especificada en la
función. Sintaxis:
filter(funcion, iterable)
numeros = [1, 2, 3, 4, 5]
impares = list(filter(lambda x: x % 2 != 0, numeros))
print(impares) # [1, 3, 5]
Usando filter junto con lambda: lambda x: x % 2 != 0 filtramos los números impares de la lista.
La función lambda toma un número x y devuelve True si el número es impar o False en caso
contrario. A través de filter, esa función lambda es aplicada a cada elemento de la lista,
creando un nuevo iterable que contiene solo los elementos que cumplen la condición. Luego
convertimos este iterable en una lista utilizando list() y finalmente, imprimimos la lista
resultante.
Funciones Lambda: map, filter y reduce
• reduce: aplica una función a los elementos de un iterable de manera
acumulativa, reduciéndolos a un solo valor. Esta función se encuentra en el
módulo functools. Sintaxis:
reduce(funcion, iterable)
from functools import reduce
numeros = [1, 2, 3, 4, 5]
producto = reduce(lambda x, y: x * y, numeros)
print(producto) # 120
La función lambda: lambda x, y: x * y se aplica acumulativamente a los elementos de la lista.
La función reduce empieza multiplicando los dos primeros elementos (1 y 2), luego multiplica
el resultado por el siguiente elemento (3), y así sucesivamente hasta que todos los elementos
hayan sido procesados. Finalmente, se imprime el producto de todos los elementos.
Módulos
En Python los módulos son archivos .py que contienen definiciones y variables
relacionadas que se pueden importar en otros archivos para reutilizar sus
funcionalidades.
Un módulo es un archivo de Python cuyas funciones pueden ser accedidas desde
otro archivo. Constituye una muy buena herramienta para organizar el código en
proyectos grandes o complejos.
Ejemplo:
1
# aritmetica.py 2
def suma(a, b): import aritmetica
return a + b print(aritmetica.suma(5, 3)) # 8
print(aritmetica.resta(5, 3)) # 2
def resta(a, b):
return a - b
1. Crear un módulo aritmética.py
2. Usar el módulo en otro archivo
Módulos
Al utilizar import <nombreModulo> estamos importando un módulo completo a
nuestro programa.
Al utilizar una función debemos indicar el módulo al que pertenece
<nombreModulo>.<nombreFuncion>
Además, es posible importar funciones directamente, ahorrando memoria. Para ello
se utiliza la sintaxis from … import … :
from modulo import funcion
from modulo import funcion1, funcion2
Para importar todas las funciones con la sintaxis from import se utiliza un
asterisco:
from modulo import *
Paquetes
• Un paquete es un directorio que contiene varios módulos y un archivo __init__.py.
• Pueden ser organizados en subdirectorios, permitiendo un mejor manejo de
grandes proyectos.
• Utilizar paquetes permite unificar distintos módulos bajo un mismo nombre, con
una jerarquía de módulos y submódulos (o subpaquetes). Permiten distribuir y
manejar el código como si fuesen librerías instalables de Python.
Esta jerarquía de carpetas se puede
expandir tanto como sea necesario
creando subpaquetes, siempre añadiendo
el archivo __init__.py en cada uno de ellos.
Paquetes | Estructura y uso
Supongamos que queremos crear un paquete para manejar operaciones matemáticas
avanzadas. La estructura del paquete sería la siguiente:
Cada módulo contendrá lo siguiente:
1. __init__.py: Este archivo indica que el directorio mi_paquete debe ser tratado como
un paquete. Puede estar vacío o contener código de inicialización del paquete.
# mi_paquete/__init__.py
from .algebra import suma, resta
from .geometria import area_circulo
Paquetes | Estructura y uso
Cada módulo contendrá lo siguiente:
2. algebra.py: Módulo que contiene funciones de operaciones algebraicas.
# mi_paquete/algebra.py
def suma(a, b):
return a + b
def resta(a, b):
return a - b
3. geometria.py: Módulo que contiene funciones relacionadas con geometría.
# mi_paquete/geometria.py
import math
def area_circulo(radio):
return math.pi * radio**2
Paquetes | Estructura y uso
Una vez que hayas creado el paquete, puedes utilizarlo en un programa Python de la
siguiente manera:
• Paquete (mi_paquete): Un
# programa_principal.py directorio que contiene
import mi_paquete varios módulos
relacionados.
resultado_suma = mi_paquete.suma(5, 3) • Módulo (algebra.py,
resultado_resta = mi_paquete.resta(5, 3) geometria.py): Archivos
area = mi_paquete.area_circulo(10) Python que contienen
funciones específicas.
• __init__.py: Permite que el
print(f"Suma: {resultado_suma}") # Suma: 8
directorio sea tratado como
print(f"Resta: {resultado_resta}") # Resta: 2 un paquete y se puede
print(f"Área del círculo: {area}") # Área del utilizar para importar
círculo: 314.159... funciones y organizarlas.
Paquetes | El rol de __init __.py
• En conclusión, el archivo __init__.py está pensado para:
▪ Indicar que el directorio es un paquete.
▪ Definir qué cosas se exponen al importar el paquete (una especie de "interfaz de
acceso").
El archivo __init__.py no está pensado para ejecutar código de uso del paquete,
pero sí para que los usuarios puedan hacer uso de las funciones que hay en él
desde un archivo externo.
Paquetes | El código de __init __.py
# mi_paquete/__init__.py
from .algebra import suma, resta
from .geometria import area_circulo
• from .algebra import suma, resta: Esto importa las funciones suma y resta del
módulo algebra que está dentro del paquete mi_paquete.
El prefijo . indica que se está importando desde el mismo paquete (es decir, desde el
módulo algebra dentro de mi_paquete).
• from .geometria import area_circulo: Similar al anterior, esto importa la función
area_circulo desde el módulo geometria dentro del paquete mi_paquete.
Paquetes | El código de __init __.py
¿Por qué es útil?
Cuando alguien importa el paquete mi_paquete, por ejemplo: import mi_paquete
Gracias al código en __init__.py, podrá acceder directamente a las funciones
importadas como si fueran parte del paquete principal:
resultado_suma = mi_paquete.suma(5, 3)
resultado_resta = mi_paquete.resta(5, 3)
area = mi_paquete.area_circulo(10)
Esto simplifica el acceso a las funciones del paquete sin necesidad de importar cada
módulo individualmente. Es decir, en lugar de escribir:
from mi_paquete.algebra import suma
from mi_paquete.geometria import area_circulo
El usuario puede simplemente puede importar el paquete y acceder directamente a
las funciones que se deseen exponer.
La variable especial __name__
En Python, el uso de if __name__ == "__main__": es una práctica común que permite definir un
punto de entrada para la ejecución de un script. Este mecanismo distingue si un archivo Python
está siendo ejecutado directamente desde la consola o si está siendo importado como un
módulo en otro archivo.
¿Qué es __name__?
• __name__: Es una variable especial en Python que se define automáticamente cuando se
ejecuta un archivo. Su valor depende de cómo se ejecuta el archivo.
a. Si el archivo se ejecuta directamente, la variable __name__ vale "__main__".
b. Si el archivo se importa como un módulo, la variable __name__ vale el nombre del archivo
(sin la extensión .py).
¿Para qué sirve if __name__ == "__main__":?
Permite controlar qué parte del código se ejecuta automáticamente.
✅ Si el archivo se ejecuta directamente, el bloque dentro del if se ejecuta.
❌ Si el archivo se importa, ese bloque no se ejecuta automáticamente, lo que permite que el
archivo funcione como un módulo reutilizable sin que se ejecute código no deseado.
La variable especial __name__
Ejemplo:
Importante: Al ejecutar otro_script.py No
se imprime el mensaje "El archivo
mi_script.py está siendo ejecutado
directamente", porque el bloque if
__name__ == "__main__": fue ignorado (ya
que mi_script.py fue importado, no
ejecutado directamente).
La variable especial __name__
¿Qué pasa cuando se ejecuta un archivo directamente?
Cuando un archivo Python se ejecuta directamente (por ejemplo, mi_script.py), la variable
especial __name__ toma el valor "__main__". En ese caso, se ejecuta el bloque de código que está
dentro de: if __name__ == "__main__": ...
Este bloque suele contener la llamada a la función main() u otras instrucciones que solo
queremos que se ejecuten cuando el archivo es el programa principal.
¿Qué pasa cuando se importa un archivo?
Cuando se importa un archivo Python desde otro archivo (por ejemplo, import mi_script en
otro_script.py), el valor de __name__ dentro de mi_script.py no será "__main__", sino que será
"mi_script" (el nombre del archivo sin la extensión .py). Como __name__ != "__main__" en ese caso,
el bloque: if __name__ == "__main__": ... no se ejecuta automáticamente, lo que permite
que mi_script funcione como un módulo reutilizable. Esto significa que podemos usar sus
funciones y variables desde otro archivo sin que se ejecute ningún código que esté destinado
solo a la ejecución directa.
Lectura recomendada
• Bibliografía obligatoria de la materia
• MARZAL VARÓ, Andres; GRACIA LUENGO, Isabel; GARCÍA SEVILLA, Pedro.
Introducción a la programación con Python 3 [En línea]. Disponible gratuitamente
bajo licencia Creative Commons en https://core.ac.uk/download/pdf/61441326.pdf
[consulta realizada el día 24/7/2024]
• The Python Tutorial - Python 3.12.4 documentation:
https://docs.python.org/3/tutorial/
• Python Tutorial - w3schools: https://www.w3schools.com/python/
Material complementario sobre __main__ y __name__:
https://www.youtube.com/watch?v=sugvnHA7ElY
Tarea para el Proyecto Final
• Funciones lambda: Aplicar funciones lambda para las matrices del proyecto. Por
ejemplo, para modificar un valor numérico (obtener descuento, incremento,
diferencias entre valores, etc) o para filtrar elementos que cumplan con cierta/s
condición/es.
• Módulos y paquetes: Modularizar el código del proyecto, organizando las
funciones relacionadas en módulos reutilizables y organizar los archivos en
paquetes. Realizar la importación de los módulos cuando considere necesario.