5.1 Funciones y parámetros
En Python, una función es un bloque de código que agrupa un conjunto de instrucciones para realizar una tarea concreta.
Su uso permite dividir un programa en partes más pequeñas y reutilizables, lo que mejora la organización, la legibilidad y el mantenimiento del código.
Las funciones pueden recibir datos de entrada, llamados parámetros, y devolver un resultado, utilizando la palabra clave return.
Este mecanismo es fundamental para construir programas modulares y evitar la repetición de código.
1️⃣ Definición y llamada de una función
Las funciones se definen en Python mediante la palabra clave def, seguida del nombre de la función, los parámetros entre paréntesis y el bloque de instrucciones indentado.
Para ejecutar una función, se realiza una llamada indicando su nombre y los argumentos correspondientes.
def saludar(nombre):
"""Muestra un saludo por pantalla."""
print(f"Hola, {nombre}!")
saludar("Ana")
defindica el comienzo de la definición.saludares el nombre de la función.nombrees el parámetro que recibe el valor al llamar a la función.print()ejecuta la acción principal de la función.- La última línea realiza la llamada pasando el argumento
"Ana".
🟩 Ventajas del uso de funciones
Las funciones aportan varias ventajas importantes al escribir programas:
- Reutilización del código: se puede invocar la misma función tantas veces como se necesite.
- Claridad: cada función agrupa instrucciones que cumplen una única finalidad.
- Mantenimiento sencillo: los cambios o correcciones se realizan en un único lugar.
- Pruebas más simples: cada función puede probarse de forma independiente.
def area_rectangulo(base, altura):
return base * altura
print(area_rectangulo(4, 3)) # 12
print(area_rectangulo(10, 2)) # 20
🟦 Estructura general de una función
La forma general de una función en Python es la siguiente:
def nombre_funcion(parámetros):
"""Descripción opcional (docstring)."""
# Bloque de instrucciones
return valor_opcional
defintroduce la definición.- El nombre debe seguir las reglas de los identificadores de Python.
- Los parámetros son los datos de entrada.
- El bloque indentado contiene las operaciones que realiza.
returndevuelve el resultado (puede omitirse si no se necesita devolver nada). Si la función no incluyereturn, devuelve implícitamenteNone.
🟨 Retornar múltiples valores
En Python, una función puede devolver más de un valor separándolos por comas. Internamente, Python agrupa estos valores en una tupla, que puede desempaquetarse fácilmente al recibirlos.
def dividir_y_resto(a, b):
"""Devuelve el cociente y el resto de una división entera."""
cociente = a // b
resto = a % b
return cociente, resto
c, r = dividir_y_resto(17, 5)
print(f"Cociente: {c}, Resto: {r}")
La función devuelve dos resultados: el cociente y el resto de la división.
Al llamar a la función, ambos valores se asignan simultáneamente a las variables c y r.
Esto permite obtener varios resultados sin necesidad de definir funciones adicionales.
2️⃣ Parámetros y argumentos
Los datos que recibe una función se denominan parámetros. Cuando se llama a la función, los valores reales que se envían se llaman argumentos.
Por ejemplo, en la función def sumar(a, b):, los nombres a y b son parámetros,
mientras que en la llamada sumar(3, 4) los valores 3 y 4 son argumentos.
Python permite utilizar varios tipos de parámetros:
- Posicionales: el orden importa.
- Nombrados (keyword arguments): se indican explícitamente.
- Con valores por defecto: tienen un valor predefinido.
- De solo posición o solo palabra clave: restringen cómo se pueden pasar los argumentos.
- Arbitrarios: permiten un número variable de argumentos (se verán en el punto 2).
🟩 Parámetros posicionales
Los parámetros posicionales son aquellos cuyo valor depende del orden en el que se pasan los argumentos. Son los más comunes.
def distancia(x1, y1, x2, y2):
"""Calcula la distancia entre dos puntos."""
return ((x2 - x1)**2 + (y2 - y1)**2) ** 0.5
print(distancia(0, 0, 3, 4)) # 5.0
Los valores 0, 0, 3, 4 se asignan a x1, y1, x2, y2 en ese orden.
Si se cambiara el orden, el resultado sería diferente.
🟦 keyword arguments
Los argumentos con nombre permiten especificar de forma explícita qué valor corresponde a cada parámetro, sin importar el orden. El uso de argumentos con nombre mejora la legibilidad y evita errores, especialmente en funciones con muchos parámetros.
print(distancia(x1=0, y1=0, x2=3, y2=4)) # 5.0
🟨 Valores por defecto
Un parámetro puede tener un valor por defecto, que se utiliza cuando no se especifica un argumento en la llamada.
def potencia(base, exponente=2):
"""Calcula la potencia de un número."""
return base ** exponente
print(potencia(5)) # 25
print(potencia(2, 10)) # 1024
El segundo parámetro exponente tiene un valor predeterminado de 2.
Por tanto, potencia(5) calcula el cuadrado y potencia(2,10) la potencia 2¹⁰.
Cuando se usan listas, diccionarios u otros objetos mutables como valores por defecto, estos persisten entre llamadas y pueden generar resultados inesperados.
def agregar(item, bolsa=[]):
bolsa.append(item)
return bolsa
print(agregar(1)) # [1]
print(agregar(2)) # [1, 2] ← comportamiento no deseado
El valor por defecto de bolsa se mantiene entre llamadas, porque se evalúa una única vez.
Esto provoca que la lista se comparta entre ejecuciones de la función.
def agregar(item, bolsa=None):
if bolsa is None:
bolsa = []
bolsa.append(item)
return bolsa
Usar None evita que la lista se comparta entre ejecuciones, creando una nueva cada vez.
🟧 Límites en parámetros
Python permite limitar cómo se pasan los argumentos usando los símbolos / y * en la definición.
def escalar(x, y, /, *, factor=1.0):
"""x e y son solo posicionales; factor solo por palabra clave."""
return (x * factor, y * factor)
print(escalar(3, 4, factor=2)) # (6, 8)
- Los parámetros antes de
/(en este casoxey) deben pasarse solo por posición. - Los parámetros después de
*(en este casofactor) deben pasarse solo con su nombre. Este mecanismo hace las funciones más claras y evita llamadas ambiguas.
3️⃣ Ámbito de las variables
El ámbito o alcance determina en qué partes del programa es visible una variable. Python sigue la regla LEGB para buscar nombres: Local → Enclosing (envolvente) → Global → Built-in.
x = 10 # variable global
def f():
x = 20 # variable local
print("x dentro de f:", x)
def g():
global x
x = 30 # modifica la variable global
print("x dentro de g:", x)
f()
print("x global:", x)
g()
print("x global tras g:", x)
La función f() crea una variable local diferente de la global.
En cambio, g() usa la palabra clave global para modificar la variable definida fuera.
🟩 Uso de nonlocal
Cuando una función se define dentro de otra, puede ser necesario modificar una variable del ámbito envolvente (no global).
Para ello se usa la palabra clave nonlocal.
def contador():
n = 0
def incrementar():
nonlocal n
n += 1
return n
return incrementar
c = contador()
print(c()) # 1
print(c()) # 2
nonlocal permite acceder y modificar una variable de una función envolvente.
En este caso, la variable n conserva su valor entre llamadas a la función interna.
4️⃣ Docstrings e indicadores de tipos
La documentación interna del código es fundamental para garantizar su comprensión, mantenimiento y reutilización. Python incorpora dos mecanismos complementarios para lograrlo: los docstrings y los indicadores de tipos. Ambos permiten que las funciones sean más claras, autoexplicativas y compatibles con herramientas de análisis estático.
🟩 Docstrings
Un docstring (documentation string) es una cadena de texto especial que describe el propósito y funcionamiento de una función, clase o módulo.
Se coloca inmediatamente después de la definición (def o class) y se encierra entre tres comillas dobles (""" ... """).
def saludar(nombre):
"""Muestra un saludo personalizado por pantalla."""
print(f"Hola, {nombre}!")
El texto entre triple comilla no se imprime, sino que actúa como documentación interna.
Puede consultarse en cualquier momento usando help(saludar) o saludar.__doc__.
Estructura recomendada
Para funciones más complejas se recomienda seguir el formato definido en la guía PEP 257:
- Una primera línea con una descripción breve y concisa.
- Una línea en blanco como separador.
- Información detallada sobre parámetros, valores devueltos y ejemplos.
def potencia(base, exponente=2):
"""
Calcula la potencia de un número.
Parámetros:
base (float): número base.
exponente (int, opcional): potencia a la que se eleva la base (por defecto, 2).
Devuelve:
float: resultado de base elevado a exponente.
"""
return base ** exponente
Este formato permite que la documentación sea legible tanto para personas como para herramientas automáticas, como pydoc o los editores de código que muestran ayuda contextual.
🟦 Indicadores de tipo (type hints)
Los indicadores de tipo especifican el tipo de datos que se espera en los parámetros y el tipo que la función devuelve. No modifican el comportamiento del programa, pero sirven como guía para el programador y facilitan el uso de analizadores estáticos (linters).
def calcular_media(valores: list[float]) -> float:
"""
Calcula la media aritmética de una lista de números.
Parámetros:
valores (list[float]): lista de valores numéricos.
Devuelve:
float: valor medio de todos los números de la lista.
"""
if not valores:
raise ValueError("La lista no puede estar vacía.")
return sum(valores) / len(valores)
valores: list[float]indica que el parámetro debe ser una lista de números reales.-> floatespecifica que la función devuelve un número de tipo real. Estas anotaciones mejoran la legibilidad y permiten detectar errores antes de ejecutar el código.
🟨 Relación entre docstrings y type hints
Ambos elementos tienen funciones distintas pero complementarias:
| Elemento | Función principal | Interpretado por |
|---|---|---|
| Docstring | Explica qué hace la función y cómo usarla | Personas, help(), generadores de documentación |
| Indicadores de tipo | Indican los tipos de datos esperados y devueltos | Editores, linters y analizadores estáticos |
Combinarlos ofrece una documentación completa tanto para el desarrollador como para las herramientas de análisis.
🟧 Ejemplo completo
def filtrar_mayores(valores: list[int], umbral: int = 0) -> list[int]:
"""
Devuelve una lista con los números mayores que el umbral indicado.
Parámetros:
valores (list[int]): lista de números enteros.
umbral (int, opcional): valor límite. Por defecto es 0.
Devuelve:
list[int]: lista con los valores que superan el umbral.
Ejemplo:
>>> filtrar_mayores([3, -1, 5, 0, 8], umbral=2)
[3, 5, 8]
"""
return [v for v in valores if v > umbral]
La combinación de docstring y anotaciones de tipo proporciona una descripción completa del comportamiento de la función. Esto hace que el código sea más auto-documentado, legible y mantenible, cumpliendo con las buenas prácticas del desarrollo profesional en Python.
✅ Buenas prácticas
- Utilizar nombres de función claros y descriptivos.
- Mantener las funciones breves y con un propósito definido.
- Evitar el uso de
globalsiempre que sea posible. - Documentar las funciones con docstrings.
- Emplear anotaciones de tipo para mejorar la legibilidad del código.
def media(valores: list[float]) -> float:
"""Calcula la media aritmética de una lista de números."""
return sum(valores) / len(valores)