Possible to change a function's repr in python?
Question
I've only seen examples for setting the __repr__
method in class definitions. Is it possible to change the __repr__
for functions either in their definitions or after defining them?
I've attempted without success...
>>> def f():
pass
>>> f
<function f at 0x1026730c8>
>>> f.__repr__ = lambda: '<New repr>'
>>> f
<function __main__.f>
Solution
Yes, if you're willing to forgo the function actually being a function.
First, define a class for our new type:
import functools
class reprwrapper(object):
def __init__(self, repr, func):
self._repr = repr
self._func = func
functools.update_wrapper(self, func)
def __call__(self, *args, **kw):
return self._func(*args, **kw)
def __repr__(self):
return self._repr(self._func)
Add in a decorator function:
def withrepr(reprfun):
def _wrap(func):
return reprwrapper(reprfun, func)
return _wrap
And now we can define the repr along with the function:
@withrepr(lambda x: "<Func: %s>" % x.__name__)
def mul42(y):
return y*42
Now repr(mul42)
produces '<Func: mul42>'
OTHER TIPS
No, because repr(f)
is done as type(f).__repr__(f)
instead.
In order to do that, you'd need to change the __repr__
function for the given class, which in this case is the built-in function class (types.FunctionType
). Since in Python you cannot edit built-in classes, only subclass them, you cannot.
However, there are two approaches you could follow:
- Wrap some functions as kwatford suggested
Create your own representation protocol with your own repr function. For example, you could define a
myrepr
function that looks for__myrepr__
methods first, which you cannot add to the function class but you can add it to individual function objects as you suggest (as well as your custom classes and objects), then defaults to repr if__myrepr__
is not found. A possible implementation for this would be:def myrepr(x): try: x.__myrepr__ except AttributeError: return repr(x) else: return x.__myrepr__()
Then you could define
__myrepr__
methods and use themyrepr
function. Alternatively, you could also do__builtins__.repr = myrepr
to make your function the defaultrepr
and keep usingrepr
. This approach would end up doing exactly what you want, though editing__builtins__
may not always be desirable.
This appears to be difficult. Kwatford's approach only solves this problem partially since it does not work for functions in classes, becuase self
would be treated like a positional argument, as explained in Decorating Python class methods - how do I pass the instance to the decorator? - However, the solution for that question is not applicable to this case, unfortunately, as using __get__()
and functools.partial
would override the custom __repr__()
.