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

Fel*_*lix 5 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))
Run Code Online (Sandbox Code Playgroud)

上面脚本的输出是:

repr called
repr called
[{"i": 1}, {"i": 2}]
repr called
repr called
[{"i": 1}, {"i": 2}]
repr called
repr called
[{"i": 1}, {"i": 2}]
Run Code Online (Sandbox Code Playgroud)

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}]
Run Code Online (Sandbox Code Playgroud)

sch*_*ggl 4

stralist调用其元素的 the ,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']"
Run Code Online (Sandbox Code Playgroud)

如果你真的想改变__str__像这样的内置类型list,你可以看看forbiddenfruit