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__)
.
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
.