Python 序列化数据类列表:str始终调用repr

Python 序列化数据类列表:str始终调用repr,python,python-dataclasses,Python,Python Dataclasses,我想将数据类序列化为字符串。使用dataclasses.asdict和创建自定义\uuuu str\uuu方法很容易。它可以完美地工作,即使对于具有其他数据类或其列表作为成员的类也是如此。但是,在数据类列表上调用str会生成repr版本。我想str生成序列化表单,并repr保持原样 import json from dataclasses import dataclass, asdict @dataclass class Ser: def __repr__(self):

我想将数据类序列化为字符串。使用
dataclasses.asdict
和创建自定义
\uuuu str\uuu
方法很容易。它可以完美地工作,即使对于具有其他数据类或其列表作为成员的类也是如此。但是,在数据类列表上调用
str
会生成
repr
版本。我想
str
生成序列化表单,并
repr
保持原样

import json
from dataclasses import dataclass, asdict


@dataclass
class Ser:
    def __repr__(self):
        print('repr called')
        return json.dumps(asdict(self))

    def __str__(self):
        print('str called')
        return json.dumps(asdict(self))


@dataclass(repr=False)
class C(Ser):
    i: int

    def __str__(self):
        print('child str called')
        return super().__str__()


list_in = json.loads('[{"i": 1}, {"i": 2}]')
data = [C(**i) for i in list_in]
print(data)
print(repr(data))
print(str(data))
上述脚本的输出为:

repr called
repr called
[{"i": 1}, {"i": 2}]
repr called
repr called
[{"i": 1}, {"i": 2}]
repr called
repr called
[{"i": 1}, {"i": 2}]
奇怪的是,即使在通过列表显式请求字符串版本时,
str
方法也不会被调用。如果删除了
repr=False
,则会覆盖
repr
,并且不会调用任何自定义方法

想要的输出是:

>>> data  # I guess inspecting with the command line always calls repr
[C(i=1), C(i=2)]
>>> repr(data)
[C(i=1), C(i=2)]
>>> str(data)
[{"i": 1}, {"i": 2}]

列表的
str
调用其元素的
repr
,这就是它的实现方式。关于如何实现元素类的任何内容都不会改变这一点。因此,如果您不想干预数据类的
\uuu repr\uuu
,则必须使用自己的集合类,而不是
列表,例如:

class StrList(list):
    def __str__(self):
        return '[' + ', '.join(str(x) for x in self) + ']'


lst = StrList([1, '1'])
str(lst)
# '[1, 1]'
repr(lst)
# "[1, '1']"

如果您确实想更改内置类型(如
列表
)的
\uu str
,您可以查看

您从未明确要求数据的
str
,而是要求数据列表的
str
。列出对其元素的隐式调用
repr
。即使您在顶级或任何列表中绕过了这一点,中间对象也可以自由决定如何对
str
做出反应。有点奇怪,但我相信这是有原因的。谢谢您可以在给定的示例中看到,元素的
str
丢失了有关其类型的一些信息。这可能是一个原因。想象一下列表中包含逗号的字符串。从这些列表的表示形式中,您不会知道任何关于这些列表的信息。是的,但在本文中,我希望它能够生成类似JSON的输出,这样就不会丢失有关该类型的信息。说得好。