Cuántos argumentos debe tener una función en Python

Una de las señales más claras de que una función está haciendo demasiado es que tiene demasiados argumentos. Cuando hay muchos argumentos se vuelve el código difícil de leer, testear y documentar. ¿Cual es el límite?

Una regla sencilla que funciona bien en la práctica:

  • Ideal: De 0 a 2 argumentos.
  • Aceptable: De 3 o 4 (si están bien justificados o usan valores por defecto).
  • Mal diseño: De 5 al infinito.

Pero hay funciones que necesito añadir más argumentos, por ejemplo a la hora de crear un usuario, necesito nombre, apellido, email, teléfono, dirección... Debe existir una solución para esto sin romper la regla de los 4 argumentos.

Pues yo te propongo algunas herramientas, y ya decides tú cuál encaja mejor en tu caso.

Dataclasses

Si tienes varios argumentos relacionados, agrúpalos en un dataclass. La función recibe un único objeto con todo lo necesario.

from dataclasses import dataclass


@dataclass
class Direccion:
    """Dirección postal completa de un usuario.

    Attributes:
        calle: Nombre de la calle y número.
        ciudad: Ciudad de residencia.
        codigo_postal: Código postal de la zona.
    """

    calle: str
    ciudad: str
    codigo_postal: str


def crear_usuario(
    nombre: str, apellido: str, email: str, telefono: str, direccion: Direccion
) -> None:
    """Crea un nuevo usuario en el sistema.

    Args:
        nombre: Nombre de pila del usuario.
        apellido: Primer apellido.
        email: Dirección de correo electrónico.
        telefono: Número de teléfono de contacto.
        direccion: Dirección postal completa.
    """
    # Tu lógica aquí

Argumentos con nombre obligatorio

El * en la firma fuerza a que todo lo que viene después se pase con nombre. Su ventaja principal es que mejora la legibilidad, ya que el código que llama a la función es más explícito.

def configurar_grafico(
    titulo: str,
    *,
    ancho: int = 800,
    alto: int = 600,
    color_linea: str = "azul",
    grosor: int = 2,
) -> None:
    """Configura y renderiza un gráfico.

    Args:
        titulo: Título del gráfico.
        ancho: Ancho en píxeles, por defecto 800.
        alto: Alto en píxeles, por defecto 600.
        color_linea: Color de la línea principal, por defecto "azul".
        grosor: Grosor de la línea en puntos, por defecto 2.
    """
    pass


configurar_grafico("Mi Gráfico", ancho=1024, color_linea="rojo")

Validación con msgspec

Trabajar con alguna biblioteca de validación de datos, por ejemplo msgspec. Si has trabajado con pydantic, te sentirás muy cómodo. Podríamos considerar msgspec un validador y parseador moderno, ligero (escrito en C) y muy eficiente.

import msgspec


class Usuario(msgspec.Struct, strict=True):
    """Modelo de usuario con validación estricta de tipos.

    Attributes:
        nombre: Nombre completo del usuario.
        edad: Edad en años.
    """

    nombre: str
    edad: int


datos_entrada = {"nombre": "Ana", "edad": 28}

usuario_validado = msgspec.convert(datos_entrada, type=Usuario)

Con strict=True, si el tipo no coincide exactamente, lanza un error. Sin sorpresas.

Apuntes finales

No he incluido *args y **kwargs porque solo esconden los argumentos. Son útiles en contextos concretos (decoradores, wrappers, APIs muy genéricas), pero no son una excusa para no pensar en el diseño.

Espero que ahora antes de añadir un quinto argumento, pregúntate si realmente pertenece ahí o si es una señal de que la función asume demasiadas responsabilidades.

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Will you buy me a coffee?

Comments

There are no comments yet.

Written by Andros Fenollosa

May 27, 2026

3 min of reading

You may also like

Visitors in real time

You are alone: 🐱