Pretty-print dataclasses prettier with line breaks and indentation
pretty-print, python, python-dataclasses
Solution
The `pprint` package supports pretty printing only since version 3.10 (NB: Python 3.10 was released in 2021).
Example:
[ins] In [1]: from dataclasses import dataclass
...:
...: @dataclass
...: class Point:
...: x: int
...: y: int
...:
...: @dataclass
...: class Coords:
...: my_points: list
...: my_dict: dict
...:
...: coords = Coords([Point(1, 2), Point(3, 4)], {'a': (1, 2), (1, 2): 'a'})
[ins] In [15]: pprint.pprint(coords, width=20)
Coords(my_points=[Point(x=1,
y=2),
Point(x=3,
y=4)],
my_dict={'a': (1,
2),
(1, 2): 'a'})
When using Python 3.9 or older, there is the prettyprinter package that supports dataclasses and provides some nice pretty-printing features.
Example:
[ins] In [1]: from dataclasses import dataclass
...:
...: @dataclass
...: class Point:
...: x: int
...: y: int
...:
...: @dataclass
...: class Coords:
...: my_points: list
...: my_dict: dict
...:
...: coords = Coords([Point(1, 2), Point(3, 4)], {'a': (1, 2), (1, 2): 'a'})
[nav] In [2]: import prettyprinter as pp
[ins] In [3]: pp.pprint(coords)
Coords(my_points=[Point(x=1, y=2), Point(x=3, y=4)], my_dict={'a': (1, 2), (1, 2): 'a'})
The dataclasses support isn't enabled, by default, thus:
[nav] In [4]: pp.install_extras()
[ins] In [5]: pp.pprint(coords)
Coords(
my_points=[Point(x=1, y=2), Point(x=3, y=4)],
my_dict={'a': (1, 2), (1, 2): 'a'}
)
Or to force indenting of all fields:
[ins] In [6]: pp.pprint(coords, width=1)
Coords(
my_points=[
Point(
x=1,
y=2
),
Point(
x=3,
y=4
)
],
my_dict={
'a': (
1,
2
),
(
1,
2
): 'a'
}
)
Prettyprinter can even syntax-highlight! (cf. `cpprint()`)
Considerations:
- `prettyprinter` isn't part of the python standard library
- default values aren't printed, at all and as of 2021 there is no way around this
- `prettyprinter` is pretty-printing very slowly, i.e. much slower than the standard `pprint`, e.g. for checking if a value is a default value, it's compared against a default-constructed value
Problem
Python Data Classes instances also include a string representation method, but its result isn't really sufficient for pretty printing purposes when classes have more than a few fields and/or longer field values. Basically I'm looking for a way to customize the default dataclasses string representation routine or for a pretty-printer that understands data classes and prints them prettier. So, it's just a small customization I have in mind: adding a line break after each field while indenting lines after the first one. For example, instead of ``` x = InventoryItem('foo', 23) print(x) # => InventoryItem(name='foo', unit_price=23, quantity_on_hand=0) ``` I want to get a string representation like this: ``` x = InventoryItem('foo', 23) print(x) # => InventoryItem( name='foo', unit_price=23, quantity_on_hand=0 ) ``` Or similar. Perhaps a pretty-printer could get even fancier, such as aligning the `=` assignment characters or something like that. Of course, it should also work in a recursive fashion, e.g. fields that are also dataclasses should be indented more.