Given a dataclass
instance, I would like print()
or str()
to only list the non-default field values. This is useful when the dataclass
has many fields and only a few are changed.
@dataclasses.dataclass
class X:
a: int = 1
b: bool = False
c: float = 2.0
x = X(b=True)
print(x) # Desired output: X(b=True)
The solution is to add a custom __str__()
function:
@dataclasses.dataclass
class X:
a: int = 1
b: bool = False
c: float = 2.0
def __str__(self):
"""Returns a string containing only the non-default field values."""
s = ', '.join(f'{field.name}={getattr(self, field.name)!r}'
for field in dataclasses.fields(self)
if getattr(self, field.name) != field.default)
return f'{type(self).__name__}({s})'
x = X(b=True)
print(x) # X(b=True)
print(str(x)) # X(b=True)
print(repr(x)) # X(a=1, b=True, c=2.0)
print(f'{x}, {x!s}, {x!r}') # X(b=True), X(b=True), X(a=1, b=True, c=2.0)
This can also be achieved using a decorator:
def terse_str(cls): # Decorator for class.
def __str__(self):
"""Returns a string containing only the non-default field values."""
s = ', '.join(f'{field.name}={getattr(self, field.name)}'
for field in dataclasses.fields(self)
if getattr(self, field.name) != field.default)
return f'{type(self).__name__}({s})'
setattr(cls, '__str__', __str__)
return cls
@dataclasses.dataclass
@terse_str
class X:
a: int = 1
b: bool = False
c: float = 2.0