Uso de Campos (Field)
Profundiza en la función Field para personalizar atributos. Aprenderás a definir valores por defecto, alias de entrada y salida, así como restricciones básicas de longitud y tamaño para tus variables.
Este capítulo profundiza en la función Field(), la herramienta central de Pydantic para personalizar y refinar el comportamiento de los atributos de un modelo a nivel individual. A lo largo de las siguientes secciones, aprenderás a ir más allá del simple tipado estático de Python mediante la asignación segura de valores predeterminados estáticos y dinámicos (evitando el clásico problema de los mutables en memoria). También descubriremos cómo conectar tus modelos con sistemas externos mediante el uso estratégico de alias de entrada y salida, y cómo implementar restricciones matemáticas inmediatas para blindar la integridad de tus datos numéricos de forma puramente declarativa.
4.1. Introducción a Field()
En los capítulos anteriores hemos visto cómo la herencia de BaseModel nos permite declarar esquemas de datos robustos utilizando únicamente el tipado estándar de Python. Sin embargo, cuando las necesidades de nuestro software van más allá de comprobar si un dato es un entero o una cadena, necesitamos una herramienta que nos permita intervenir directamente sobre la definición y el comportamiento de cada variable individual. Aquí es donde entra en juego la función Field().
La función Field() de Pydantic actúa como el centro de control para la personalización de atributos dentro de un modelo. Su propósito principal es asociar metadatos adicionales y aplicar comportamientos específicos a un campo, tales como modificar la documentación del esquema, alterar los nombres de entrada/salida o inyectar restricciones inmediatas sin necesidad de escribir validadores personalizados.
¿Por qué utilizar Field()?
Cuando definimos un atributo de manera estándar, el margen de configuración es limitado:
Python
Con este enfoque, Pydantic solo sabe que id debe convertirse a un entero y nombre a una cadena de texto. Si quisiéramos añadir una descripción técnica para documentar nuestra API, o si necesitáramos que el id sea siempre un número positivo, la sintaxis nativa de Python no nos ofrece una solución limpia.
Field() expande la declaración del atributo al interceptar el proceso de análisis (parsing) y de generación de esquemas. El siguiente diagrama en texto plano ilustra cómo se posiciona Field() entre la definición de un atributo y el motor interno de validación de Pydantic:
TEXT
Sintaxis Básica e Importación
Para utilizar Field(), debemos importarlo directamente desde el módulo principal de pydantic. La función se asigna como el valor predeterminado del atributo del modelo empleando el operador =.
Veamos un ejemplo práctico en el que introducimos metadatos informativos a un modelo de inventario. Estos metadatos no alteran la validación del tipo de dato en sí, pero enriquecen sustancialmente el esquema JSON generado por el modelo (concepto que se explorará a fondo en el Capítulo 16):
Python
El rol de Field() frente a las anotaciones de tipo
Es muy importante entender que Field() no reemplaza a las anotaciones de tipo de Python; trabaja en conjunto con ellas. Pydantic utiliza un enfoque híbrido: la anotación de tipo (a la izquierda del signo =) define la estructura de datos primaria, mientras que Field() (a la derecha) refina las condiciones de contorno.
Si omites la anotación de tipo al usar Field(), Python arrojará un error de sintaxis o Pydantic no podrá inicializar correctamente el validador, dado que el motor requiere obligatoriamente saber el tipo base para poder procesar la información.
Python
A lo largo de este capítulo profundizaremos en el amplio abanico de parámetros que acepta esta función. Aprenderemos a gestionar valores por defecto dinámicos, a mapear estructuras de datos externas mediante alias y a delimitar matemáticamente las variables numéricas, permitiendo que tus modelos se conviertan en la primera y más sólida línea de defensa de tu aplicación.
4.2. Valores predeterminados
Una de las tareas más comunes al diseñar modelos de datos es gestionar qué sucede cuando el usuario o un servicio externo no proporciona un dato específico. Pydantic maneja esto permitiendo definir valores predeterminados. Sin embargo, cuando usamos la función Field(), la asignación de estos valores adquiere una flexibilidad muy superior a la de la sintaxis estándar de Python, resolviendo además uno de los problemas más habituales y problemáticos del lenguaje: los valores predeterminados mutables.
Valores predeterminados estáticos con Field()
En Python estándar, podemos asignar un valor predeterminado directamente con el operador =. Si decidimos usar Field(), el primer parámetro posicional de la función (o el parámetro nombrado default) se convierte en el valor por defecto estático.
Las dos formas siguientes de declarar un campo son completamente equivalentes para Pydantic en términos de asignación, aunque Field() abre la puerta a meter metadatos o restricciones adicionales:
Python
El peligro de los mutables en Python y cómo lo soluciona Pydantic
En Python puro, usar un objeto mutable (como una lista o un diccionario) como valor predeterminado en una función o en una clase es una mala práctica muy conocida. Esto se debe a que el objeto mutable se crea una sola vez cuando el módulo se carga, y todas las instancias de la clase terminan compartiendo exactamente la misma lista en memoria. Si una instancia modifica la lista, se modifica para todas las demás.
Pydantic elimina por completo este dolor de cabeza. Cuando asignas una lista o un diccionario por defecto (ya sea de forma directa o a través de Field(default=[])), Pydantic realiza una copia profunda (deep copy) del valor cada vez que se crea una nueva instancia del modelo.
Python
Valores predeterminados dinámicos: default_factory
¿Qué pasa si queremos que el valor predeterminado no sea un dato fijo, sino algo que cambie dinámicamente cada vez que instanciamos el modelo? Por ejemplo, la fecha y hora exacta de registro, o un identificador único (UUID).
Para este escenario, Field() incluye el parámetro default_factory. Este parámetro acepta una función (o cualquier elemento ejecutable, conocido como callable) sin argumentos. Pydantic ejecutará esa función cada vez que se cree una instancia del modelo si el campo no ha sido provisto explícitamente.
Python
El flujo lógico que sigue Pydantic para determinar el valor final de un campo se puede resumir en el siguiente esquema:
TEXT
Regla de oro: No puedes usar
defaultydefault_factoryal mismo tiempo en el mismoField(). Si intentas definir ambos parámetros para un solo atributo, Pydantic lanzará inmediatamente un error de configuración (PydanticUserError) al inicializar la clase.
4.3. Alias y validación de nombres
En el mundo del desarrollo de software, es sumamente común que los sistemas con los que interactúa nuestra aplicación utilicen convenciones de nombres diferentes a las de Python. Mientras que en Python la norma estricta es usar snake_case (palabras separadas por guiones bajos), muchas APIs externas, bases de datos o archivos de configuración emplean camelCase (primera letra minúscula y el resto de palabras iniciadas en mayúscula) o estructuran las propiedades de formas particulares.
La función Field() proporciona una solución limpia y transparente para este desacoplamiento mediante el uso de alias. Los alias nos permiten mapear un nombre de campo externo con un atributo interno de Python sin perder los beneficios del tipado ni romper las guías de estilo del lenguaje.
Los tres tipos de alias en Field()
Field() nos ofrece tres parámetros específicos para gestionar los alias según nuestras necesidades de entrada y salida de datos:
alias: Define un nombre alternativo universal. Se utiliza tanto para leer el dato (deserialización) como para exportarlo (serialización).validation_alias: Se aplica únicamente cuando estamos recibiendo y validando datos. Pydantic buscará este nombre en el diccionario o JSON de entrada.serialization_alias: Se aplica únicamente cuando estamos exportando el modelo (por ejemplo, al convertirlo a un diccionario o JSON).
Veamos un ejemplo práctico donde consumimos datos de una API externa que usa camelCase, pero nosotros queremos exportar los datos internamente hacia otro servicio en un formato diferente:
Python
Nota importante: Al exportar el modelo mediante
model_dump()omodel_dump_json(), debes pasar obligatoriamente el argumentoby_alias=Truesi deseas que los alias de salida se apliquen. De lo contrario, Pydantic usará por defecto los nombres de los atributos nativos de Python (id_empleado,nombre_completo).
Validación de alias y nombres nativos
Por defecto, cuando asignas un alias o un validation_alias a un campo, Pydantic se vuelve estricto: solo aceptará el nombre del alias durante la inicialización del modelo y rechazará el nombre nativo de la variable de Python.
Si intentamos pasar el nombre nativo, el sistema lanzará un error de validación:
Python
Si necesitas que Pydantic sea flexible y acepte tanto el alias externo como el nombre nativo de Python durante la carga de datos, debes configurar el modelo utilizando populate_by_name=True dentro del diccionario de configuración general del modelo (model_config):
Python
Prioridad en la resolución de alias
Cuando combinas varios tipos de alias en un mismo Field(), Pydantic sigue un orden jerárquico estricto para determinar qué nombre evaluar. El comportamiento se divide claramente entre la fase de lectura y la de escritura:
TEXT
Comprender esta jerarquía evita comportamientos inesperados cuando construyes modelos de datos complejos que actúan como puentes de comunicación entre múltiples microservicios con tecnologías heterogéneas.
4.4. Restricciones numéricas
La última gran ventaja que exploraremos sobre Field() en este capítulo es su capacidad para aplicar restricciones matemáticas directamente en la declaración de los atributos. Cuando trabajamos con datos numéricos (como enteros o flotantes), a menudo no basta con asegurar que el dato sea un número; necesitamos garantizar que se encuentre dentro de un rango lógico de negocio.
En lugar de esperar a que los datos se procesen para ejecutar estructuras condicionales o validadores complejos, Field() expone un conjunto de argumentos específicos que actúan como compuertas matemáticas inmediatas durante la fase de análisis de datos.
Parámetros de restricción matemática
Pydantic define cuatro parámetros fundamentales para controlar los límites de las variables numéricas:
gt(Greater Than): Mayor que. El valor debe ser estrictamente superior al límite establecido ().ge(Greater than or Equal to): Mayor o igual que. El valor debe ser igual o superior al límite ().lt(Less Than): Menor que. El valor debe ser estrictamente inferior al límite ().le(Less than or Equal to): Menor o igual que. El valor debe ser igual o inferior al límite ().
Adicionalmente, existe el parámetro multiple_of, que obliga a que el número sea un múltiplo exacto del valor indicado (es decir, que el residuo de la división sea cero).
Implementación práctica de restricciones
Veamos cómo aplicar estas restricciones en un modelo que simula el indicador de control de un reactor industrial, donde la temperatura y la presión deben mantenerse bajo parámetros operacionales estrictos:
Python
Al intentar ejecutar el segundo bloque, Pydantic detiene la inicialización y genera un ValidationError detallado que especifica qué límites matemáticos se han vulnerado:
TEXT
Combinación de restricciones y coerción de tipos
Es crucial recordar que Pydantic ejecuta la coerción de tipos antes de evaluar las restricciones numéricas de Field(). Si pasas una cadena de texto como "25.5" a un campo definido como float con restricciones, Pydantic primero la transformará al número flotante 25.5 y posteriormente comprobará si cumple con los parámetros gt, lt, etc.
TEXT
Si el dato no puede convertirse al tipo numérico base, el proceso fallará inmediatamente en la etapa de coerción, sin llegar a evaluar los límites matemáticos.
Resumen del capítulo
En el Capítulo 4: Uso de Campos (Field), hemos profundizado en la herramienta más potente de Pydantic para personalizar atributos a nivel individual:
- Introducción a
Field(): Aprendimos que funciona como un contenedor de metadatos y restricciones que trabaja de la mano con las anotaciones de tipo de Python para robustecer los esquemas de datos. - Valores predeterminados: Analizamos cómo Pydantic soluciona de forma nativa el problema de los objetos mutables compartidos en memoria mediante copias profundas automáticas, y cómo generar valores dinámicos en tiempo de ejecución utilizando
default_factory. - Alias y validación de nombres: Evaluamos las estrategias para desacoplar los nombres de variables internas en Python (
snake_case) de los formatos de integración externos (camelCase) mediante el uso preciso dealias,validation_aliasyserialization_alias. - Restricciones numéricas: Validamos de forma directa rangos numéricos y multiplicidades mediante parámetros declarativos (
gt,ge,lt,le,multiple_of), evitando la necesidad de escribir lógica de validación manual para reglas matemáticas básicas.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página