Funciones básicas
Al completar este módulo serás capaz de:
- Entender qué son las funciones y por qué usarlas
- Crear funciones con
def - Usar parámetros y argumentos
- Devolver valores con
return - Entender el scope de variables
¿Por qué necesitas funciones?
Imagina que eres chef en un restaurante. Cada vez que un cliente pide una tortilla, podrías explicar desde cero cómo batir huevos, qué sartén usar, cuánto aceite añadir… O podrías tener una receta que sigues siempre. La receta se escribe una vez y se usa mil veces.
Las funciones son las recetas de la programación. En lugar de repetir el mismo código una y otra vez, lo escribes una vez, le das un nombre, y lo usas cuando lo necesites.
Los problemas de no usar funciones
Mira este código sin funciones:
1# Calcular el área de un rectángulo de 5x3
2area1 = 5 * 3
3print(f"Área: {area1}")
4
5# Calcular el área de otro rectángulo de 10x7
6area2 = 10 * 7
7print(f"Área: {area2}")
8
9# Y otro más de 8x4
10area3 = 8 * 4
11print(f"Área: {area3}")¿Qué pasa si ahora quieres añadir el perímetro también? Tendrías que modificar tres lugares. ¿Y si tienes 50 rectángulos? Se convierte en una pesadilla.
El principio DRY: Don’t Repeat Yourself
En programación existe una regla de oro: no te repitas. Si copias y pegas código, algo está mal. Las funciones son la solución:
1def calcular_area(base, altura):
2 return base * altura
3
4# Ahora es fácil y limpio
5print(f"Área: {calcular_area(5, 3)}")
6print(f"Área: {calcular_area(10, 7)}")
7print(f"Área: {calcular_area(8, 4)}")- Reutilización: Escribe una vez, usa muchas veces
- Organización: Divide problemas grandes en piezas pequeñas
- Legibilidad:
calcular_precio()es más claro que 20 líneas de código - Mantenimiento: Si hay un bug, lo arreglas en un solo lugar
Tu primera función
Una función es como una caja mágica: le metes algo (entrada), hace su trabajo (procesamiento), y te devuelve algo (salida).
graph LR
A["Entrada<br/>(parámetros)"] --> B["Función<br/>procesamiento"]
B --> C["Salida<br/>(return)"]Sintaxis básica
1def nombre_de_la_funcion(parametro1, parametro2):
2 # Cuerpo de la función (lo que hace)
3 resultado = parametro1 + parametro2
4 return resultadoDesglosemos cada parte:
| Elemento | Qué es | Ejemplo |
|---|---|---|
| def | Palabra clave que indica “voy a definir una función” | def |
| Nombre | Identificador de la función (en minúsculas, con guiones bajos) | calcular_precio |
| Paréntesis | Contienen los parámetros de entrada | (precio, descuento) |
| Dos puntos | Indican que empieza el cuerpo de la función | : |
| Cuerpo | Código indentado que se ejecuta al llamar la función | return precio * 0.9 |
| return | Devuelve un valor (opcional) | return resultado |
Ejemplo paso a paso
1# 1. DEFINIR la función (escribir la receta)
2def saludar(nombre):
3 mensaje = f"¡Hola, {nombre}!"
4 return mensaje
5
6# 2. LLAMAR a la función (usar la receta)
7resultado = saludar("Ana")
8print(resultado) # ¡Hola, Ana!
9
10# Puedes llamarla las veces que quieras
11print(saludar("Luis")) # ¡Hola, Luis!
12print(saludar("María")) # ¡Hola, María!Definir una función (con def) es como escribir una receta. No cocina nada, solo guarda las instrucciones.
Llamar a una función (escribiendo su nombre con paréntesis) es cocinar siguiendo la receta. Ahí es cuando realmente se ejecuta el código.
Parámetros y argumentos
Imagina un formulario de registro. El formulario tiene campos vacíos (nombre, email, teléfono). Cuando alguien lo rellena, esos campos tienen valores concretos.
- Los parámetros son los campos vacíos del formulario (la definición)
- Los argumentos son los valores concretos que rellenas (la llamada)
1# parámetros ↓
2def registrar(nombre, email):
3 print(f"Usuario: {nombre}, Email: {email}")
4
5# argumentos ↓
6registrar("Ana García", "[email protected]")Parámetros posicionales
El orden importa. El primer argumento va al primer parámetro, el segundo al segundo…
1def presentar(nombre, edad, ciudad):
2 print(f"Soy {nombre}, tengo {edad} años y vivo en {ciudad}")
3
4presentar("Ana", 25, "Madrid") # Correcto
5presentar(25, "Ana", "Madrid") # ¡Error! 25 no es un nombreParámetros con nombre (keyword arguments)
Puedes especificar el nombre del parámetro al llamar. Así el orden no importa:
1presentar(ciudad="Barcelona", nombre="Luis", edad=30)
2# Soy Luis, tengo 30 años y vivo en BarcelonaParámetros con valores por defecto
A veces quieres que un parámetro tenga un valor “de fábrica” si no se especifica:
1def saludar(nombre, saludo="Hola"):
2 return f"{saludo}, {nombre}!"
3
4print(saludar("Ana")) # Hola, Ana!
5print(saludar("Ana", "Buenos días")) # Buenos días, Ana!Los parámetros con valor por defecto deben ir después de los que no tienen. Si no, Python se confunde:
1# Mal
2def funcion(a=1, b): # SyntaxError!
3
4# Bien
5def funcion(b, a=1): # CorrectoNúmero variable de argumentos
A veces no sabes cuántos argumentos recibirás. Python tiene dos herramientas para esto:
1# *args: recibe múltiples argumentos posicionales como tupla
2def sumar_todos(*numeros):
3 return sum(numeros)
4
5print(sumar_todos(1, 2)) # 3
6print(sumar_todos(1, 2, 3, 4, 5)) # 15
7
8# **kwargs: recibe argumentos con nombre como diccionario
9def crear_perfil(**datos):
10 for clave, valor in datos.items():
11 print(f"{clave}: {valor}")
12
13crear_perfil(nombre="Ana", edad=25, ciudad="Madrid")
14# nombre: Ana
15# edad: 25
16# ciudad: MadridDevolver valores con return
La palabra return hace dos cosas:
- Devuelve un valor al código que llamó la función
- Termina la ejecución de la función inmediatamente
La diferencia entre print() y return
Esta es una confusión muy común entre principiantes. Piensa en un trabajador:
print()es como un trabajador que hace su trabajo y te cuenta lo que hizo (muestra en pantalla)returnes como un trabajador que hace su trabajo y te entrega el resultado (puedes usarlo después)
1# Solo muestra en pantalla, no devuelve nada útil
2def sumar_print(a, b):
3 print(a + b)
4
5# Devuelve el valor, puedes usarlo después
6def sumar_return(a, b):
7 return a + b
8
9# Con print: no puedes hacer nada con el resultado
10resultado1 = sumar_print(2, 3) # Muestra: 5
11print(resultado1) # None (no devolvió nada)
12
13# Con return: el resultado es útil
14resultado2 = sumar_return(2, 3)
15print(resultado2) # 5
16print(resultado2 * 2) # 10 (puedes operarlo)Retornar múltiples valores
Python permite devolver varios valores a la vez (en realidad, devuelve una tupla):
1def analizar_numeros(lista):
2 minimo = min(lista)
3 maximo = max(lista)
4 promedio = sum(lista) / len(lista)
5 return minimo, maximo, promedio
6
7# Desempaquetar los valores
8menor, mayor, media = analizar_numeros([1, 5, 3, 9, 2])
9print(f"Mínimo: {menor}, Máximo: {mayor}, Promedio: {media}")
10# Mínimo: 1, Máximo: 9, Promedio: 4.0Funciones sin return
Si una función no tiene return, devuelve None automáticamente:
1def saludar(nombre):
2 print(f"Hola, {nombre}")
3 # No hay return
4
5resultado = saludar("Ana") # Muestra: Hola, Ana
6print(resultado) # Nonereturn termina la función
Cuando Python encuentra un return, la función termina inmediatamente:
1def verificar_edad(edad):
2 if edad < 0:
3 return "Edad inválida" # Si es negativa, termina aquí
4 if edad < 18:
5 return "Menor de edad" # Si es menor, termina aquí
6 return "Mayor de edad" # Si llegamos aquí, es adulto
7
8print(verificar_edad(-5)) # Edad inválida
9print(verificar_edad(15)) # Menor de edad
10print(verificar_edad(25)) # Mayor de edadScope: ¿Dónde viven las variables?
Imagina una casa con habitaciones. Lo que pasa en la cocina, se queda en la cocina. Si dejas una sartén en la cocina, no aparece mágicamente en el dormitorio.
En programación, las variables también tienen su “habitación”: es lo que llamamos scope (ámbito).
graph TB
subgraph Global["Ámbito Global (toda la casa)"]
A["variable_global = 'visible en toda la casa'"]
subgraph Funcion["Ámbito Local (una habitación)"]
B["variable_local = 'solo visible aquí dentro'"]
end
endVariables locales
Las variables creadas dentro de una función son locales. Solo existen mientras la función se ejecuta:
1def mi_funcion():
2 mensaje = "Soy local" # Variable local
3 print(mensaje)
4
5mi_funcion() # Soy local
6print(mensaje) # NameError: 'mensaje' is not definedVariables globales
Las variables creadas fuera de las funciones son globales. Son visibles desde cualquier parte:
1saludo = "Hola" # Variable global
2
3def saludar():
4 print(saludo) # Puede LEER la variable global
5
6saludar() # HolaModificar variables globales (y por qué evitarlo)
Si intentas modificar una variable global dentro de una función, Python crea una nueva variable local:
1contador = 0
2
3def incrementar():
4 contador = contador + 1 # ¡Error! Python piensa que es local
5 print(contador)
6
7incrementar() # UnboundLocalErrorPuedes usar global para forzar el acceso, pero no es recomendable:
1contador = 0
2
3def incrementar():
4 global contador # "Usa la variable global, no crees una local"
5 contador = contador + 1
6
7incrementar()
8print(contador) # 1Las variables globales hacen el código difícil de entender y depurar. Si una función necesita un valor, pásalo como parámetro. Si necesita devolver algo, usa return.
1# Mal: usa variable global
2total = 0
3def sumar(x):
4 global total
5 total += x
6
7# Bien: usa parámetros y return
8def sumar(total, x):
9 return total + xDocumentar funciones (docstrings)
Un docstring es un texto que explica qué hace una función. Va justo después de la línea def, entre triple comillas:
1def calcular_imc(peso, altura):
2 """
3 Calcula el Índice de Masa Corporal (IMC).
4
5 Args:
6 peso: Peso en kilogramos
7 altura: Altura en metros
8
9 Returns:
10 El IMC como número decimal
11 """
12 return peso / (altura ** 2)¿Por qué documentar?
- Para otros: Quien lea tu código (incluido tu yo del futuro) entenderá qué hace cada función
- Para herramientas: IDEs y editores muestran el docstring cuando pasas el cursor sobre una función
- Para generar documentación: Herramientas como Sphinx generan documentación automática
1# Ver el docstring de una función
2print(calcular_imc.__doc__)
3
4# O usando help()
5help(calcular_imc)Buenas prácticas
Nombra funciones con verbos
El nombre debe describir qué hace la función:
1# Mal: sustantivos o nombres confusos
2def datos_usuario():
3 pass
4
5def proceso():
6 pass
7
8# Bien: verbos que indican acción
9def obtener_datos_usuario():
10 pass
11
12def procesar_pedido():
13 pass
14
15def calcular_total():
16 pass
17
18def validar_email():
19 passUna función = una tarea
Cada función debe hacer una sola cosa bien. Si hace muchas cosas, divídela:
1# Mal: hace demasiadas cosas
2def procesar_usuario(datos):
3 # Valida datos
4 # Guarda en base de datos
5 # Envía email de bienvenida
6 # Genera estadísticas
7 pass
8
9# Bien: funciones pequeñas y enfocadas
10def validar_datos(datos):
11 pass
12
13def guardar_usuario(datos):
14 pass
15
16def enviar_email_bienvenida(email):
17 passMantén las funciones cortas
Si una función tiene más de 20-30 líneas, probablemente hace demasiado. Considera dividirla.
Cuándo crear una función
Crea una función cuando:
- Repites código más de dos veces
- Un bloque de código hace una tarea específica que puedes nombrar
- Quieres simplificar código complejo dividiéndolo en partes
- Necesitas testear una parte del código de forma aislada
Resumen
| Concepto | Descripción | Ejemplo |
|---|---|---|
| def | Define una función | def mi_funcion(): |
| Parámetros | Variables de entrada (en la definición) | def suma(a, b): |
| Argumentos | Valores concretos (en la llamada) | suma(2, 3) |
| return | Devuelve un valor y termina la función | return resultado |
| Valor por defecto | Parámetro con valor “de fábrica” | def f(x=10): |
| *args | Múltiples argumentos posicionales | def f(*args): |
| **kwargs | Múltiples argumentos con nombre | def f(**kwargs): |
| Scope local | Variables dentro de la función | Solo visibles en la función |
| Scope global | Variables fuera de funciones | Visibles en todo el programa |
| Docstring | Documentación de la función | “““Texto…””” |
Ejercicios prácticos
Crea una función calcular_propina(total, porcentaje=15) que calcule la propina de una cuenta. El porcentaje por defecto es 15%.
Crea una función validar_password(password) que verifique si una contraseña cumple:
- Al menos 8 caracteres
- Al menos una mayúscula
- Al menos un número
Devuelve True si cumple todo, False si no.
Crea una función estadisticas(numeros) que reciba una lista de números y devuelva un diccionario con: mínimo, máximo, suma, promedio y cantidad de elementos.