https://docs.python.org/3/tutorial/classes.html
https://docs.python.org/3/library/functions.html#iter
https://docs.python.org/3/library/stdtypes.html#typeiter
Three notions:
(1) an iterable is anything that you can iterate over
[iter() can build an iterator],
(2) an iterator is the thing that does the actual iterating
[__iter__() and __next__() methods should be present],
(3) generators are one of the simpler ways to create your own iterators
['lazy evaluation'; generator expressions and generator functions].
for item in iterable: # iteration print(item) L = list(iterable) result = sum(iterable) high = max(iterable) low = min(iterable)
# Builtin function. reversed(sequence) # reversed object
# Generator expression. sequence = "word" gen = (sequence[i] for i in range(len(sequence)-1,-1,-1)) # generator object
# Generator function. def Reverse(sequence): # a generator iterator is returned """A reverse iterator based on a sequence.""" idx = len(sequence) while idx > 0: idx = idx-1 yield sequence[idx]
# The other version based on a class. class Reverse: # an instance of this class is an iterator """A reverse iterator based on a sequence.""" def __init__(self, sequence): self.sequence = sequence self.idx = len(sequence) def __iter__(self): # for the iter() function return self def __next__(self): # for the next() function if self.idx == 0: raise StopIteration self.idx -= 1 return self.sequence[self.idx] next = __next__ # compatibility # Python 2 has X.next(). # Python 3 has X.__next__(). # Python 3 i 2.6+ have a builtin function next(X).
# Usage (for both versions). for char in Reverse("spam"): print(char) # m, a, p, s for item in Reverse([1, 2, 3, 4]): print(item) # 4, 3, 2, 1
# iter(iterable) return iterator # iter(callable, sentinel) return iterator # an iterator based on a sequence it1 = iter([1, 2]) # list_iterator object in Py3 (lists have __iter__) it2 = iter("abcd") # str_iterator object in Py3 (strings have __iter__) it3 = iter(it2) # all iterators are also iterables assert it3 is it2 # Once you have an iterator, the only thing you can do with it is get # its next item. And you’ll get a stop iteration exception if you ask # for the next item but there aren’t anymore items. print(next(it1)) # 1 print(next(it1)) # 2 print(next(it1)) # StopIteration
class Dumb: def __init__(self, sequence): self.data = sequence def __getitem__(self, n): return self.data[n] x = Dumb("word") print(x[1]) # o #print(x[10]) # IndexError: string index out of range #len(x) # AttributeError: Dumb instance has no attribute '__len__' for item in x: # iteration print(item) # manual iteration y = iter(x) # make an iterator, iter() use the sequence protocol (__getitem__) print(next(y)) # w print(next(y)) # o print(next(y)) # r print(next(y)) # d print(next(y)) # StopIteration, the iterator is exhausted
# Chunking list by two using an iterator. it = iter(range(6)) list(zip(it, it)) # [(0, 1), (2, 3), (4, 5)]
# https://www.programiz.com/python-programming/iterator for element in iterable: # do something with element process(element) # It is equivalent to the following code. # create an iterator object from that iterable iter_obj = iter(iterable) # infinite loop while True: try: # get the next item element = next(iter_obj) # do something with element process(element) except StopIteration: # if StopIteration is raised, break from loop break
class MyInt: def __init__(self): self.n = -1 def __call__(self): self.n = self.n + 1 return self.n x = MyInt() # x is a MyInt instance, a callable object print(x()) # returns 0 print(x()) # returns 1 print(x()) # returns 2
# Preparing an iterator 'y'. # If the callable returns 5 then y stops. y = iter(MyInt(), 5) # y is a callable-iterator object for i in y: # returns 0, 1, 2, 3, 4 (without 5) print(i) # 5 was used to stop the iterator y. print(next(y)) # StopIteration is raised, y is exhausted
# Infinite iterators. import itertools iter_zeros1 = iter(int, 1) # int() gives 0 iter_zeros2 = iter((lambda: 0), 1) iter_zeros3 = itertools.cycle([0]) # itertools.cycle(sequence) iter_zeros4 = itertools.repeat(0) # itertools.repeat(x, times=5)