functools.partialmethod permite definir métodos com alguns argumentos já preenchidos, preservando o comportamento de binding do descriptor. Ele é semelhante a functools.partial, mas foi criado especificamente para funcionar dentro do corpo de uma classe.
O recurso é útil para criar atalhos sem duplicar métodos, especializar comandos, configurar flags e expor operações de domínio com nomes claros.
Primeiro exemplo
from functools import partialmethod
class Porta:
def alterar(self, estado, *, registrar=True):
self.estado = estado
if registrar:
print("estado:", estado)
abrir = partialmethod(alterar, "aberta")
fechar = partialmethod(alterar, "fechada")
porta = Porta()
porta.abrir()
porta.fechar(registrar=False)
self continua sendo inserido automaticamente. Os argumentos fixados aparecem depois do binding do método.
Diferença para partial
from functools import partial
class Exemplo:
def metodo(self, valor):
return valor
atalho_incorreto = partial(metodo, 10)
partial é um objeto chamável comum e não implementa o mesmo comportamento de descriptor para inserir self. partialmethod existe para resolver essa diferença.
Argumentos posicionais e nomeados
class Cliente:
def requisitar(self, metodo, caminho, *, timeout=10):
...
obter = partialmethod(requisitar, "GET")
criar = partialmethod(requisitar, "POST", timeout=30)
O chamador ainda pode fornecer os argumentos restantes e, quando permitido, sobrescrever keywords.
Sem duplicação de wrappers
Uma alternativa seria escrever vários métodos que apenas chamam outro. partialmethod reduz boilerplate quando não há lógica adicional. Se o wrapper precisa validar, registrar métricas específicas ou adaptar erros, um método explícito costuma ser mais claro.
Integração com descriptors
Se o primeiro argumento já é um descriptor, como classmethod, staticmethod ou outro partialmethod, a resolução é delegada ao descriptor original.
class Conversor:
@classmethod
def criar(cls, formato, valor):
return cls(formato, valor)
de_json = partialmethod(criar, "json")
Teste a ordem dos decorators e o comportamento na versão mínima do Python suportada.
Métodos abstratos
Em hierarquias com abc, o estado abstrato pode ser propagado pelo descriptor. Porém, APIs complexas ficam mais fáceis de entender com métodos abstratos explícitos e implementações concretas simples.
Assinatura e introspecção
Ferramentas podem exibir uma assinatura adaptada, mas nem toda biblioteca de documentação interpreta descriptors da mesma forma. Use inspect.signature nos métodos vinculados e teste a documentação gerada.
import inspect
print(inspect.signature(Porta().abrir))
O guia interno sobre inspect.signature aprofunda a análise de callables.
Herança
O método parcial usa a resolução normal do atributo subjacente. Se uma subclasse sobrescrever o método base, verifique se o atalho deve acompanhar a sobrescrita ou permanecer ligado à função original definida no descriptor.
Keywords mutáveis
Evite fixar objetos mutáveis que serão modificados entre chamadas. Assim como em argumentos padrão, compartilhar uma lista ou dicionário pode criar estado inesperado.
APIs de domínio
class Consulta:
def filtrar(self, operador, campo, valor):
...
igual = partialmethod(filtrar, "eq")
maior_que = partialmethod(filtrar, "gt")
Nomes de domínio tornam chamadas legíveis sem repetir a implementação geral.
Erros comuns
- Usar
partialno corpo da classe esperando binding de método. - Fixar argumentos na ordem errada.
- Esconder lógica importante em muitos atalhos.
- Ignorar assinaturas e documentação.
- Compartilhar keywords mutáveis.
Boas práticas
Use partialmethod para especializações simples, escolha nomes claros, mantenha poucos níveis de composição e escreva testes de binding em classe, instância e subclasses. Veja também o guia interno sobre functools.partial.
Conclusão
functools.partialmethod cria métodos especializados sem perder a inserção automática de self ou cls. Ele reduz wrappers repetitivos, mas deve ser reservado para especializações transparentes.







