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

时间:2019-09-12 09:17:30

标签: python python-dataclasses

我想将数据类序列化为字符串。使用dataclasses.asdict并创建自定义__str__方法很容易。即使对于具有其他数据类或作为成员的列表的类,它也可以完美地工作。但是,在数据类列表上调用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}]

1 个答案:

答案 0 :(得分:1)

str的{​​{1}}调用其元素的list,这就是实现它的方式。关于如何实现元素类的任何事情都不会改变这一点。因此,如果您不想插入数据类的repr,则必须使用自己的集合类而不是__repr__,例如:

list

如果您确实要更改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']" 之类的内置类型的__str__,则可以查看forbiddenfruit