[Python-ideas] namedtuple literals [Was: RE a new namedtuple]

Koos Zevenhoven k7hoven at gmail.com
Wed Jul 26 17:50:09 EDT 2017

On Wed, Jul 26, 2017 at 8:10 PM, Steven D'Aprano <steve at pearwood.info>

> On Thu, Jul 27, 2017 at 02:05:47AM +1000, Nick Coghlan wrote:
> >     >>> from collections import OrderedDict
> >     >>> OrderedDict(x=1, y=2)
> >     OrderedDict([('x', 1), ('y', 2)])
> >     >>> OrderedDict(y=2, x=1)
> >     OrderedDict([('y', 2), ('x', 1)])
> >
> > In this case, the "order matters" expectation is informed by the
> > nature of the constructor being called: it's an *ordered* dict, so the
> > constructor argument order matters.
> I don't think that's a great analogy. There's no real equivalent of
> packing/unpacking OrderedDicts by position to trip us up here. It is
> better to think of OrderedDicts as "order-preserving dicts" rather than
> "dicts where the order matters". Yes, it does matter, in a weak sense.

Careful here, this is misleading. What you say applies to the normal dict
since 3.6, which now *preserves* order. But in OrderedDict, order matters
in quite a strong way:

​od1 = OrderedDict(a=1, b=2)
od2 = OrderedDict(b=2, a=1)  # (kwargs order obviously matters)
od1 == od2 # gives False !!

od1 == dict(a=1, b=2) # gives True
od2 == dict(a=1, b=2) # gives True
od1 == OrderedDict(a=1, b=2) # gives True ​

​I also think this is how OrderedDict *should* behave to earn its name.
It's great that we now also have an order-*preserving* dict, because ​often
you want that, but still dict(a=!, b=2) == dict(b=2, a=1).

But not in the important sense of binding values to keys:
> py> from collections import OrderedDict
> py> a = OrderedDict([('spam', 1), ('eggs', 2)])
> py> b = OrderedDict([('eggs', -1), ('spam', 99)])
> py> a.update(b)
> py> a
> OrderedDict([('spam', 99), ('eggs', -1)])
> update() has correctly bound 99 to key 'spam', even though the keys are
> in the wrong order. The same applies to dict unpacking:
​​​The reason for this is that the order is determined by the first
binding, not by subsequent​ updates to already-existing keys.​

> a.update(**b)
>Unpacking by name is still ordered in a.update(**b), but the update order
does not matter, because keys 'spam' and 'eggs' already exist.

> In contrast, named tuples aren't just order-preserving. The field order
> is part of their definition, and tuple unpacking honours the field
> order, not the field names. While we can't update tuples in place, we
> can and often do unpack them into variables. When we do, we need to know
> the field order:
​I hope this was already clear to people in the discussion, but in case
not, thanks for clarifying.​

> flavour, charge, mass, spin, isospin, hypercharge = mytuple
> but the risk is that the field order may not be what we expect unless we
> are scrupulously careful to *always* call ntuple(...) with the arguments
> in the same order.
This is indeed among the reasons why the tuple api is desirable mostly for
backwards compatibility in existing functions, as pointed out early in this
thread. New functions will hopefully use something with only attribute
access to the values, unless there is a clear reason to also have integer
indexing and unpacking by order.

​-- Koos​

+ Koos Zevenhoven + http://twitter.com/k7hoven +
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170727/3a6d41ef/attachment.html>

More information about the Python-ideas mailing list