Nested loops is strangely slow, totally at a loss.

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Dec 10 09:38:58 EST 2014


Shiyao Ma wrote:

> Thanks guys.
> 
> I was only aware of a limited iterables which themselves are iterators,
> e.g., the generator.
> 
> Seems like its really a pitfall. Any glossary, list on the iterables that
> *might* exhaust themselves?

Iterables include:

- iterators
- sequences (e.g. lists, tuples, xrange objects)
- collections such as dicts, sets, etc.
- strings (byte strings and unicode strings)


Only iterators can be exhausted, since they generate their values on-call,
not in advance, and once a value is extracted, it's gone.

Iterators are not a type or class, they are objects which obey the iterator
protocol. In other words, iterators are duck-typed, not all instances of
the same type.

How do you tell if something is an iterator? By duck-typing:

# is obj an iterator?
if iter(obj) is obj and hasattr(obj, "__next__"):
    # in Python 2, use "next" instead of "__next__"
    print("obj is an iterator")


In Python 3 you can also use an Abstract Base Class:

from collections.abc import Iterator
if isinstance(obj, Iterator):
     print("obj is an iterator")


You can also get a hint from the name:

py> print iter([])
<listiterator object at 0xb7bf690c>


A built-in type that claims to be a "something iterator" is very probably an
iterator.

Calling iter() on any iterable will return an iterator.

Generators are also iterators.

In Python 2, dicts have methods .iterkeys(), .itervalues(), .iteritems()
which return iterators.

Anything you get from the itertools module is likely to be an iterator.


-- 
Steven




More information about the Python-list mailing list