I would like to ignore the default values after calling asdict()
@dataclass
class A:
a: str
b: bool = True
so if I call
a = A("1")
result = asdict(a, ignore_default=True)
assert {"a": "1"} == result # the "b": True should be deleted
The dataclasses
module doesn't appear to have support for detecting default values in asdict()
, however the dataclass-wizard
library does -- via skip_defaults
argument.
Example:
from dataclasses import dataclass
from dataclass_wizard import asdict
@dataclass
class A:
a: str
b: bool = True
a = A("1")
result = asdict(a, skip_defaults=True)
assert {"a": "1"} == result # the "b": True should be deleted
Further, results show it is close to 2x faster than an approach with dataclasses.adict()
.
I've added benchmark code I used for testing below.
from dataclasses import dataclass, asdict as asdict_orig, MISSING
from timeit import timeit
from dataclass_wizard import asdict
@dataclass
class A:
a: str
b: bool = True
def asdict_factory(cls):
def factory(obj: list[tuple]) -> dict:
d = {}
for k, v in obj:
field_value = cls.__dataclass_fields__[k].default
if field_value is MISSING or field_value != v:
d[k] = v
return d
return factory
a = A("1")
A_fact = asdict_factory(A)
print('dataclass_wizard.asdict(): ', timeit('asdict(a, skip_defaults=True)', globals=globals()))
print('dataclasses.asdict(): ', timeit('asdict_orig(a, dict_factory=A_fact)', globals=globals()))
result1 = asdict(a, skip_defaults=True)
result2 = asdict_orig(a, dict_factory=A_fact)
assert {"a": "1"} == result1 == result2
a2 = A("1", True)
a3 = A("1", False)
assert asdict(a2, skip_defaults=True) == asdict_orig(a2, dict_factory=A_fact)
assert asdict(a3, skip_defaults=True) == asdict_orig(a3, dict_factory=A_fact)
Disclaimer: I am the creator and maintainer of this library.