776

Are there any applicable differences between dict.items() and dict.iteritems()?

From the Python docs:

dict.items(): Return a copy of the dictionary’s list of (key, value) pairs.

dict.iteritems(): Return an iterator over the dictionary’s (key, value) pairs.

If I run the code below, each seems to return a reference to the same object. Are there any subtle differences that I am missing?

#!/usr/bin/python

d={1:'one',2:'two',3:'three'}
print 'd.items():'
for k,v in d.items():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'

print 'd.iteritems():'   
for k,v in d.iteritems():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'   

Output:

d.items():
    they are the same object
    they are the same object
    they are the same object
d.iteritems():
    they are the same object
    they are the same object
    they are the same object
Josh Correia
  • 3,807
  • 3
  • 33
  • 50
the wolf
  • 34,510
  • 13
  • 53
  • 71
  • 50
    It's basically a difference in how they are computed. `items()` creates the items all at once and returns a list. `iteritems()` returns a generator--a generator is an object that "creates" one item at a time every time `next()` is called on it. – Joel Cornett May 05 '12 at 04:12
  • 10
    In your particular case, `d[k] is v` would always return True because python keeps an array of integer objects for all integers between -5 and 256: https://docs.python.org/2/c-api/int.html When you create an int in that range you actually just get back a reference to the existing object: `>> a = 2; b = 2 >> a is b True` But, `>> a = 1234567890; b = 1234567890 >> a is b False` – t_tia Nov 23 '15 at 16:09
  • 3
    @the_wolf I think would be better to add the python version of the doc you are referring to in the question. – Lorenzo Belli Jan 12 '17 at 16:23
  • 2
    Did `iteritems()` change to `iter()` in Python 3? The documentation link above doesn't seem to be matching up with this answer. – Gabriel Staples Apr 10 '18 at 19:54
  • 5
    Not exactly, @GabrielStaples. iteritems() is removed from dictionaries Python 3, and has no replacement. However, for the same effect, you do use iter(). e.g. iter(dict.items()). See pep 469: https://www.python.org/dev/peps/pep-0469/ – Zim Jul 31 '18 at 22:52
  • 1
    dict.iteritems is gone in Python3 – Trect Oct 16 '18 at 13:38
  • @GabrielStaples in python3 dict.items() is roughly the same as dict.iteritems() in python2 (or rather dict.viewitems()), both operate as a generator O(n), where python2 dict.items() iterates over the dict and returns a list of tuples. O(n*2) – Tcll Aug 10 '19 at 18:43

9 Answers9

942

It's part of an evolution.

Originally, Python items() built a real list of tuples and returned that. That could potentially take a lot of extra memory.

Then, generators were introduced to the language in general, and that method was reimplemented as an iterator-generator method named iteritems(). The original remains for backwards compatibility.

One of Python 3’s changes is that items() now return views, and a list is never fully built. The iteritems() method is also gone, since items() in Python 3 works like viewitems() in Python 2.7.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Keith
  • 42,110
  • 11
  • 57
  • 76
  • 175
    Note that you have missed a step in the evolution: the Py3 behavior isn't the same as `iteritems()`. It actually makes a full sequence-protocol object that also reflects changes to the dict (and is backed by the dict itself, rather than a redundant list)- it's been backported to 2.7 as `viewitems()`. – lvc May 05 '12 at 05:38
  • 3
    I'd like to learn about this in greater detail, but my google-fu is failing me. Could someone point me to documentation, articles or source that would help me better understand this? @lvc? – Stew Feb 10 '16 at 22:52
  • 10
    @Stew the change is described in [PEP 3106](https://www.python.org/dev/peps/pep-3106/) and there is a bit more in [what's new in python 3.0](https://docs.python.org/3/whatsnew/3.0.html#views-and-iterators-instead-of-lists) – Tadhg McDonald-Jensen Apr 22 '16 at 18:57
  • 1
    Sorry for elaborating on this ancient question but do I understand correctly that **`iteritems()` is always preferable over `items()`** in Python 2.x? – RubenGeert Nov 11 '18 at 07:39
  • 2
    @RubenGeert Most of the time, it doesn't matter. For really large dicts it might be preferable. – Keith Nov 12 '18 at 03:44
  • 1
    @RubenGeert. One place where it is *not* preferable is when you want to iterate over the original items, but make modifications to the underlying dict. – Mad Physicist Mar 11 '19 at 21:58
  • 1
    Is there any speed performance difference by calling two different methods? – jtcloud Jan 09 '20 at 20:09
105

dict.items() returns a list of 2-tuples ([(key, value), (key, value), ...]), whereas dict.iteritems() is a generator that yields 2-tuples. The former takes more space and time initially, but accessing each element is fast, whereas the second takes less space and time initially, but a bit more time in generating each element.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    Why is each element the same then? – the wolf May 05 '12 at 03:03
  • 9
    Why would you expect them to be different? – Ignacio Vazquez-Abrams May 05 '12 at 03:04
  • 4
    The "copy" in the docs doesn't mean that the elements are copied (if you want that, use `copy.deepcopy`). It means that it's a copy of the dictionary items: if you do `items = dct.items()` and then modify `dct` by adding/deleting keys or `dct[k] = other_v`, `items` will stay the same. – Danica May 05 '12 at 03:07
  • I did interpret 'copy' as meaning a deep copy and that the elements would be different... – the wolf May 05 '12 at 04:12
  • 5
    Nothing in Python is ever a deep copy unless explicitly documented as such. – Karl Knechtel May 05 '12 at 04:21
  • The 'copy' in the documentation seemed most similar to `l1=l[:]` -- i.e., a true copy versus just an added reference... – the wolf May 05 '12 at 06:36
  • 1
    @IgnacioVazquez-Abrams - Regarding "more space and time" : At what size of dictionary do they start to matter. Say I've a "large" dictionary `{1:'one', 2:'two', ... }` over which I want to iterate on a webserver and render the results. At what scale should I start to worry about choosing `.items()` vs `.iteritems()` for Python 2.7 ? – user Sep 19 '15 at 14:32
  • 1
    @buffer: Not really sure. My estimate would be 15-20 items, but I haven't tested that. – Ignacio Vazquez-Abrams Sep 19 '15 at 15:11
78

In Py2.x

The commands dict.items(), dict.keys() and dict.values() return a copy of the dictionary's list of (k, v) pair, keys and values. This could take a lot of memory if the copied list is very large.

The commands dict.iteritems(), dict.iterkeys() and dict.itervalues() return an iterator over the dictionary’s (k, v) pair, keys and values.

The commands dict.viewitems(), dict.viewkeys() and dict.viewvalues() return the view objects, which can reflect the dictionary's changes. (I.e. if you del an item or add a (k,v) pair in the dictionary, the view object can automatically change at the same time.)

$ python2.7

>>> d = {'one':1, 'two':2}
>>> type(d.items())
<type 'list'>
>>> type(d.keys())
<type 'list'>
>>> 
>>> 
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
>>> type(d.iterkeys())
<type 'dictionary-keyiterator'>
>>> 
>>> 
>>> type(d.viewitems())
<type 'dict_items'>
>>> type(d.viewkeys())
<type 'dict_keys'>

While in Py3.x

In Py3.x, things are more clean, since there are only dict.items(), dict.keys() and dict.values() available, which return the view objects just as dict.viewitems() in Py2.x did.

But

Just as @lvc noted, view object isn't the same as iterator, so if you want to return an iterator in Py3.x, you could use iter(dictview) :

$ python3.3

>>> d = {'one':'1', 'two':'2'}
>>> type(d.items())
<class 'dict_items'>
>>>
>>> type(d.keys())
<class 'dict_keys'>
>>>
>>>
>>> ii = iter(d.items())
>>> type(ii)
<class 'dict_itemiterator'>
>>>
>>> ik = iter(d.keys())
>>> type(ik)
<class 'dict_keyiterator'>
Community
  • 1
  • 1
YaOzI
  • 16,128
  • 9
  • 76
  • 72
35

You asked: 'Are there any applicable differences between dict.items() and dict.iteritems()'

This may help (for Python 2.x):

>>> d={1:'one',2:'two',3:'three'}
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>

You can see that d.items() returns a list of tuples of the key, value pairs and d.iteritems() returns a dictionary-itemiterator.

As a list, d.items() is slice-able:

>>> l1=d.items()[0]
>>> l1
(1, 'one')   # an unordered value!

But would not have an __iter__ method:

>>> next(d.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator

As an iterator, d.iteritems() is not slice-able:

>>> i1=d.iteritems()[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dictionary-itemiterator' object is not subscriptable

But does have __iter__:

>>> next(d.iteritems())
(1, 'one')               # an unordered value!

So the items themselves are same -- the container delivering the items are different. One is a list, the other an iterator (depending on the Python version...)

So the applicable differences between dict.items() and dict.iteritems() are the same as the applicable differences between a list and an iterator.

dawg
  • 98,345
  • 23
  • 131
  • 206
14

dict.items() return list of tuples, and dict.iteritems() return iterator object of tuple in dictionary as (key,value). The tuples are the same, but container is different.

dict.items() basically copies all dictionary into list. Try using following code to compare the execution times of the dict.items() and dict.iteritems(). You will see the difference.

import timeit

d = {i:i*2 for i in xrange(10000000)}  
start = timeit.default_timer() #more memory intensive
for key,value in d.items():
    tmp = key + value #do something like print
t1 = timeit.default_timer() - start

start = timeit.default_timer()
for key,value in d.iteritems(): #less memory intensive
    tmp = key + value
t2 = timeit.default_timer() - start

Output in my machine:

Time with d.items(): 9.04773592949
Time with d.iteritems(): 2.17707300186

This clearly shows that dictionary.iteritems() is much more efficient.

Prabhu
  • 5,296
  • 4
  • 37
  • 45
11

dict.iteritems is gone in Python3.x So use iter(dict.items()) to get the same output and memory alocation

Framester
  • 33,341
  • 51
  • 130
  • 192
Trect
  • 2,759
  • 2
  • 30
  • 35
4

If you have

dict = {key1:value1, key2:value2, key3:value3,...}

In Python 2, dict.items() copies each tuples and returns the list of tuples in dictionary i.e. [(key1,value1), (key2,value2), ...]. Implications are that the whole dictionary is copied to new list containing tuples

dict = {i: i * 2 for i in xrange(10000000)}  
# Slow and memory hungry.
for key, value in dict.items():
    print(key,":",value)

dict.iteritems() returns the dictionary item iterator. The value of the item returned is also the same i.e. (key1,value1), (key2,value2), ..., but this is not a list. This is only dictionary item iterator object. That means less memory usage (50% less).

  • Lists as mutable snapshots: d.items() -> list(d.items())
  • Iterator objects: d.iteritems() -> iter(d.items())

The tuples are the same. You compared tuples in each so you get same.

dict = {i: i * 2 for i in xrange(10000000)}  
# More memory efficient.
for key, value in dict.iteritems():
    print(key,":",value)

In Python 3, dict.items() returns iterator object. dict.iteritems() is removed so there is no more issue.

Hary Bakta
  • 499
  • 4
  • 5
0

dict.iteritems(): gives you an iterator. You may use the iterator in other patterns outside of the loop.

student = {"name": "Daniel", "student_id": 2222}

for key,value in student.items():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

for key,value in student.iteritems():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

studentIterator = student.iteritems()

print(studentIterator.next())
('student_id', 2222)

print(studentIterator.next())
('name', 'Daniel')
-6

dict.iteritems() in python 2 is equivalent to dict.items() in python 3.

user128364
  • 4,533
  • 3
  • 20
  • 12