
On Wed, Jul 26, 2017 at 8:10 PM, Steven D'Aprano <steve@pearwood.info> wrote:
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 +