This article is an example of Python understanding iterators and generators through for loops. Shared for your reference, as follows:
iterator (math.)
iterable object (computing)
pass (a bill or inspection etc)for…in… The process of looping through to get the data in order to use it is called traversal, also called iteration. We take the data that can be passed through thefor…in… Objects whose statements iteratively read data are called iterable objects.
- pass (a bill or inspection etc)
isinstance()
You can determine whether an object can be iterated
# Judgment list print(isinstance([], Iterable)
Printing a True result means that the object is iterable.
- Customize a class that can hold data and test the class for iterability
import collections class MyClassmate(object): def __init__(self): = [] def add(self, name): (name) # Create MyClassmate objects my_classmate = MyClassmate() my_classmate.add("Little King.") my_classmate.add("Little Lee.") my_classmate.add("Little Zhang.") # Determine if MyClassmate is an iterable object print("Whether it is an iterable object:",isinstance(my_classmate, )) # Iterate the data for temp in my_classmate: print(temp)
Running results:
Whether the object is iterable or not: False
Traceback (most recent call last):
for temp in my_classmate:
TypeError: 'MyClassmate' object is not iterable
Encapsulating a type that can hold multiple pieces of data is not iterative
What is an iterable object
- When we analyze the process of iterating over an iterable object, we find that every iteration (i.e., every loop in the for...in...) returns the next piece of data in the object, and continues to read back until all the data has been iterated over. So, there should be a "person" in the process to keep track of what data was accessed each time, so that each iteration can return the next piece of data. We call this "person" who helps us iterate over the data an Iterator.
- The essence of an iterable object is to provide an intermediate "person", an iterator, to help us iteratively traverse its use.
- Iterable objects are passed through the
__iter__
method provides us with an iterator, and when iterating over an iterable object, you actually get an iterator over the object first, and then use that iterator to get each piece of data in the object in turn.
1. The essence of an iterable object is to provide such an intermediate "person" that is, an iterator to help us iterate through it using the
2. An iterable object is an object with a
__iter__
method of the object through the__iter__
method to get the iterator for an iterable object
from collections import Iterable class MyClassmate(object): def __init__(self): = [] def add(self, name): (item) def __iter__(self): """Empty implementation of the method""" return None # Create MyClassmate objects my_classmate = MyClassmate() my_classmate.add("Little King.") my_classmate.add("Little Lee.") my_classmate.add("Little Zhang.") # Determine if MyClassmate is an iterable object print(isinstance(my_classmate, Iterable))
Run results:
If or not the object is iterable: True
This time the test revealed the addition of__iter__
method's my_classmate object is already an iterable object.
The iter() and next() Functions
Lists, tuples, etc. are all iterable objects, and we can get iterators for them with the iter() function. Then, we can keep using the
next()
function to get the next piece of data.
li = [11, 22, 33, 44, 55] # Get the iterator of an iterable object via iter() iterator = iter(li) # Get the next value pointed to by the iterator with the next() function. print(next(iterator)) print(next(iterator)) print(next(iterator)) print(next(iterator)) print(next(iterator)) print(next(iterator))
1.
iter(iterable)
function is taking the iterator out of the iterable object, and internally it is calling the iterable object's__iter__
method to get the iterator's2.
next(iterator)
function is to get the value of the next position through the iterator, internally it is a call to the iterator object's__next__
method to get the value of the next position
Caution.After we've iterated over the last piece of data, calling again thenext()
function throws a StopIteration exception to tell us that all the data has been iterated over and we don't need to execute thenext()
function now.
iterator (math.)
To construct an iterator, we have to implement its
__next__
method. But that's not enough, python requires that the iterator itself be iterative, so we also have to implement the__iter__
method, and the__iter__
method to return an iterator, the iterator itself is exactly that, an iterator, so the iterator's__iter__
method to return itself is sufficient.A realization of the
__iter__
methodology and__next__
The object of a method is an iterator, which is also an iterable object.
import collections class MyClassmate(object): def __init__(self): # Declare a list = [] # Record the iterator's iteration position, default is 0, i.e., from the beginning. = 0 def add(self, name): (name) def __iter__(self): """Obtain the iterator object through this method.""" return self def __next__(self): """Get the value of the next iteration.""" if < len(): name = [] += 1 return name else: raise StopIteration # Create an instance of MyClassmate my_classmate = MyClassmate() my_classmate.add("Little King.") my_classmate.add("Little Lee.") my_classmate.add("Little Zhang.") # Test if MyList is an iterable object print(isinstance(my_classmate, )) # Traverse the data for name in my_classmate: print(name)
for...in... the essence of a loop
The essence of the for item in Iterable loop is that it is first passed through theiter()
function gets an iterator over the Iterable, and then keeps calling next() on the obtained iterator to get the next value and assign it to item, ending the loop when a StopIteration exception is encountered (for..in. automatically handles StopIteration exceptions).
generator
generator
Generators are a special kind of iterator that are more elegant than iterators.
Methods for creating generators
1. Replace [] with () for list generator
# Reference list generator L=[x*2 for x in range(6)] print(L) # Change [] to () :is a simple list generator G=(x*2 for x in range(6)) # The output is a generator object print(G) print("pass (a bill or inspection etc)next()function to get the next value") print(next(G)) print(next(G)) print(next(G)) print(next(G)) print(next(G)) print(next(G)) # Create a simple generator that iterates through for G=(x*2 for x in range(6)) print("Result of iteration by for:") for num in G: print(num)
Running results:
[0, 2, 4, 6, 8, 10]
<generator object <genexpr> at 0x7ff7f8bbd5c8>
Getting the next value with the next() function
0
2
4
6
8
10
Result of iteration by for.
0
2
4
6
8
10
2. Keyword yield to realize the generator
def fib(n): current_index = 0 num1, num2 = 0, 1 while current_index < n: # print(num1) # Print the Fibonacci series """ 1. If the function hasyield,then it is no longer a function,Instead, it's a generator. 2. yield A breakpoint will be generated 3. providedyieldFollowed immediately by a data,It will then return the data to the, act asnext()function or thefor ...in...Iterate out the next value """ yield num1 num1, num2 = num2, num1 + num2 current_index += 1 if __name__ == '__main__': # If a function has a yield, it's no longer a function, it's a generator. gen = fib(5) # The generator is a special kind of iterator for num in gen: print(num) # You can also use the next() function to take the next value
In the way it is implemented using generators, we take what was originally in the iterator__next__
The basic logic implemented in the method is put into a function to realize, but the printout is changed to yield, then the newly defined function is no longer a function, but a generator. In short: any function that has the yield keyword in it is called a generator.
In this case, the function is called in the same way as it was called (casegen = fib(5)
) Instead of executing the function body, using a generator returns a generator object (gen in the case), which can then be used in the same way as an iterator.
utilizationsend()
awakens
def gen(): i = 0 while i < 5: temp = yield i print(temp) i += 1 if __name__ == '__main__': # Get the generator object obj = gen() # Use next() to wake up the generator print(next(obj)) print(next(obj)) # Use the send wakeup generator to pass additional data to the breakpoint on wakeup. print(("haha")) # Use next() to wake up the generator print(next(obj)) # Use the send wakeup generator to pass additional data to the breakpoint on wakeup. print(("python"))
Results.
0
None
1
haha
2
None
3
python
In addition to using the next() function to wake up the generator to continue execution, we can also use the send() function to wake up execution. One advantage of using the send() function is that you can pass additional data to the breakpoint while waking up.
summarize
1. If a function has a yield, it is no longer a function, but a generator.
2. yield generates a breakpoint, suspends the function, and saves state.
3. If the field is immediately followed by a piece of data, the data is returned as anext()
function or thefor …in… Iterate out the next value
4. This can be done bynext()
Wake up the generator to allow the generator to continue execution from a breakpoint
SEND is different from NEXT wake-up generator:
1. send and next can both wake up the generator, but send(value) can pass a value to the generator's breakpoints.
2. Use:
next(generator) ("Hello.")
3. (None)
equivalencenext(generator)
4. Note: When waking up the generator for the first time, if you use send, you can only pass None, because there is no breakpoint when the generator is first executed.
- analyze
temp = yield num ("Hello.")
temp = yield num When you see the equal sign, the left side of the equal sign must be run first, and then the right side of the equal sign is assigned.
And when the program runs to yield num, it will first return a value, which is num at this point, and then set thesend()
The parameters in theyield num
which in turn is assigned to temp
I hope the description of this article will help you in Python programming.