Iterators
Implicit Sequences
Rather than store every element in the memory, range computes values on demand. In computer science, lazy computation describes any program that delays the computation of a value until that value is needed.
Iterators
An iterator is an object that provides sequential access to values, one by one.
- retrieving the next element in the sequence being processed
- signaling that the end of the sequence has been reached and no further elements remain
The underlying series of data for an iterator may not be represented explicitly in memory. when the next element is requested from an iterator, that element may be computed on demand instead of being retrieved from an existing memory source.
iter and next
iter(iterable)Return an iterator over the elements of an iterable valuenext(iterator)Return the next element in an iterator
>>> primes = [2, 3, 5, 7]
>>> type(primes)
>>> iterator = iter(primes)
>>> type(iterator)
>>> next(iterator)
2
>>> next(iterator)
3
>>> next(iterator)
5StopIteration Exception
>>> next(iterator)
7
>>> next(iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> try:
next(iterator)
except StopIteration:
print('No more values')
No more valuesRemainings
When a next is executed, the iterator has a pointer moved to the next element on the iteratable value, and never goes back.
>>> s = [1, 1, 4]
>>> t = iter(s)
>>> next(t)
1
>>> list(t)
[1, 4]
>>> next(t)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIterationMultiple Iterators
Two separate iterators can track two different positions in the same sequence. Calling iter on an iterator will return that iterator, not a copy.
Iterating on Dictionaries
All iterable
dict<class dict>dict.keys()<class dict_keys>dict.values()<class dict_values>dict.items()<class dict_items>- Tuples of key-value pair
Changing a Dictionary during Iteration
- Can do
- Change keys
- Change values
- Change items
- CANNOT do
- Change size
Built-in Iterators
All of them are lazy, only calculating the value (evaluating the body) on demand. They all return objects rather than a list or something else
map(func, iterable)
Iterate over func(x) for x in iterable
filter(func, iterable)
Iterate over x in iterable if func(x)
zip(first_iter, second_iter[, ...])
Iterate over co-indexed (x, y) pairs
reversed(sequence)
Iterate over x in a sequence in an reverse order
Viewing Iterators
Run the iteration until the end, and return the value. These create a new instance of the iterable.
list(iterable)tuple(iterable)sorted(iterable)
for Operates on Iterators
Objects are iterable (an interface) if they have an __iter__ method that returns an iterator.
for <name> in <expression>:
<suite>- To execute a for statement, Python evaluates the header
<expression>, which must yield an iterable value. - Then, the
__iter__method is invoked on that value. - Until a
StopIterationexception is raised, Python repeatedly invokes the__next__method on that iterator and binds the result to the<name>in the for statement. - Then, it executes the
<suite>.
Some trivia: [[CS61A/Labs/Lab06#Q6]]
Alike, if an element got passed in an iterator, a for statment will not deal with that element.
>>> ri = iter(range(3))
>>> next(ri)
0
>>> for i in ri:
... print(i)
...
1
2Using Iterators
An iterator bundles together a sequence and a position within that sequence as one object
- Passing that object to another function always retains the position
- Useful for ensuring that each element of a sequence is processed only once
- Limits the operations that can be performed on the sequence to only requesting
next