functools.partialmethod defines methods with selected arguments already filled while preserving descriptor binding. It resembles functools.partial, but it is designed specifically for declarations inside a class body.
Use it to create clear aliases, specialize commands, configure flags, and expose domain operations without repetitive wrapper methods.
Basic example
from functools import partialmethod
class Door:
def change(self, state, *, log=True):
self.state = state
if log:
print("state:", state)
open = partialmethod(change, "open")
close = partialmethod(change, "closed")
Door().open()
self is still inserted automatically. The fixed arguments are applied after method binding.
Difference from partial
functools.partial is an ordinary callable object and does not provide the same descriptor behavior when placed directly in a class body. partialmethod exists to preserve method binding.
Positional and keyword arguments
class Client:
def request(self, method, path, *, timeout=10):
...
get = partialmethod(request, "GET")
create = partialmethod(request, "POST", timeout=30)
The caller supplies remaining arguments and can override keywords when the underlying function allows it.
Replacing trivial wrappers
A handwritten wrapper is better when it adds validation, metrics, error translation, or documentation. Use partialmethod when the specialization is transparent and contains no extra logic.
Descriptor integration
If the wrapped callable is already a descriptor, such as classmethod, staticmethod, or another partialmethod, binding is delegated to that descriptor.
class Converter:
@classmethod
def create(cls, format_name, value):
return cls(format_name, value)
from_json = partialmethod(create, "json")
Test decorator order and behavior on every supported Python version.
Abstract methods
In ABC-based hierarchies, abstract status can be propagated. For complicated contracts, explicit abstract methods may still be easier to understand.
Signatures and documentation
Introspection tools may display an adapted signature, but documentation systems differ in descriptor support. Test the bound method with inspect.signature.
import inspect
print(inspect.signature(Door().open))
See the internal inspect.signature guide.
Inheritance
Verify how an alias should behave when subclasses override the underlying method. A descriptor may retain the originally supplied function rather than dynamically targeting a replacement with the same name.
Mutable fixed values
Avoid fixing lists or dictionaries that are modified between calls. Shared mutable objects can create hidden state.
Domain APIs
class Query:
def filter(self, operator, field, value):
...
equals = partialmethod(filter, "eq")
greater_than = partialmethod(filter, "gt")
Domain names improve readability while reusing one implementation.
Common mistakes
- Using
partialand expecting method binding. - Fixing arguments in the wrong order.
- Hiding important logic behind many aliases.
- Ignoring signatures and generated documentation.
- Sharing mutable keyword values.
Recommended practice
Use partialmethod for simple specializations, choose explicit names, keep composition shallow, and test class, instance, and subclass access. See the internal guide to functools.partial.
Conclusion
functools.partialmethod creates specialized methods without losing automatic self or cls binding. It removes repetitive wrappers while keeping method semantics intact.







