In python 2 when using an OrderedDict
I was able to get the keys in the order they were inserted by simply using the keys
method that returned a list. In python 3 however:
rows = OrderedDict()
rows[0]=[1,2,3]
rows[1]=[1,2,3]
image = [rows[k] for k in rows.keys()[:2]]
I get:
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'odict_keys' object is not subscriptable
I certainly can do list(rows)[:2]
as advised for instance here - but is this guaranteed to get me the keys in order ? Is this the one right way ?
UPDATE: the python 2 code would be better as:
image = [v for v in rows.values()[:2]]
which of course still blows with the same error on python 3
Python 3.6 (CPython) As of Python 3.6, for the CPython implementation of Python, dictionaries maintain insertion order by default. This is considered an implementation detail though; you should still use collections. OrderedDict if you want insertion ordering that's guaranteed across other implementations of Python.
Answer. No, there is no guaranteed order for the list of keys returned by the keys() function. In most cases, the key list is returned in the same order as the insertion, however, that behavior is NOT guaranteed and should not be depended on by your program.
Standard dict objects preserve order in the reference (CPython) implementations of Python 3.5 and 3.6, and this order-preserving property is becoming a language feature in Python 3.7.
Since dictionaries in Python 3.5 don't remember the order of their items, you don't know the order in the resulting ordered dictionary until the object is created. From this point on, the order is maintained. Since Python 3.6, functions retain the order of keyword arguments passed in a call.
@mglison is right. Because OrderedDict
follows the iterator protocol, it is guaranteed to yield
the keys in the correct order to list()
:
However, like @mglison also mentioned,itertools.islice()
would be better and more efficent than simply using list
and subscripting. After timing both methods multiple times using the timeit
module, the itertools
method was roughly 2x faster. Here are the exact numbers:
After getting the average time of running both list(itertools.islice(rows, 2))
and list(rows.keys())[:2]
(notice I'm casting the result of islice()
to a list) multiple times, it appears that using the latter method is actual slightly faster:
---------------------------------------------------------------
| list(itertools.islice(rows, 2)) | 1.5023668839901838 |
---------------------------------------------------------------
| list(rows.keys())[:2] | 1.495460570215706 |
---------------------------------------------------------------
However, the difference of the two numbers is so small, I really would not make much of difference which method you use. Just choose the method which is the most readable and understandable for your specific case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With