Advanced function -- yield keyword and generator

Export: comparison between iterative values and index values

Iterative values provide a new way that does not depend on index values.

  • Iteration value:

    1. It does not depend on the index value and can be accessed by calling__ next__ () method value.
    2. Values cannot be repeated. You can only take values one by one from left to right. To get the same value, you can only reinitialize the iterator object and call__ next__ () method.
  • Index value:

    1. The value object must be a container type, such as list, tuple, etc
    2. You can take values repeatedly, that is, a value can be taken multiple times at any time.

Generator and yield keyword

A generator is a custom iterator, essentially an iterator. If the function body contains the yield keyword, the function will not execute the function body code when called, and the returned result is a generator object. Built in generator__ iter__ () methods and__ next__ () method, called through the generator object__ next__ () method, which will trigger the execution of the function body code.

The yield keyword can be used to return a value, but unlike the return keyword, the function ends directly when it encounters a return, while the yield keyword can keep the function running and "pause" the function to return multiple values.

Code demonstration:

def index():
    print('from index')
    yield
    
index()
print(index())
index().__next__()
print(index().__next__())

Execution results:

Conclusion: the function body contains the yield keyword, the code is not executed when calling, and the returned result is the generator object; Generator object call__ next__ () method, execute the function body and return the value after yield. If it is not written, it returns None by default.

def index():
    print('from index')
    yield 123,234,345
    
res = index()
print(res.__next__())
# print(next(res))  # Consistent with the code in the previous sentence

Execution results:

Summary: you can return values after yield, and you can return multiple values at the same time, in the form of tuples.

def index():
    print('for the first time next')
    yield 123,234,345
    print('The second time next')
    yield 'aaaa'
    print('third time next')
    yield 'xxxx'

res=index()  # Once it's a generator, you can__ next__ Value
print(res.__next__())
print(res.__next__())
print(res.__next__()) 
print(next(res))  # StopIteration

Summary: the generator object is called once__ next__ () method, walk a yield, and the cursor will stop at the yield. If you call again__ next__ (), it will continue to go down from the yield position of the last stop. If there is, it will execute. If not, it will throw an exception.

Note: after the yield keyword is in the function, it is still a function before the function call. Once the call function becomes a generator

Generator application example: the generator implements the range function

  • range function:

    1. Function 1:
    range(10)  # Numbers 0-9
    2. Function 2:
    range(3,10)  # Figures 3-9
    3. Function 3:
    range(1, 10, 2) # 1,3,5,7,9
    
  • Use the generator to realize the range function:

    def my_range(start, end=None, step=1):
        if not end:
            end = start
            start = 0
    
        while start < end:
            yield start
            start += step
    
    # res = my_range(2, 10, 2)
    res = my_range(10)
    
    for i in res:
        print(i)
    

yield value

With the yield keyword, you can get the function's generator object to continue to be the send value of the function body.

Example:

def index(name):
    print('%s Get ready for dinner' % name)
    while True:
        food = yield
        print('%s Open dry %s' % (name, food))

res=index('handsome young man')
res.__next__()
res.__next__()

res.send('Grilled rice')
res.send('Rice')

Execution results:

Comparison between yield and return

  • yield:

    1. When the yield keyword is encountered in the function, the function is turned into a generator when called
    2. yield can also return a value, and supports multiple (tuple form) returns
    3. When yield is encountered, the function will not end, but "pause"
    4. yield also supports value passing (using the send method)
  • return:

    1. Return can be followed by a return value, or multiple returns (in tuple form) are supported
    2. If the function encounters return, it will end immediately

Generator Expressions

We derive the generation expression from the list generation expression, as shown in the following code:

  • List generating formula:

    l = [1,2,3,4]
    new_l = [i + 1 for i in l]
    print(new_l)
    

    Execution result: [2, 3, 4, 5]

    Summary: the return value of the list generator is the list

  • Generator expression:

    l = [1,2,3,4]
    new_l = (i + 1 for i in l)
    print(new_l)
    print(next(new_l))
    

    Execution results:

    Summary: the generator expression returns a generator object. To get the value, it needs to be generated through next(). The generator expression is similar to a "factory". When there is a demand, the "factory" will process "products" for you.

Generator written test questions

Title: write the execution results of the following procedures.

def add(n, i):
    return n + i

def test():
    for i in range(4):
        yield i

g = test() 
for n in [1, 10]:
    g = (add(n, i) for i in g)
    
res = list(g)
print(res)

Implementation results: [20, 21, 22, 23]

Process analysis:

# 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]:
    g = (add(n, i) for i in g)
    '''
        First cycle:
            g = (add(1, i) for i in g)
        Second cycle:
            g = (add(10, i) for i in (add(10, i) for i in g))
    '''
res = list(g)
print(res)

Common built-in function supplement

abs(): find the absolute value.

print(abs(123))
print(abs(-123))

# Execution result: 123

all(): returns True only if all the elements in the list are True; otherwise, returns False.

l1 = [1,2,3,4,5,6]
l2 = [1,2,3,0]
print(all(l1))
print(all(l2))

# Execution result: true or false

any(): returns True as long as one of the elements in the list is True.

l1 = [1,2,3,4,5,6]
l2 = [1,2,3,0]
l3 = [0, None,[]]
print(any(l1))
print(any(l2))
print(any(l3))

# Execution result: true 		 True 	 False

sum(): sum. Note that the incoming object must be an iteratable object.

l = [1,2,3,4,5,6]
print(sum(l))

# Implementation result: 21

divmod(): divide remainder. The first parameter is the divisor, the second parameter is the divisor, and the return result is (quotient, remainder).

print(divmod(100,10))
print(divmod(101,10))
print(divmod(99,10))

# Execution result: (10, 0) 	 (10, 1) 	 (9, 9)

Application: Design of pager.

eval(), exec(): execute the code in the string. Note that the code in the string cannot be indented, otherwise an error will be reported.

string1 = """
print("hello world")
"""

eval(string1)
eval(string1)

# Execution results:
hello world
hello world

isinstance(): judge whether a data is an instance.

s = "hello world"
print(isinstance(s, int))
print(isinstance(s, str))

# Execution results:
False
True

chr(): pass in decimal number and return ASCII characters corresponding to decimal number.

print(chr(65))

# Execution results:
A

ord(): pass in ASCII characters and return the corresponding decimal digits.

print(ord('A'))

# Execution results:
65

pow(): parameter 1 is the base, parameter 2 is the power, and the result is returned.

print(pow(2,3))
print(pow(3,3))

# Execution results:
8
27

round(): rounded to an integer after the decimal point.

print(round(4.3))
print(round(4.5))
print(round(4.8))

# Execution results:
4
4
5

bytes(): convert to binary.

s = 'hello world'
print(bytes(s, 'utf8'))

# Execution results:
b'hello world'

Keywords: Python

Added by limitedreality on Thu, 13 Jan 2022 16:00:57 +0200