Is some_dict.items() an iterator in Python?

Viewed 3190

I'm a little confused over the difference between iterators and iterables. I've done a lot of reading and have got this much:

Iterator: An object that has __next__ in it’s class. You can call next() on it. All iterators are iterable.

Iterable: An object that defines __iter__ or __getitem__ in it's class. Something is iterable if it can build an iterator using iter(). Not all iterables are iterators.

Is some_dict.items() an iterator? I know that some_dict.iteritems() would be in Python2 right?

I'm just checking because a course I'm doing says it is and I'm pretty sure it's just an iterable (not an iterator).

Thanks for your help :)

4 Answers

No, it isn't. It is an iterable view of the items in the dict:

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

It's __iter__ method returns a specialized iterator instance:

>>> iter({}.items())
<dict_itemiterator object at 0x10478c1d8>
>>>

dict.items returns a dict view, according to the docs:

In [5]: d = {1: 2}

In [6]: next(d.items())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-945b6258a834> in <module>()
----> 1 next(d.items())

TypeError: 'dict_items' object is not an iterator

In [7]: next(iter(d.items()))
Out[7]: (1, 2)

Answering your question, dict.items is not an iterator. It is an iterable object which supports len, __contains__ and reflects changes made in the original dict:

In [14]: d = {1: 2, 3: 4}

In [15]: it = iter(d.items())

In [16]: next(it)
Out[16]: (1, 2)

In [17]: d[3] = 5

In [18]: next(it)
Out[18]: (3, 5)

You can test this directly:

from collections import Iterator, Iterable

a = {}
print(isinstance(a, Iterator))  # -> False
print(isinstance(a, Iterable))  # -> True
print(isinstance(a.items(), Iterator))  # -> False
print(isinstance(a.items(), Iterable))  # -> True

Check it yourselves:

d = {'a': 1, 'b': 2}

it = d.items()
print(next(it))

This results in TypeError: 'dict_items' object is not an iterator.

On the other hand, you can always iterate through d.items() as:

d = {'a': 1, 'b': 2}

for k, v in d.items():
    print(k, v)

Or:

d = {'a': 1, 'b': 2}

it = iter(d.items())
print(next(it))  # ('a', 1)
print(next(it))  # ('b', 2)
Related