pythondebuggingloggingrepr

Is it possible to turn off printing the id (hex address) globally for Python objects?


When you don't provide a __repr__ or __str__ method on a custom class, you just get a classname and the Python address of the object (or, to be more specific, what id(self) would return.

This is fine most of the time. And it is very helpful when you are debugging some code and you want to see if instances are/are not the same, visually. But to be honest I almost never care about that id value.

However it also means that running a program with debugging print functions never looks the same. Ditto if you are comparing log files. Unless you write a lot of __repr__ only to avoid this issue. Or if you pre-format the log files to zero out the hex values on the default object prints.

A sample program to illustrate what I would like to do: not have that id printed.
class ILookDifferentEveryRun:
    "baseline behavior"
    
    def __init__(self,a):
        "I don't actually care about `a`, that's why I don't need a `repr`"
        self.a = a

class ILookTheSameEveryRun(ILookDifferentEveryRun):
    """this is my workaround, a cut and paste of a default __repr__"""
    
    def __repr__(self) : return type(self).__name__

class ILookAlmostLikeBuiltinRepr(ILookDifferentEveryRun):
    "can I do this with a global switch?"

    def __repr__(self) :
        """this is more or less what I want"""
        res = f"<{type(self).__module__}.{type(self).__name__} object> at <dontcare>"
        return res


inst1 = ILookDifferentEveryRun(a=1)
inst2 = ILookTheSameEveryRun(a=1)
inst3 = ILookAlmostLikeBuiltinRepr(a=1)

print(inst1)
print(inst2)
print(inst3)

run twice:

<__main__.ILookDifferentEveryRun object at 0x100573260>
ILookTheSameEveryRun
<__main__.ILookAlmostLikeBuiltinRepr object> at <dontcare>
<__main__.ILookDifferentEveryRun object at 0x104ca7320>
ILookTheSameEveryRun
<__main__.ILookAlmostLikeBuiltinRepr object> at <dontcare>

I took a look at the startup flags for the python interpreter, but nothing seems to allow for this. Any workarounds? I know I could also put the repr on a Mixin and reuse that everywhere, but that's ugly too.

If I can't, that's fine and that's what I am expecting to hear. Just wondering if someone else had the same problem and found a way.

p.s. this is less about dedicated printing of instances and more about things like print(mylist) where mylist=[item1,item2,item3], generally any complex data structures with nested items in them.


Solution

  • I don't know for certain but I very much doubt if there's any kind of magic "switch" that would affect the behaviour of __repr__. One idea would be to write a class that implements __repr__ in the style that you want then just subclass that.

    For example:

    class REPR:
        def __repr__(self):
            return f"<{type(self).__module__}.{type(self).__name__}>"
    
    class FOO(REPR):
        def __init__(self, n):
            self._n = n
    
    mylist = [FOO(n) for n in range(5)]
    
    print(mylist)
    

    Output:

    [<__main__.FOO>, <__main__.FOO>, <__main__.FOO>, <__main__.FOO>, <__main__.FOO>]