[Article 14] Python Iterator

Posted by FlashbackJon on Wed, 18 Sep 2019 08:48:11 +0200

Iterator

Iteration is a way of accessing set elements. Iterator is an object that can remember the location of traversal. Iterator objects are accessed from the first element of the collection until all elements are accessed. Iterators can only move forward and not backward.

1.1 Judging whether an object can be iterated

You can use isinstance() to determine whether an object is an Iterable object:
In [50]: from collections import Iterable

In [51]: isinstance([], Iterable)
Out[51]: True

In [52]: isinstance({}, Iterable)
Out[52]: True

In [53]: isinstance('abc', Iterable)
Out[53]: True

In [54]: isinstance(mylist, Iterable)
Out[54]: False

In [55]: isinstance(100, Iterable)
Out[55]: False

1.2 Essence of Iterable Objects

We analyze the process of iterating on an iterative object and find that every iteration (i.e. every iteration in... Will return the next data in the object, reading the data backwards until all the data is iterated. So, in this process, there should be a "person" to record the number of data accessed each time, so that each iteration can return the next data. We call this "human" who can help us iterate data an Iterator.
 
The essence of an iterative object is to provide us with an intermediate "human" that is, an iterator to help us iterate through it.
 
Iterable objects provide us with an iterator through the _iter_ method. When we iterate over an iterative object, we actually get an iterator provided by the object first, and then use this iterator to obtain each data in the object in turn.
 
That is to say, an object with _iter_ method is an iterative object.
 1 from collections import Iterable
 2 
 3 
 4 class MyList(object):
 5 
 6     def __init__(self):
 7         self.container = []
 8 
 9     def add(self, item):
10         self.container.append(item)
11 
12     def __iter__(self):
13         """Returns an iterator"""
14         pass
15 
16 
17 mylist = MyList()
18 print(isinstance(mylist, Iterable))     # True

This test found that the mylist object with the _iter_ method was already an iterative object.

1.3 iter() function and next() function

list, tuple, etc. are iteratable objects. We can get iterators of these iteratable objects by iter() function. Then we can use the next() function continuously to get the next data for the acquired iterator. The iter() function actually calls the _iter_ method of an iteratable object.
>>> li = [11, 22, 33, 44, 55]
>>> li_iter = iter(li)
>>> next(li_iter)
11
>>> next(li_iter)
22
>>> next(li_iter)
33
>>> next(li_iter)
44
>>> next(li_iter)
55
>>> next(li_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>

Note that when we have iterated over the last data, calling the next() function again throws an exception to StopIteration to tell us that all data has been iterated and that the next() function is no longer needed.

1.4 How to determine whether an object is an iterator

You can use isinstance() to determine whether an object is an Iterator object:

In [56]: from collections import Iterator

In [57]: isinstance([], Iterator)
Out[57]: False

In [58]: isinstance(iter([]), Iterator)
Out[58]: True

In [59]: isinstance(iter("abc"), Iterator)
Out[59]: True

1.5 Iterator

From the above analysis, we know that the iterator is used to help us record the location visited by each iteration. When we use the next() function for the iterator, the iterator will return to us the data of the next location at which it records. In fact, when you use the next() function, you call the _next_ method of the iterator object (python 3 is the _next_ method of the object, and python 2 is the next() method of the object). So, if we want to construct an iterator, we need to implement its _next_ method. But that's not enough. python requires that the iterator itself be iterative, so we also need to implement the _iter_ method for the iterator, and the _iter_ method returns an iterator. The iterator itself is an iterator, so the _iter_ method of the iterator can return itself.
 
An object that implements the _iter_ method and _next_ method is an iterator.
 1 # Implementing an iterator(Writing of Two Classes)
 2 class MyList(object):
 3     """
 4     A Customized Iterable Object
 5     """
 6 
 7     def __init__(self):
 8         self.items = []
 9 
10     def add(self, val):
11         self.items.append(val)
12 
13     def __iter__(self):
14         myiterator = MyIterator(self)
15 
16         return myiterator
17 
18 
19 class MyIterator(object):
20     """
21         A custom iterator for the above iteratable objects
22     """
23     def __init__(self, mylist):
24         self.mylist = mylist
25         # current Used to record current access locations
26         self.current = 0
27 
28     def __next__(self):
29         if self.current < len(self.mylist.items):
30             item = self.mylist.items[self.current]
31             self.current += 1
32             return item
33         else:
34             raise StopIteration
35 
36     def __iter__(self):
37         return self
38 
39 
40 if __name__ == '__main__':
41     mylist = MyList()
42     mylist.add(1)
43     mylist.add(2)
44     mylist.add(3)
45     mylist.add(4)
46     mylist.add(5)
47     for num in mylist:
48         print(num)
 1 Implementing an iterator(Write in a class) 
 2 class MyList(object):
 3 
 4 
 5     def __init__(self):
 6         self.container = []
 7         self.current = 0
 8 
 9 
10     def add(self, item):
11         self.container.append(item)
12 
13 
14     def __iter__(self):
15 
16 
17         return self
18 
19 
20     def __next__(self):
21         if self.current < len(self.container):
22             item = self.container[self.current]
23             self.current += 1
24             return item
25         else:
26             raise StopIteration
27 
28 
29 
30 
31 my_list = MyList()
32 my_list.add(1)
33 my_list.add(2)
34 my_list.add(3)
35 my_list.add(4)
36 my_list.add(5)
37 
38 
39 for num in my_list:
40     print(num)

1.6 The essence of the cycle for...in...

The essence of the iterator loop for item in Iterable is to obtain the iterator of Iterable by iter() function, and then call next() method to get the next value and assign it to item. When the exception of StopIteration is encountered, the loop ends.
 
The characteristics of the iterator:
  • Save memory
  • Inertia mechanism
  • You can't repeat it, you can only go down.

Application scenario of 1.7 iterator

Fibonacci sequence

 1 class FibIterator(object):
 2     """
 3         Fibonacci sequence
 4     """
 5 
 6     def __init__(self, n):
 7         """
 8         :param n:int, Specifies the front of the generated sequence n Number
 9         """
10         self.n = n
11         # current Used to save the number currently generated in a sequence
12         self.current = 0
13         # num1 Used to save the previous number, the initial value is the first number 0 in the sequence.
14         self.num1 = 0
15         # num2 Used to save the previous number, the initial value is the second number 1 in the sequence.
16         self.num2 = 1
17 
18     def __next__(self):
19         """
20         cover next()Function calls to get the next number
21         :return:
22         """
23 
24         if self.current < self.n:
25             num = self.num1
26             self.num1, self.num2 = self.num2, self.num1+self.num2
27             self.current += 1
28             return num
29         else:
30             raise StopIteration
31 
32     def __iter__(self):
33         """
34         "Iterator__iter__Just go back to yourself.
35         :return:
36         """
37         return self
38 
39 
40 if __name__ == '__main__':
41     fib = FibIterator(10)
42     for num in fib:
43         print(num, end=" ")

In addition to for loops, list s, tuple s, and so on can receive iterative objects.

1. In addition to for loop, list, tuple and so on can receive iterative objects.
2 
3 li = list(FibIterator(15))
4 print(li)
5 tp = tuple(FibIterator(6))
6 print(tp)

 

Topics: Python