Qué son las Funciones en Python y Cómo Crearlas paso a paso

D
DanisCh
(Actualizado: ) 12 min de lectura
Qué son las Funciones en Python y Cómo Crearlas paso a paso
Python

Hay un momento en el aprendizaje de Python en el que todo cambia. Un momento en el que dejas de escribir código como una lista interminable de instrucciones y empiezas a estructurarlo de forma limpia, reutilizable y profesional.

Ese momento ocurre cuando aprendes a usar funciones.

Las funciones son uno de los conceptos más importantes de cualquier lenguaje de programación. Son la base de todo código bien escrito. Y en Python, crearlas es tan sencillo que en los próximos minutos ya estarás escribiendo las tuyas propias.

Vamos paso a paso.


¿Qué es una función en Python?

Una función es un bloque de código con nombre que realiza una tarea específica y puede ejecutarse (llamarse) desde cualquier parte de tu programa, las veces que necesites.

La analogía perfecta: imagina que eres el chef de un restaurante y tienes que preparar pasta todos los días. Podrías escribir los pasos cada vez que la preparas, o podrías crear una receta con un nombre ("preparar_pasta") y simplemente ejecutarla cuando la necesites.

Eso es exactamente una función: una receta reutilizable para una tarea específica.

Python ya incluye muchas funciones listas para usar. Las has estado usando desde el primer día:

print("Hola, mundo")   # función print()
len("Python")          # función len()
int("25")              # función int()
type(42)               # función type()

Todas esas son funciones integradas de Python. Pero lo mejor es que puedes crear las tuyas propias para resolver exactamente los problemas que necesitas resolver.


¿Por qué usar funciones?

Antes de ver cómo crearlas, entendamos por qué importan tanto. Hay tres razones principales:

1. 🔁 Reutilización — escribe una vez, usa muchas veces

# ❌ Sin funciones: repetir el mismo código 3 veces
print("Bienvenido, Ana. Tienes 3 mensajes nuevos.")
print("Bienvenido, Luis. Tienes 1 mensaje nuevo.")
print("Bienvenido, María. Tienes 7 mensajes nuevos.")

# ✅ Con funciones: definir una vez, llamar las veces que quieras
def bienvenida(nombre, mensajes):
    print(f"Bienvenido, {nombre}. Tienes {mensajes} mensaje(s) nuevo(s).")

bienvenida("Ana", 3)
bienvenida("Luis", 1)
bienvenida("María", 7)

2. 📦 Organización — código más limpio y legible

Un programa bien estructurado con funciones se lee casi como un libro. Cada función tiene un nombre descriptivo que dice exactamente qué hace. No tienes que leer 50 líneas de código para entender qué está pasando: lees los nombres de las funciones.

3. 🐛 Mantenimiento — un cambio en un solo lugar

Si necesitas modificar cómo funciona algo, solo cambias la función. Sin funciones, tendrías que buscar y cambiar ese código en cada lugar donde lo repetiste. Con funciones, lo cambias una vez y el cambio se aplica en todas partes.


Paso 1: Tu primera función — la sintaxis básica

Crear una función en Python es muy sencillo. Usa la palabra clave def, seguida del nombre de la función, paréntesis y dos puntos. El código de la función va indentado:

def saludar():
    print("¡Hola! Bienvenido a Python.")
    print("Las funciones son geniales.")

Eso define la función. Pero definirla no la ejecuta. Para ejecutarla, la llamas por su nombre seguido de paréntesis:

saludar()  # llamada a la función
¡Hola! Bienvenido a Python.
Las funciones son geniales.

Puedes llamarla tantas veces como quieras:

saludar()
saludar()
saludar()
# Imprime el mensaje 3 veces con una sola línea cada vez

💡 Regla importante: Siempre define la función antes de llamarla. Python lee el código de arriba hacia abajo, así que si llamas a una función antes de definirla, obtendrás un error.


Paso 2: Parámetros — dale información a tu función

Las funciones sin parámetros siempre hacen exactamente lo mismo. Eso está bien para algunas tareas, pero la mayoría de las veces querrás que la función trabaje con datos diferentes cada vez que la llamas.

Para eso existen los parámetros: variables que defines en la función y que reciben valores cuando la llamas.

# Función con un parámetro
def saludar(nombre):
    print(f"¡Hola, {nombre}! Bienvenido a Python.")

saludar("Ana")    # Hola, Ana! Bienvenido a Python.
saludar("Luis")   # Hola, Luis! Bienvenido a Python.
saludar("María")  # Hola, María! Bienvenido a Python.

Con múltiples parámetros:

# Función con varios parámetros
def presentar(nombre, edad, ciudad):
    print(f"Me llamo {nombre}, tengo {edad} años y soy de {ciudad}.")

presentar("Ana", 25, "Ciudad de México")
presentar("Luis", 30, "Bogotá")
Me llamo Ana, tengo 25 años y soy de Ciudad de México.
Me llamo Luis, tengo 30 años y soy de Bogotá.

Parámetros vs Argumentos: la diferencia

Son términos que se confunden mucho. La diferencia es simple:

  • Parámetro — la variable en la definición de la función (nombre, edad)
  • Argumento — el valor que pasas al llamarla ("Ana", 25)
def saludar(nombre):    # 'nombre' es el PARÁMETRO
    print(f"Hola, {nombre}")

saludar("Ana")          # "Ana" es el ARGUMENTO

Paso 3: return — devolver resultados

Hasta ahora nuestras funciones solo imprimen cosas. Pero muchas veces necesitas que la función calcule algo y te devuelva el resultado para seguir usándolo en tu programa.

Para eso existe return:

# Sin return — solo imprime, no devuelve nada útil
def sumar_sin_return(a, b):
    print(a + b)

resultado = sumar_sin_return(5, 3)
print(resultado)  # None ← no puedes usar este valor
# Con return — devuelve el valor para usarlo después
def sumar(a, b):
    return a + b

resultado = sumar(5, 3)
print(resultado)          # 8
print(sumar(10, 20) * 2)  # 60 ← puedes operar con el resultado
print(f"La suma es: {sumar(7, 9)}")  # La suma es: 16

La diferencia es crucial: print() muestra algo en pantalla pero no devuelve nada usable. return devuelve un valor que puedes guardar en una variable, pasar a otra función o usar en cualquier expresión.

Retornar múltiples valores

Python te permite retornar varios valores a la vez, algo que muchos otros lenguajes no permiten tan fácilmente:

def calcular_estadisticas(numeros):
    minimo  = min(numeros)
    maximo  = max(numeros)
    promedio = sum(numeros) / len(numeros)
    return minimo, maximo, promedio  # devuelve 3 valores

datos = [4, 8, 15, 16, 23, 42]
min_val, max_val, prom = calcular_estadisticas(datos)

print(f"Mínimo:   {min_val}")   # 4
print(f"Máximo:   {max_val}")   # 42
print(f"Promedio: {prom:.1f}")  # 18.0

Paso 4: Parámetros con valores por defecto

A veces quieres que un parámetro sea opcional: si el usuario no lo especifica, usa un valor predeterminado. Para eso se usan los valores por defecto:

def saludar(nombre, saludo="Hola"):
    print(f"{saludo}, {nombre}!")

saludar("Ana")                    # Hola, Ana!        ← usa el valor por defecto
saludar("Luis", "Buenos días")    # Buenos días, Luis! ← usa el valor pasado
saludar("María", saludo="Qué tal") # Qué tal, María!

Un ejemplo más práctico:

def calcular_precio(precio_base, descuento=0, impuesto=0.19):
    precio_con_descuento = precio_base * (1 - descuento)
    precio_final = precio_con_descuento * (1 + impuesto)
    return round(precio_final, 2)

print(calcular_precio(100))              # 119.0   (sin descuento, con IVA normal)
print(calcular_precio(100, descuento=0.10))  # 107.1   (10% descuento)
print(calcular_precio(100, 0.20, 0.16))      # 92.8    (20% descuento, 16% impuesto)

⚠️ Regla importante: Los parámetros con valores por defecto siempre van después de los parámetros obligatorios. Si los pones antes, Python te dará un error de sintaxis.

# ❌ Error: parámetro con default antes de obligatorio
def saludar(saludo="Hola", nombre):
    ...

# ✅ Correcto: obligatorios primero, con default después
def saludar(nombre, saludo="Hola"):
    ...

Paso 5: *args y **kwargs — parámetros flexibles

¿Qué pasa cuando no sabes de antemano cuántos argumentos va a recibir tu función? Python tiene dos herramientas para eso.

*args — cantidad variable de argumentos posicionales

def sumar_todo(*numeros):
    total = 0
    for n in numeros:
        total += n
    return total

print(sumar_todo(1, 2, 3))          # 6
print(sumar_todo(10, 20, 30, 40))   # 100
print(sumar_todo(5))                # 5
print(sumar_todo())                 # 0

El * antes del nombre indica que Python empaquetará todos los argumentos en una tupla. Puedes nombrarla como quieras, pero la convención es args.

**kwargs — cantidad variable de argumentos con nombre

def crear_perfil(**datos):
    print("Perfil de usuario:")
    for clave, valor in datos.items():
        print(f"  {clave}: {valor}")

crear_perfil(nombre="Ana", edad=25, ciudad="Lima", lenguaje="Python")
# Perfil de usuario:
#   nombre: Ana
#   edad: 25
#   ciudad: Lima
#   lenguaje: Python

El ** empaqueta los argumentos con nombre en un diccionario. La convención es kwargs (keyword arguments).

Combinándolos todos

def funcion_completa(obligatorio, por_defecto="default", *args, **kwargs):
    print(f"Obligatorio: {obligatorio}")
    print(f"Por defecto: {por_defecto}")
    print(f"Args extra:  {args}")
    print(f"Kwargs:      {kwargs}")

funcion_completa("requerido", "personalizado", 1, 2, 3, a=10, b=20)
# Obligatorio: requerido
# Por defecto: personalizado
# Args extra:  (1, 2, 3)
# Kwargs:      {'a': 10, 'b': 20}

Paso 6: Scope — dónde viven las variables

El scope (ámbito) define en qué partes del código es accesible una variable. En Python, las variables creadas dentro de una función son locales: solo existen dentro de esa función.

def mi_funcion():
    variable_local = "Solo existo dentro de la función"
    print(variable_local)  # ✅ Funciona

mi_funcion()
print(variable_local)  # ❌ NameError: no existe fuera de la función
variable_global = "Existo en todo el programa"

def mi_funcion():
    print(variable_global)  # ✅ Puede leer variables globales

mi_funcion()
print(variable_global)  # ✅ También accesible aquí

💡 Buena práctica: Evita modificar variables globales desde dentro de las funciones. Es mejor pasar los valores como parámetros y retornar los resultados. Tu código será más predecible y fácil de depurar.


Paso 7: Funciones Lambda — funciones en una línea

Las funciones lambda son funciones anónimas y compactas que se definen en una sola línea. Son perfectas para operaciones simples que no necesitan un nombre permanente.

# Función normal
def cuadrado(x):
    return x ** 2

# Equivalente con lambda
cuadrado_lambda = lambda x: x ** 2

print(cuadrado(5))        # 25
print(cuadrado_lambda(5)) # 25

Las lambdas brillan cuando las usas junto con funciones como map(), filter() y sorted():

numeros = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

# Ordenar de mayor a menor
ordenados = sorted(numeros, key=lambda x: -x)
print(ordenados)  # [9, 6, 5, 5, 4, 3, 3, 2, 1, 1]

# Solo los números pares
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares)  # [4, 2, 6]

# Multiplicar cada número por 10
multiplicados = list(map(lambda x: x * 10, numeros))
print(multiplicados)  # [30, 10, 40, 10, 50, 90, 20, 60, 50, 30]

Paso 8: Docstrings — documenta tus funciones

Un código profesional siempre documenta sus funciones. En Python, esto se hace con los docstrings: cadenas de texto que van justo después de la definición de la función y explican qué hace, qué recibe y qué devuelve.

def calcular_imc(peso, altura):
    """
    Calcula el Índice de Masa Corporal (IMC).

    Args:
        peso (float): Peso en kilogramos.
        altura (float): Altura en metros.

    Returns:
        float: El IMC calculado, redondeado a 2 decimales.

    Examples:
        >>> calcular_imc(70, 1.75)
        22.86
    """
    imc = peso / (altura ** 2)
    return round(imc, 2)

# Puedes ver el docstring así:
help(calcular_imc)
print(calcular_imc.__doc__)

# Uso:
print(calcular_imc(70, 1.75))  # 22.86
print(calcular_imc(90, 1.80))  # 27.78

Puede parecer un detalle menor cuando estás empezando, pero cuando revises código que escribiste hace 6 meses (o cuando otro desarrollador revise el tuyo), los docstrings valen su peso en oro.


Ejemplo final: juntando todo en un proyecto real

Vamos a construir una pequeña calculadora de notas escolares que usa todo lo que aprendiste en este artículo:

# ============================================
# CALCULADORA DE NOTAS ESCOLARES
# ============================================

def calcular_promedio(*notas):
    """Calcula el promedio de una lista de notas."""
    if not notas:
        return 0
    return round(sum(notas) / len(notas), 2)


def clasificar_nota(promedio, aprobacion=6.0):
    """
    Clasifica el rendimiento según el promedio.

    Args:
        promedio (float): Promedio del estudiante.
        aprobacion (float): Nota mínima para aprobar (default: 6.0).

    Returns:
        str: Clasificación del rendimiento.
    """
    if promedio >= 9.0:
        return "Excelente ⭐"
    elif promedio >= 7.5:
        return "Muy bien 👍"
    elif promedio >= aprobacion:
        return "Aprobado ✅"
    else:
        return "Reprobado ❌"


def reporte_estudiante(nombre, *notas, aprobacion=6.0):
    """Genera un reporte completo de un estudiante."""
    promedio = calcular_promedio(*notas)
    clasificacion = clasificar_nota(promedio, aprobacion)

    print(f"\n{'='*40}")
    print(f"  Reporte de: {nombre}")
    print(f"{'='*40}")
    print(f"  Notas:       {list(notas)}")
    print(f"  Promedio:    {promedio}")
    print(f"  Resultado:   {clasificacion}")
    print(f"{'='*40}")

    return promedio


# Generar reportes
reporte_estudiante("Ana García", 8.5, 9.0, 7.5, 9.5, 8.0)
reporte_estudiante("Luis Pérez", 5.0, 6.5, 4.5, 7.0, 5.5)
reporte_estudiante("María López", 10, 9.5, 10, 9.0, 9.8)
========================================
  Reporte de: Ana García
========================================
  Notas:       [8.5, 9.0, 7.5, 9.5, 8.0]
  Promedio:    8.5
  Resultado:   Muy bien 👍
========================================

========================================
  Reporte de: Luis Pérez
========================================
  Notas:       [5.0, 6.5, 4.5, 7.0, 5.5]
  Promedio:    5.7
  Resultado:   Reprobado ❌
========================================

========================================
  Reporte de: María López
========================================
  Notas:       [10, 9.5, 10, 9.0, 9.8]
  Promedio:    9.66
  Resultado:   Excelente ⭐
========================================

Errores comunes al usar funciones en Python

Llamar la función sin paréntesis

def saludar():
    print("Hola")

saludar   # ❌ No hace nada, solo referencia la función
saludar() # ✅ Ejecuta la función

Confundir print() con return

def sumar(a, b):
    print(a + b)  # ❌ Muestra el resultado pero no lo devuelve

resultado = sumar(5, 3)  # resultado = None (no el número 8)
print(resultado * 2)     # Error: no puedes multiplicar None

Poner parámetros con default antes de los obligatorios

def saludar(saludo="Hola", nombre):  # ❌ SyntaxError
    ...

def saludar(nombre, saludo="Hola"):  # ✅ Correcto
    ...

Intentar acceder a variables locales desde fuera

def mi_funcion():
    resultado = 42

mi_funcion()
print(resultado)  # ❌ NameError: resultado no existe fuera

Buenas prácticas para escribir funciones en Python

  • Una función, una responsabilidad — cada función debe hacer una sola cosa y hacerla bien
  • Nombres descriptivoscalcular_promedio() es mejor que calc() o f()
  • Funciones cortas — si tu función tiene más de 20-30 líneas, probablemente debería dividirse
  • Usa return en lugar de print() cuando quieras usar el resultado
  • Documenta con docstrings — especialmente si otros van a usar tu código
  • Evita variables globales — pasa los valores como parámetros
  • Los parámetros con default al final — obligatorios primero

Resumen: lo que aprendiste hoy

  • ✅ Una función es un bloque de código reutilizable definido con def
  • ✅ Los parámetros reciben datos; los argumentos son los valores que pasas
  • return devuelve un valor usable; print() solo lo muestra
  • ✅ Los valores por defecto hacen que un parámetro sea opcional
  • *args acepta número variable de argumentos posicionales
  • **kwargs acepta número variable de argumentos con nombre
  • ✅ Las variables locales solo existen dentro de su función
  • ✅ Las funciones lambda son funciones anónimas de una sola línea
  • ✅ Los docstrings documentan qué hace la función, qué recibe y qué devuelve

🧪 ¿Tienes los fundamentos de Python bien sólidos?

Las funciones son uno de los temas que más aparece en cualquier evaluación de Python. Si quieres saber qué tan sólidos están tus fundamentos — variables, tipos de datos, bucles y ahora funciones — este es el momento perfecto para comprobarlo.

👉 Test: Python Básico 👉 Test: Python Intermedio 

¿Ya usabas funciones o era la primera vez que las veías? ¿Cuál fue el concepto que más te costó entender: el return, el scope o los *args? Cuéntanos en los comentarios 👇 — respondemos todos. 🐍

¿Te ha gustado esta entrada?

Compártela con tus compañeros para que también sigan aprendiendo.

Comunidad y Comentarios

0 COMENTARIOS

No hay comentarios todavía. Sé el primero en compartir tu opinión.

Escribe tu opinión
Respondiendo a