functools.partialmethod permite definir métodos con algunos argumentos ya fijados sin perder el binding del descriptor. Se parece a functools.partial, pero está diseñado específicamente para declaraciones dentro del cuerpo de una clase.
Es útil para crear atajos claros, especializar comandos, configurar flags y exponer operaciones de dominio sin repetir wrappers triviales.
Ejemplo básico
from functools import partialmethod
class Puerta:
def cambiar(self, estado, *, registrar=True):
self.estado = estado
if registrar:
print("estado:", estado)
abrir = partialmethod(cambiar, "abierta")
cerrar = partialmethod(cambiar, "cerrada")
Puerta().abrir()
self sigue insertándose automáticamente. Los argumentos fijados se aplican después del binding del método.
Diferencia frente a partial
functools.partial es un callable normal y no ofrece el mismo comportamiento de descriptor cuando se coloca directamente en una clase. partialmethod conserva la semántica de método.
Argumentos posicionales y keywords
class Cliente:
def solicitar(self, metodo, ruta, *, timeout=10):
...
obtener = partialmethod(solicitar, "GET")
crear = partialmethod(solicitar, "POST", timeout=30)
El llamador proporciona los argumentos restantes y puede reemplazar keywords si la función base lo permite.
Sustituir wrappers triviales
Un wrapper escrito a mano es mejor cuando añade validación, métricas, traducción de errores o documentación. Usa partialmethod cuando la especialización sea transparente y no tenga lógica adicional.
Integración con descriptors
Si el callable envuelto ya es un descriptor, como classmethod, staticmethod u otro partialmethod, el binding se delega a ese descriptor.
class Conversor:
@classmethod
def crear(cls, formato, valor):
return cls(formato, valor)
desde_json = partialmethod(crear, "json")
Prueba el orden de decorators y el comportamiento en todas las versiones soportadas.
Métodos abstractos
En jerarquías basadas en ABC, el estado abstracto puede propagarse. Para contratos complejos, métodos abstractos explícitos suelen ser más fáciles de entender.
Firmas y documentación
Las herramientas de introspección pueden mostrar una firma adaptada, pero los generadores de documentación difieren en el soporte de descriptors. Prueba el método vinculado con inspect.signature.
import inspect
print(inspect.signature(Puerta().abrir))
Consulta la guía interna de inspect.signature.
Herencia
Verifica cómo debe comportarse el alias cuando una subclase sobrescribe el método base. El descriptor puede mantener la función original suministrada.
Valores mutables fijados
Evita fijar listas o diccionarios que se modifiquen entre llamadas. Los objetos mutables compartidos pueden crear estado oculto.
APIs de dominio
class Consulta:
def filtrar(self, operador, campo, valor):
...
igual = partialmethod(filtrar, "eq")
mayor_que = partialmethod(filtrar, "gt")
Los nombres de dominio mejoran la lectura mientras reutilizan una implementación.
Errores comunes
- Usar
partialesperando binding de método. - Fijar argumentos en orden incorrecto.
- Ocultar lógica importante detrás de muchos aliases.
- Ignorar firmas y documentación generada.
- Compartir keywords mutables.
Buenas prácticas
Usa partialmethod para especializaciones simples, elige nombres explícitos, mantén poca composición y prueba acceso por clase, instancia y subclase. Consulta la guía interna sobre functools.partial.
Conclusión
functools.partialmethod crea métodos especializados sin perder el binding automático de self o cls. Reduce wrappers repetitivos y mantiene la semántica de los métodos.







