Arhitectură Type-Safe în Python: Type Hints, Generics și Validare cu Pydantic v2 în Python

Variabile și tipuri de date Python 3.10+ & Pydantic 2.x

Ghid complet pentru arhitecturi type-safe în Python modern: protocoale structurale, adnotări avansate de tip și validarea ultra-rapidă la runtime cu Pydantic v2 scris în Rust.

Sintaxă
from pydantic import BaseModel, Field
class User(BaseModel):
    id: int
    email: str

În ultimii ani, Python a evoluat dintr-un limbaj cu tipare exclusiv dinamică într-un ecosistem în care Type Hints (adnotările de tip) sunt considerate standardul de aur pentru proiectele de producție. În combinație cu un verificator static (precum mypy sau pyright) și o bibliotecă de validare la runtime ultra-rapidă (precum Pydantic v2), Python oferă aceeași siguranță ca limbajele compilate, păstrând în același timp flexibilitatea sa caracteristică.

1. Duck Typing Verificabil cu typing.Protocol
from typing import Protocol

# Definim un Protocol structural (interfață):
# Orice clasă care implementează metoda 'salveaza()' este compatibilă automat!
class Salubilizabil(Protocol):
    def salveaza(self) -> bool:
        ...

class ArticolBlog:
    def salveaza(self) -> bool:
        print("Articol salvat în baza de date.")
        return True

class FisierLog:
    def salveaza(self) -> bool:
        print("Log salvat pe disc.")
        return True

# Funcția acceptă orice obiect care respectă protocolul (fără moștenire explicită!):
def persista_date(entitate: Salubilizabil) -> None:
    entitate.salveaza()

persista_date(ArticolBlog()) # Valid conform mypy!
persista_date(FisierLog())    # Valid conform mypy!

Pydantic v2: Validare la Runtime Scrisă în Rust

În timp ce type hints ajută doar la scrierea codului în IDE, Pydantic v2 validează și transformă datele concrete primite din exterior (JSON-uri de la clienți, variabile de mediu, răspunsuri de baze de date). În versiunea 2, nucleul său (pydantic-core) a fost rescris în Rust, oferind viteze de validare de 5 până la 20 de ori mai mari decât Pydantic v1.

Model Pydantic v2 complet cu validatoare și transformări
from pydantic import BaseModel, Field, EmailStr, field_validator
from datetime import datetime

class ComandaNoua(BaseModel):
    # Validări declarative pe câmpuri:
    id_comanda: int = Field(gt=0, description="Identificator unic pozitiv")
    email_client: EmailStr
    produse_ids: list[int] = Field(min_length=1, description="Comanda trebuie să conțină minim un produs")
    total_plata: float = Field(ge=0.0)
    data_creare: datetime = Field(default_factory=datetime.utcnow)

    # Validator personalizat pe un câmp specific:
    @field_validator('email_client')
    @classmethod
    def normalizeaza_email(cls, v: str) -> str:
        return v.lower().strip()

# Parsare și validare dintr-un dicționar brut JSON:
date_brute = {
    "id_comanda": 105,
    "email_client": "  Ion.Popescu@Dexblog.RO  ",
    "produse_ids": [10, 42],
    "total_plata": 349.99
}

comanda = ComandaNoua.model_validate(date_brute)

# Email-ul a fost sanitizat automat:
print(comanda.email_client) # "ion.popescu@dexblog.ro"

# Serializare ultra-rapidă înapoi în JSON:
json_output = comanda.model_dump_json()

Bune Practici de Arhitectură

  1. Separarea Modelelor de Domeniu de Modelele de API: Nu folosiți aceleași clase Pydantic pentru request-ul HTTP, entitatea internă de business și modelul ORM (SQLAlchemy/Tortoise). Folosiți DTO-uri dedicate pentru fiecare strat.
  2. Imuabilitate când este posibil: Activați model_config = ConfigDict(frozen=True) pentru a transforma modelele în structuri imuabile rezistente la mutații accidentale în cod.