On Thu, Feb 27, 2014 at 8:17 AM, David Mertz <mertz@gnosis.cx> wrote:
On Wed, Feb 26, 2014 at 12:54 PM, Ron Adam <ron3200@gmail.com> wrote:
For example you could say, we don't need dict.items because we can do...
zip(dict.keys(), dict.values())
Have we actually been promised that d.keys() and d.values() walk the (unordered) dictionary in the same order, for every Python implementation/version? While I think it is almost certainly true in practice, I haven't where this invariant is guaranteed:
Yes, it's promised. It's intrinsic to the definition of keys()/values(). http://docs.python.org/3.4/library/stdtypes.html#dict-views """ Keys and values are iterated over in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions. If keys, values and items views are iterated over with no intervening modifications to the dictionary, the order of items will directly correspond. This allows the creation of (value, key) pairs using zip(): pairs = zip(d.values(), d.keys()). Another way to create the same list is pairs = [(v, k) for (k, v) in d.items()]. """ http://docs.python.org/2/library/stdtypes.html#mapping-types-dict """ 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()). The same relationship holds for the iterkeys() and itervalues() methods: pairs = zip(d.itervalues(), d.iterkeys()) provides the same value for pairs. Another way to create the same list is pairs = [(v,k) for (k, v) in d.iteritems()]. """ The latter has a "CPython implementation detail" box immediately above the piece I quoted, which in a way emphasizes the fact that the bit not in the box is not CPython-specific. Note the criteria, by the way. You have to not modify the dictionary in any way in between. I believe CPython will maintain iteration order as long as the set of keys never changes, but it would be legal for a compliant Python implementation to assert-fail here: d = {1:2, 3:4, 5:6, 7:8, 9:10} items = list(d.items()) d[3] = 4 # Breakage assert items == list(d.items()) However, retrieval is safe. A compliant Python will never assert-fail if the breakage line is changed to: spam = d[3] # No breakage So a splay tree implementation (say) would have to have some other means of iterating, or it would have to not adjust itself on reads. ChrisA