dict.keys() and dict.values() are always the same order, is it?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Tue Apr 20 09:48:15 CEST 2010


On Mon, 19 Apr 2010 23:47:06 -0700, John Yeung wrote:

> On Apr 20, 1:23 am, Cameron Simpson <c... at zip.com.au> wrote:
>> On 19Apr2010 21:31, alex23 <wuwe... at gmail.com> wrote: | Cameron Simpson
>> <c... at zip.com.au> wrote: | >   If items(), keys(), values(),
>> iteritems(), iterkeys(), and | >   itervalues() are called with no
>> intervening modifications to the | >   dictionary, the lists will
>> directly correspond. This allows the | >   creation of (value, key)
>> pairs using zip(): pairs = zip(d.values(), | >   d.keys()).
>> |
>> | I stand corrected. Thanks Cameron.
>>
>> Oh, I was all ready to say what you said, but decided to check the docs
>> myself first:-)
> 
> I am not too comfortable relying on it.  It feels fragile and
> "implementationy" to me, as I'm sure it does to many people (such as
> everyone in this thread so far! ;)

It is a language feature that is guaranteed to be true for every 
implementation of Python, as much of a promise as the guarantee that 
sorted([3,1,2]) will return [1,2,3] or that [1,2,3][42:142] will return 
[] rather than fail. It's not an implementation detail that 
implementations are free to change, it is a promised language feature.

If it ever fails, that is a bug that needs to be reported.

Defensive programming is good, but at the point that you don't believe 
the promises that the language makes, how can you trust anything? You 
suggested 

pairs = [(v, k) for (k, v) in d.iteritems()]

as an alternative, but if you don't trust the language to behave 
correctly in this case:

pairs = zip(d.values(), d.items())

what makes you think you can trust d.iteritems(), list comprehensions, or 
even tuple packing and unpacking?



> I do trust the docs on this issue,
> but every so often I forget that I read this bit of the docs, and am
> once again left with an insecure feeling about it.

*shrug*

This is no different to any other little-used feature. I personally never 
remember whether divmod(a,b) returns (a//b, a%b) or the other way around, 
but that doesn't mean that the behaviour of divmod is implementation 
dependent, or that I'm justified in feeling insecure about it. One 
behaviour is promised, and anything else would be a bug. It would be a 
waste of time and code for me to write

a//b, a%b

just because I can't remember what divmod() does.


> All in all, the
> alternative idiom for flipping keys and values (provided in the docs a
> couple of sentences down from your quote) is short enough for my taste,
> easy enough for me to read, and never makes me wonder if I should check
> the docs just to be sure:
> 
>   pairs = [(v, k) for (k, v) in d.iteritems()]

Yes, and if you can't remember whether or not ints are automatically 
promoted to longs, you will continue writing this long after it became 
unnecessary:

try:
    result = a + b
except OverflowError:
    result = long(a) + long(b)

and then other coders will laugh at you :)

(But of course if you need to still support older versions of Python, 
then it isn't silly at all.)




-- 
Steven



More information about the Python-list mailing list