python - generator

1. Generator object

  • Definition: a generator is actually a special iterator, which can be called a user-defined iterator. The definition stage is an ordinary function. The function is turned into a generator only when it is called. When calling a function for the first time, the function body code will not be executed, but only conversion.
  • Keyword: yield
  • As long as there is a yield keyword in the function, it is a generator!

Examples are as follows:

# def my_range(start,stop = None,step=1):
#     if stop ==None:
#         stop,start = start,0
#         # start = 0
#     while start<stop:
#         yield start
#         start+=step
# # Convert function names into iterators with parentheses
# for i in my_range(0,10,2):
#     print(i)




# for i in range(1,10):
#     print(i)

# Generator yield
# Define stage as normal function
def build():
    print('First call')
    yield 'stay yield You can also write the return value later!'
    print('Second call')
    yield 'stay yield You can also write the return value later!'



# The calling function does not execute code, but is transformed into a generator
build()
# Receive by traversing res
res = build()
# Output through the next() function. Note that calling the next() function matches the number of lines of code
ret = res.__next__()
# There is only one print statement, and an error is reported when calling next()
# ret = res.__next__()
# Printing ret is to get the return value of yield
print(ret)
'''Every call next()Function, the code will automatically stop at yield,And return the following values. Calling again will follow the last execution'''
res.__next__()

Exercise: customizing the range function

Implement the function of 1:1 restore range() and use the generator object

First, recall the range function structure, range (start, stop, step)

Examples are as follows:

# for loop traversal implementation 1-10
for i in range(1,10):
    print(i)
    
# Custom range() function
# Write parameters according to range
def my_range(start,stop = None,step=1):
    # If only one value is entered, the end value is the starting value
    if stop == None:
        stop,start = start,0
        # Traversal output
    while start<stop:
        yield start
        # Realize step function
        start+=step
# Convert function names into iterators with parentheses
for i in my_range(0,10,2):
    print(i)
    
'''The result is the same!'''

yield value

Using the send() function, you can avoid multiple writes after yield

def doing(name):
    print(f'{name}Get up!')
    while True:
        some_wh = yield
        print(f'{name}go{some_wh}')
# The first call is converted to a generator without executing the code
res = doing('HammerZe')
res.__next__()
# Pass value with send()
res.send('Beijing')
res.send('Shanghai')
res.send('Guangzhou')

# result
# HammerZe, get up!
# HammerZe to Beijing
# HammerZe to Shanghai
# HammerZe to Guangzhou

Through the above examples, we can find that the function of yield is very similar to that of return. The similarities and differences between yield and return are as follows:

  • Similarities:

    • Can return one or more values (when multiple values are organized into meta groups)
  • difference:

    • When the function encounters yield, it will not end, but "stop". The next call will be executed. return directly ends the function!
    • yield can turn the function into a generator, support value passing, and use the send() function

2. Generator expression

How do I create a generator?

  • As mentioned in the previous article of list generation, the generator here only needs to change the brackets of list generation into parentheses.

How do I get the elements of the generator? There are two ways

  • for loop / list traversal

  • The next () function iterates through it in turn

Examples are as follows:

# Create a list generator
l = [i for i in range(10)]
print(l)
# Convert to generator
l1 = (i for i in range(10))
# The generator can only be executed through traversal. The following are the three methods of traversal
for j in l1:  # Or list(l1)
    print(j)
l2 = (i for i in range(10))
print(l2.__next__())
print(l2.__next__())
print(l2.__next__())

# result
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

0
1
2
3
4
5
6
7
8
9

0
1
2

Both the generator object and the iterator object use the next () function once to print a sentence. The advantage of the generator is that it can calculate and cycle at the same time. The use of the generator saves space!

Exercise: output res results (PIT)

Examples are as follows:

# Sum
def add(n, i):
    return n + i
# The call is preceded by a function call and followed by a generator
def test():
    for i in range(4):
        yield i
g = test()  # Initialize generator object
for n in [1, 10]:   # Pit!!!
    g = (add(n, i) for i in g)

"""
for the first time for loop
    g = (add(n, i) for i in g)
The second time for loop
    g = (add(10, i) for i in (add(10, i) for i in g))
"""
# Here, g takes n from the last traversal and passes it in for calculation, n = 10
res = list(g)
print(res)

#result
[20, 21, 22, 23]

Let's guess the result of res. it is not allowed to execute. Don't peek at the result (pretend not to see it). The options are as follows:

A. res=[10,11,12,13] B. res=[11,12,13,14]
C. res=[20,21,22,23] D. res=[21,22,23,24]

If there are any errors, please correct them. Thank you. They are constantly updated·····

Tags: Python

Posted on Mon, 22 Nov 2021 20:30:32 -0500 by wacook