Profile photo

from miller import blake

Hello, I'm a systems administrator, I get paid to be a software developer, I like Python, I'm a fan of good design, and I don't think things always have to be so stupid.
You can follow me @bltmiller, subscribe via RSS, and email me.

Get a List of Keys From a Dictionary in Both Python 2 and Python 3

It was mentioned in an earlier post that there is a difference in how the keys() operation behaves between Python 2 and Python 3. If you’re adapting your Python 2 code to Python 3 (which you should), it will throw a TypeError when you try to operate on keys() like a list. So, if you depend on getting a list returned from keys(), here’s how to make it work for both Python 2 and Python 3.

In Python 2, simply calling keys() on a dictionary object will return what you expect:

$ python
>>> foo = { 'bar': "hello", 'baz': "world" }
>>> type(foo.keys())
<type 'list'>
>>> foo.keys()
['baz', 'bar']
>>> foo.keys()[0]
'baz'

That’s great, however, in Python 3, keys() no longer returns a list, but a view object:

The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.

The dict_keys object is an iterator and looks a lot more like a set than a list. So using the same call in Python 3 would produce this result:

$ python3
>>> foo = { 'bar': "hello", 'baz': "world" }
>>> type(foo.keys())
<class 'dict_keys'>
>>> foo.keys()
dict_keys(['baz', 'bar'])
>>> foo.keys()[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'dict_keys' object does not support indexing

The TypeError can be avoided and compatibility can be maintained by simply converting the dict_keys object into a list which can then be indexed as normal in both Python 2 and Python 3:

$ python3
>>> foo = { 'bar': "hello", 'baz': "world" }
>>> type(list(foo.keys()))
<class 'list'>
>>> list(foo.keys())
['baz', 'bar']
>>> list(foo.keys())[0]
'baz'

And just for good measure, here it is in Python 2:

$ python
>>> foo = { 'bar': "hello", 'baz': "world" }
>>> type(list(foo.keys()))
<class 'list'>
>>> list(foo.keys())
['baz', 'bar']
>>> list(foo.keys())[0]
'baz'

comments powered by Disqus

Copyright © 2016, Blake Miller. All rights reserved. | Sitemap · RSS