为什么数据类偏爱__repr__而不是__str__?

Why does dataclass favour __repr__ over __str__?

提问人:Tobias Wilfert 提问时间:11/7/2023 最后编辑:wjandreaTobias Wilfert 更新时间:11/7/2023 访问量:75

问:

鉴于以下代码,我认为输出是有道理的,因为优先于输出,但是我对输出有点困惑,为什么它偏向于输出,有没有办法让类使用而不是 of 而不定义 for?(A)__str____repr__(B)__repr____str____str____repr__Foo__str__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__) 

我偶然发现了这一点,因为我看到我的习惯实际上没有被使用,即使我删除了输出,输出仍然会是而不是。__str__FooBar__repr__(B)Bar(foo=Foo())Bar(foo=Foo::__str__)

蟒蛇 python-dataclasses

评论

1赞 Charles Duffy 11/7/2023
关注“如何”的问题而不是“为什么”的问题可能是有意义的——“为什么”的问题可以说是题外话因为理解为什么会做出你不同意的设计决策并不能解决软件开发实践中遇到的任何狭隘的、具体的问题。
0赞 wjandrea 11/7/2023
对于问题的第一部分,请参阅:为什么在 Python 中打印元组(列表、字典等)会加倍反斜杠?、__str____repr__ 有什么区别?
0赞 wjandrea 11/7/2023
对于问题的第二部分,“有没有办法让类在不定义 Bar __str__的情况下让类使用 Foo__str__而不是__repr__?”,你为什么要这样做?如果你想有一个更最终用户友好的,你需要自己编写它。您是否知道默认为 因为该类没有 ?Bar__str__str(b)repr(b)__str__

答:

4赞 wim 11/7/2023 #1

在某种容器中呈现表示时,repr 优先于 str 是正常的,例如:

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

repr 必须明确无误,例如要在此处查看数字和字符串之间的区别:

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

我认为你不应该以这种方式覆盖,因为你偏离了 eval(repr(obj)) == obj 的“不成文规则”。Foo.__repr__

评论

2赞 Charles Duffy 11/7/2023
..._is_未成文?我依稀记得它被明确地写成(在 2.x 时代的某个地方),当人们不能遵守该约定时,使用箭头括号来明确表示所发出的内容是不可评估的。
1赞 wim 11/7/2023
据我所知,文档只说“对于许多类型,这个函数会尝试[这样做]......”,并且没有明确提供任何指导,建议用户定义的类型也应该这样做。
0赞 Learning is a mess 11/7/2023
@CharlesDuffy 我不认为有这样的规则,例如 sklearn 不遵守 Charles 提到的第一条规则,但在其不包含拟合状态的 repr 给出中也没有使用方括号。repr(PCA().fit(np.random.randn(10,10)))PCA()
1赞 Barmar 11/7/2023 #2

这是容器的默认约定。它类似于列表、元组和字典的工作方式——它们用于元素值。repr()