pprint with custom float formats
Asked Answered
C

1

10

I have a nested dictionary structure with tuple keys. Here's what an entry looks like when I pretty-print the dictionary using pprint:

...
 ('A', 'B'): {'C': 0.14285714285714285,
              'D': 0.14285714285714285,
              'E': 0.14285714285714285,
              'F': 0.14285714285714285,
              'G': 0.14285714285714285,
              'H': 0.14285714285714285,
              'I': 0.14285714285714285},
...

It's pretty nifty, but I'd like to customize it further by cutting down some extra digits from the floats. I was thinking that it'd be possible to achieve by subclassing pprint.PrettyPrint but I don't know how that would be done.

Thanks.

Congreve answered 4/6, 2017 at 17:7 Comment(0)
N
11

As you said, you can achieve this by subclassing PrettyPrinter and overwriting the format method. Note that the output is not only the formatted string, but also some flags.

Once you're at it, you could also generalize this and pass a dictionary with the desired formats for different types into the constructor:

class FormatPrinter(pprint.PrettyPrinter):

    def __init__(self, formats):
        super(FormatPrinter, self).__init__()
        self.formats = formats

    def format(self, obj, ctx, maxlvl, lvl):
        if type(obj) in self.formats:
            return self.formats[type(obj)] % obj, 1, 0
        return pprint.PrettyPrinter.format(self, obj, ctx, maxlvl, lvl)

Example:

>>> d = {('A', 'B'): {'C': 0.14285714285714285,
...                   'D': 0.14285714285714285,
...                   'E': 0.14285714285714285},
...       'C': 255}
...
>>> FormatPrinter({float: "%.2f", int: "%06X"}).pprint(d)
{'C': 0000FF,
 ('A', 'B'): {'C': 0.14,
              'D': 0.14,
              'E': 0.14}}
Nephralgia answered 4/6, 2017 at 17:24 Comment(5)
what about super(FormatPrinter, self) instead of pprint.PrettyPrinter?Palmira
You probably want to take general formatting functions. So FormatPrinter({float: '{0:.2f}'.format}), and have it return self.formats[type(obj)](obj).Sharlasharleen
@Sharlasharleen Yes, that's a possibility, too. Might be more versatile than just passing the format strings, but also a bit more verbose.Nephralgia
@Sharlasharleen Yeah, that's what I did. Thanks for your additional input. :)Aery
Thank you for your input. I use your code with the following changes: def __init__(self, **kwargs): kwargsNext = { key: kwargs[key] for key in kwargs if key != 'formats' } super().__init__(**kwargsNext) self.formats = kwargs['formats']Hanni

© 2022 - 2025 — McMap. All rights reserved.