Newlines in OrderedDict.__repr__ and/or pprint(OrderedDict) would be helpful:

* closed; superseded by:
* "general pprint rewrite"

As a workaround, a suitable JSONEncoder and json.dumps(obj, indent=2) works alright.

On Dec 27, 2015 7:55 PM, "Steven D'Aprano" <> wrote:
On Sun, Dec 27, 2015 at 10:16:34AM -0700, Guido van Rossum wrote:

> I really feel you all are overworrying and overthinking this. A downside to
> me is that <...> isn't clear about what the type of the object is. The use
> case here is not sophisticated users, it's beginners who have accidentally
> managed to create a recursive list or dict. They have most likely not even
> encountered Ellipsis objects yet. There's nothing clearer than the current
> notation to help them see that they've done something unusual.

As a data point, or perhaps an anecdote point, I've been a regular on
the tutor@ and python-list@ lists for many years now, and I don't recall
seeing recursive lists being an issue. I can't categorically say that it
has *never* come up, but it certainly isn't common.

My sense is that the not-really-an-invariant-more-of-a-guideline that
eval'ing the repr of an object returns the object is not that important
here. There are many things you can put in a list which will break the
invariant. It is a little unfortunate that [...] is no longer a syntax
error, giving us this:

eval("[[...]]") == [[Ellipsis]]

but I don't see that as a problem worth fixing.

I think the repr of OrderedDict is fine the way it is, and I like
the fact that it uses a bare ... to refer to itself rather than
wrapping it in braces like regular dicts. It just looks nicer in the
OrderedDict repr:

OrderedDict([('key', ...)])


OrderedDict([('key', {...})])

I thought I would generate an extreme example, an OrderedDict with
multiple references to itself in values which contain references to
themselves as well:

py> from collections import OrderedDict
py> o = OrderedDict([(1, []), (2, {}), (3, ('a', []))])
py> o[1].append(o[1])
py> o[1].append(o)
py> o[2]['x'] = o[2]
py> o[2]['y'] = o
py> o[3][-1].append(o[3])
py> o[3][-1].append(o)
py> o[4] = o
py> o
OrderedDict([(1, [[...], ...]), (2, {'y': ..., 'x': {...}}), (3, ('a',
[(...), ...])), (4, ...)])

As an extreme case, I would hope that I would never need to debug
something this complex in real life, but I think it is useful to see all
the different kinds of recursive reprs in one place. I think it is
useful that they are all slightly different. If it looked like this:

OrderedDict([(1, [<...>, <...>]), (2, {'y': <...>, 'x': <...>}),
(3, ('a', [<...>, <...>])), (4, <...>)])

we would lose valuable hints about the types, and if they all used
object __repr__ the amount of visual noise would be overwhelming:

OrderedDict([(1, [<list object at 0xb7bcf7cc>, <collections.OrderedDict
object at 0xb7bcbc5c>]), (2, {'y': <collections.OrderedDict object at
0xb7bcbc5c>, 'x': <dict object at 0xb7c6f96c>}), (3, ('a', [<tuple
object at 0xb7bb320c>, <collections.OrderedDict object at
0xb7bcbc5c>])), (4, <collections.OrderedDict object at 0xb7bcbc5c>)])

Given the risk that any such change will break doctests, I don't think
this is a problem worth fixing:

+1 on keeping the status quo
-1 on using the verbose object.__repr__
-0.5 on consistently using <...> for all types
-0.5 on changing the repr of recursive OrderedDicts to be more like dict

Python-ideas mailing list
Code of Conduct: