Reputation: 7694
How do I override the string representation for a single function in Python?
What I have tried:
>>> def f(): pass
...
>>> f
<function f at 0x7f7459227758>
>>> f.__str__ = lambda self: 'qwerty'
>>> f
<function f at 0x7f7459227758>
>>> f.__repr__ = lambda self: 'asdfgh'
>>> f
<function f at 0x7f7459227758>
>>> f.__str__(f)
'qwerty'
>>> f.__repr__(f)
'asdfgh'
I know I can get the expected behavior by making a class with __call__
(to make it look like a function) and __str__
(to customize the string representation). Still, I'm curious if I can get something similar with regular functions.
Upvotes: 3
Views: 482
Reputation: 318698
As explained by MartijnPieters, you can't do it without going through a class. But you can easily write a decorator which completely hides the added complexity:
from functools import update_wrapper
class _CustomReprFunc(object):
def __init__(self, fn, repr_):
self.fn = fn
self.repr = repr_
update_wrapper(self, fn)
def __repr__(self):
return self.repr
def __call__(self, *args, **kwargs):
return self.fn(*args, **kwargs)
def custom_repr(repr_):
def decorator(fn):
return _CustomReprFunc(fn, repr_)
return decorator
Usage:
@custom_repr('foobar')
def foo():
"""foo function"""
return 'bar'
Upvotes: 3
Reputation: 1124538
You can't. __str__
and __repr__
are special methods and thus are always looked up on the type, not the instance. You'd have to override type(f).__repr__
here, but that then would apply to all functions.
Your only realistic option then is to use a wrapper object with a __call__
method:
def FunctionWrapper(object):
def __init__(self, callable):
self._callable = callable
def __call__(self, *args, **kwargs):
return self._callable(*args, **kwargs)
def __repr__(self):
return '<custom representation for {}>'.format(self._callable.__name__)
Upvotes: 6