It bugs me that the default __repr__()
for a class is so uninformative:
>>> class Opaque(object): pass
...
>>> Opaque()
<__main__.Opaque object at 0x7f3ac50eba90>
... so I've been thinking about how to improve it. After a little consideration, I came up with this abstract base class which leverages the pickle
protocol's __getnewargs__()
method:
from abc import abstractmethod
class Repro(object):
"""Abstract base class for objects with informative ``repr()`` behaviour."""
@abstractmethod
def __getnewargs__(self):
raise NotImplementedError
def __repr__(self):
signature = ", ".join(repr(arg) for arg in self.__getnewargs__())
return "%s(%s)" % (self.__class__.__name__, signature)
Here's a trivial example of its usage:
class Transparent(Repro):
"""An example of a ``Repro`` subclass."""
def __init__(self, *args):
self.args = args
def __getnewargs__(self):
return self.args
... and the resulting repr()
behaviour:
>>> Transparent("an absurd signature", [1, 2, 3], str)
Transparent('an absurd signature', [1, 2, 3], <type 'str'>)
>>>
Now, I can see one reason Python doesn't do this by default straight away - requiring every class to define a __getnewargs__()
method would be more burdensome than expecting (but not requiring) that it defines a __repr__()
method.
What I'd like to know is: how dangerous and/or fragile is it? Off-hand, I can't think of anything that could go terribly wrong except that if a Repro
instance contained itself, you'd get infinite recursion ... but that's solveable, at the cost of making the code above uglier.
What else have I missed?