SoFunction
Updated on 2024-10-30

Python Understanding Iterators and Generators through for Loops Example Details

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 thenext() 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's

2.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 numwhich in turn is assigned to temp

I hope the description of this article will help you in Python programming.