Métodos de Clase vs. Instancia vs. Estáticos
Python ofrece tres tipos de métodos. Los métodos de instancia operan sobre objetos, los métodos de clase sobre la clase (a menudo fábricas), y los métodos estáticos como funciones con espacio de nombres sin self o cls implícitos.
Receta
class User:
def __init__(self, email: str) -> None:
self.email = email
def domain(self) -> str:
return self.email.split("@", 1)[1]
@classmethod
def from_row(cls, row: dict[str, str]) -> "User":
return cls(row["email"])
@staticmethod
def is_valid_email(email: str) -> bool:
return "@" in email and "." in email.split("@", 1)[-1]Cuándo usar esto:
- Constructores alternativos (
from_json,from_env) - Utilidades lógicamente agrupadas con la clase pero que no necesitan estado
- Métodos de fábrica heredados que respetan la
clsde la subclase - Métodos de clase para
Enum/clases personalizadas que modifican el estado de la clase
Ejemplo de Trabajo
from datetime import datetime, timezone
class Event:
def __init__(self, name: str, ts: datetime) -> None:
self.name = name
self.ts = ts
def age_seconds(self, now: datetime | None = None) -> float:
now = now or datetime.now(timezone.utc)
return (now - self.ts).total_seconds()
@classmethod
def now(cls, name: str) -> "Event":
return cls(name, datetime.now(timezone.utc))
@classmethod
def from_iso(cls, name: str, iso: str) -> "Event":
ts = datetime.fromisoformat(iso.replace("Z", "+00:00"))
return cls(name, ts)
@staticmethod
def normalize_name(name: str) -> str:
return name.strip().lower()
class AdminEvent(Event):
pass
if __name__ == "__main__":
base = Event.now("deploy")
admin = AdminEvent.now("promote")
print(type(base), type(admin))
print(Event.is_valid_email("a@b.com"))Lo que esto demuestra:
- El
classmethodnowes un constructor alternativo AdminEvent.nowdevuelveAdminEventporqueclses la subclase- El método de instancia
age_secondsusa el estado del objeto - El
staticmethodnormalize_nameno necesita niselfnicls
Inmersión Profunda
Cómo Funciona
- Métodos enlazados - Los métodos de instancia enlazan
selfen el momento de la llamada. - Descriptor
classmethod- Pasa la clase como primer argumento automáticamente. - Descriptor
staticmethod- Sin argumento de primer elemento automático. - Herencia -
clsenclassmethodes la clase real llamada (AdminEventnoEvent). - Acceso - Los métodos de clase pueden acceder a atributos de clase; los métodos de instancia a atributos de instancia.
Cuándo Usar Cada Uno
| Decorador | Primer arg | Uso Típico |
|---|---|---|
| (ninguno) | self | Comportamiento del objeto |
@classmethod | cls | Fábricas, configuración de clase |
@staticmethod | ninguno | Ayudante agrupado |
Notas de Python
# Patrón de classmethod estilo enum
class Money:
def __init__(self, amount: int, currency: str) -> None:
self.amount = amount
self.currency = currency
@classmethod
def usd(cls, amount: int) -> "Money":
return cls(amount, "USD")Trampas
staticmethodcuando se necesitaclassmethod- Una fábrica que devuelveclsfalla en subclases constaticmethod. Solución: Usaclassmethodpara constructores polimórficos.classmethodaccediendo a estado de instancia - No hayselfdisponible. Solución: Pasa la instancia explícitamente o usa un método de instancia.- Función confusa a nivel de módulo - Un
staticmethodque nunca toca la clase podría ser una función de módulo. Solución: Usastaticmethodsolo cuando agrupes la API en el espacio de nombres de la clase. - Orden de
classmethodabstracto - Apila@classmethody@abstractmethodsegún la documentación de la versión de Python. - Llamar a
classmethoden una instancia - Permitido pero inusual - todavía pasa la clase real.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Función de módulo | No se necesita agrupación de clase | La API pertenece a la clase |
__init__ solamente | Ruta de construcción única | Múltiples fuentes de análisis |
Pydantic model_validate | Análisis de DTO validado | Dominio no Pydantic |
dataclass __post_init__ | Validación post-construcción | Constructores alternativos |
Preguntas Frecuentes
¿`classmethod` vs `__init__`?
Usa fábricas classmethod cuando múltiples rutas de construcción analizan diferentes entradas en el mismo tipo.
¿Por qué `AdminEvent.now` devuelve `AdminEvent`?
cls se enlaza a la clase utilizada en la llamada - comportamiento de fábrica polimórfico.
¿`staticmethod` en una instancia?
Se puede llamar desde una instancia pero la ignora - sin acceso al estado.
¿`classmethod` para decoradores?
Raro - algunos patrones de registro registran subclases a través de __init_subclass__ en su lugar.
¿Tipado de `classmethod`?
Devuelve Self (3.11+) desde classmethod para un tipado de subclase correcto.
¿Propiedad `classmethod`?
Existen patrones de classmethod que envuelven propiedades a partir de Python 3.9+ para metaprogramación - avanzado.
¿Herencia de `staticmethod`?
Se hereda sin cambios - todavía sin enlace cls en la subclase a menos que se anule.
¿Nomenclatura de constructor alternativo?
Convenciones from_json, from_env, parse - no sobrecargas de __init__.
¿`classmethod` mutando el estado de la clase?
Posible a través de patrones cls._registry - documenta la seguridad de hilos si el estado de clase mutable es compartido.
¿Fábricas de dependencias de FastAPI?
A menudo funciones simples - classmethod cuando la fábrica está ligada a la configuración de la clase de servicio.
Relacionado
- Propiedades y Descriptores - descriptores de métodos
- Dataclasses - patrones de construcción
- Herencia y MRO -
clsen contexto MRO - Enums - métodos de clase
Enum
Versiones de Stack: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.