Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the data type returned by dict.viewkeys()? [ python 2.7 ]

I am studying dict.viewkeys() today, I found that my python calls it dict_keys object. And I can deal it as an iterable, but it's not a generator, because I can iterate over it more than once.

By my limited knowledge, I know only a few data types such as String, int, float, list, dict, tuple, set.

But yesterday I learned that enumerate() returns a special pair of data which can be used by dict() only once, thus it's a special tuple generator with (index_of_iteration, item) value

Is this dict_keys object another "I don't know what it exactly is but I know how to use it" type of object in python, or something else?

like image 821
Zen Avatar asked Apr 06 '14 05:04

Zen


2 Answers

It returns a dictionary view object (https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects).

This is a dynamic view of the elements in a dictionary. i.e. if you have a view to the keys in a dictionary, if you delete a key from the dictionary it will also be deleted from the view. See the examples below.

From the docs:

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.viewkeys()
>>> values = dishes.viewvalues()

>>> # iteration
>>> n = 0
>>> for val in values:
...     n += val
>>> print(n)
504

>>> # keys and values are iterated over in the same order
>>> list(keys)
['eggs', 'bacon', 'sausage', 'spam']
>>> list(values)
[2, 1, 1, 500]

>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['spam', 'bacon']

>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}

Also see: What are Python dictionary view objects?

like image 125
ebarr Avatar answered Oct 19 '22 10:10

ebarr


if you enter into the shell:

print type(dct.viewkeys())

it will return:

<type 'dict_keys'>

dict_keys is a Dictionary view object, new in Python 2.7.

from PEP 3106:

The dictionary methods keys(), values(), and items() are different in Python 3.x. They return an object called a view instead of a fully materialized list.

It’s not possible to change the return values of keys(), values(), and items() in Python 2.7 because too much code would break. Instead the 3.x versions were added under the new names viewkeys(), viewvalues(), and viewitems().

>>>
>>> d = dict((i*10, chr(65+i)) for i in range(26))
>>> d
{0: 'A', 130: 'N', 10: 'B', 140: 'O', 20: ..., 250: 'Z'}
>>> d.viewkeys()
dict_keys([0, 130, 10, 140, 20, 150, 30, ..., 250])

Views are iterable, but the key and item views also behave like sets; & performs intersection, and | performs union:

>>>
>>> d1 = dict((i*10, chr(65+i)) for i in range(26))
>>> d2 = dict((i**.5, i) for i in range(1000))
>>> d1.viewkeys() & d2.viewkeys()
set([0.0, 10.0, 20.0, 30.0])
>>> d1.viewkeys() | range(0, 30)
set([0, 1, 130, 3, 4, 5, 6, ..., 120, 250])

The view keeps track of the dictionary and its contents change as the dictionary is modified:

>>>
>>> vk = d.viewkeys()
>>> vk
dict_keys([0, 130, 10, ..., 250])
>>> d[260] = '&'
>>> vk
dict_keys([0, 130, 260, 10, ..., 250])

However, note that you can’t add or remove keys while you’re iterating over the view:

>>>
>>> for k in vk:
...     d[k*2] = k
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
like image 23
OrangeCube Avatar answered Oct 19 '22 10:10

OrangeCube