3

When I try running this code:

from pprint import PrettyPrinter

class MyPrettyPrinter(PrettyPrinter):
    def __init__(self, *args, **kwargs):
        PrettyPrinter.__init__(self, *args, **kwargs)
    def format(self, object, context, maxlevels, level):
        (repr, readable, recursive) = PrettyPrinter.format(self, object, context, maxlevels, level)
        return (type(repr)(object), readable, recursive) if isinstance(object, str) else (repr, readable, recursive)

print(MyPrettyPrinter().pformat(['x']))

I get a different output in Python 3 (['x']) than I get in Python 2 ([x]).

Why is this, and how do I get the same behavior as in Python 2?

user541686
  • 205,094
  • 128
  • 528
  • 886

1 Answers1

2

This is how Python 3’s internal _format function works:

def _format(self, object, stream, indent, allowance, context, level):
    # …
    rep = self._repr(object, context, level - 1)
    max_width = self._width - 1 - indent - allowance
    sepLines = len(rep) > max_width

    if sepLines:
        # … custom repr logic
    write(rep)

As you can see, if the the output of _repr fits into a single line, then no custom logic for generating the repr is used. self._repr delegates to self.format, which essentially just does a more complex repr(). So this is just called once if the output fits in a single line; otherwise, the output is not used but the (here: sequence) element is split into multiple parts, and the logic is again invoked for subelements.

In comparison, Python 2’s _format implements a completely custom logic at any stage, always invoking the custom formatter for all subelements in lists. That’s why your trigger works in Python 2 but does not in Python 3.

Unfortunately, I don’t see any simple way to hook into this without replicating a lot of the logic that’s in the new Python 3 implementation.

poke
  • 369,085
  • 72
  • 557
  • 602
  • +1 huh, interesting. Would you call this a bug? It seems like a bug to me but I'm not sure if it was intentional... – user541686 Aug 23 '15 at 19:14
  • I wouldn’t call it a bug, as it’s kind of an implementation detail. But it does seem odd to me that the documentation suggests subclassing the pretty printer but does not ensure that `format` is called for each level. – poke Aug 23 '15 at 19:25