pythonpython-dataclasses

Why does dataclass favour __repr__ over __str__?


Given the following code, I think output (A) makes sense since __str__ takes precedence over __repr__ however I am a bit confused about output (B) why does it favour __repr__ over __str__ and is there a way to make the class use the __str__ rather than the __repr__ of Foo without defining __str__ for Bar?

@dataclass()
class Foo():    
    def __repr__(self) -> str:
        return "Foo::__repr__"
    
    def __str__(self) -> str:
        return "Foo::__str__"

@dataclass()
class Bar():   
    foo: Foo

f = Foo()
b = Bar(f)

print(f)  # (A) Outputs: Foo::__str__ 
print(b)  # (B) Outputs: Bar(foo=Foo::__repr__) 

I stumbled upon this because I saw that my custom __str__ of Foo was not being used by Bar in fact even if I remove the __repr__ output (B) will still be Bar(foo=Foo()) instead of Bar(foo=Foo::__str__).


Solution

  • It is normal for the repr to be preferred to str when rendering a representation within a container of some sort, e.g.:

    >>> print(f)
    Foo::__str__
    >>> print([f])
    [Foo::__repr__]
    

    It is necessary for repr to be unambiguous, for example to see the difference between numbers and strings here:

    >>> from dataclasses import dataclass
    >>> @dataclass
    ... class D:
    ...     s: str
    ...     n: int
    ... 
    >>> D('1', 1)
    D(s='1', n=1)
    

    I think you should not override Foo.__repr__ in that way, because you're straying from the "unwritten rule" that eval(repr(obj)) == obj.