Я хотел бы сериализовать классы данных в строки. Это достаточно просто с 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}]
str
ваших данных, вы запрашиваетеstr
из списка ваших данных. Списки неявно вызываютrepr
для своих элементов. Даже если вы обойдете это для верхнего уровня или любого другого списка, промежуточные объекты также могут решать, как реагировать наstr
. - person MisterMiyagi   schedule 12.09.2019