python - iterator and generator in coprocess

Keywords: Programming Python

1. Iterator Understanding

Iterator:

  • Iterators are tools for accessing iteratable objects

  • Iterator is the object (instance) returned by iter(obj) function.

  • Iterator refers to the use of next(it) function to obtain data of iteratable objects.

Iterator functions (iter and next)

  • iter(iterable) returns an iterator from an Iterable object. Iterable must be an object that provides an iterator

  • next(iterator) retrieves the next record from iterator and triggers the stoptrerator exception if the next record cannot be retrieved

Explain:
1. Iterators can only take values forward, not backward.
2. Iterator function can be used to return an iterator of an iteratable object

2. Application of Iterator

class Fabonacci(object):
    def __init__(self,all_num):
        self.all_num = all_num
        self.current_num = 0
        self.a = 0
        self.b = 1


    def __iter__(self):
        return self


    def __next__(self):
        if self.current_num < self.all_num:
            ret = self.a

            self.a, self.b = self.b, self.a + self.b
            self.current_num += 1

            return ret
        else:
            raise StopIteration


fibo = Fabonacci(10)
for num in fibo:
    print(num)

3. Understanding of Generators

generator

  • It is a simple way to construct new iterative objects. The general function return only returns a single value, while the generator does not directly put the iteratable value into memory, but returns a sequence of values in a delayed manner, i.e., pauses after each value is returned until the next value is requested, which can effectively save memory consumption.

  • To build a generator, you need to use the keyword yield. The function of yield is somewhat similar to the return value of a function. By replacing return with yield in a function, you can turn a function into a generator.
    The function of yield is no longer a normal function, python
    The interpreter regards the function object as the generator object, and the generator returns the iterative sequence of values generated by the yield expression. The iterative sequence of values returned by the generator can be read sequentially by means of for loop and other methods.

  • The iteratable value generated by the generator can only be read once. Each iteration returns the value when the generator code flow meets the yield expression and records the position. The next iteration stops until the next iteration. The starting position of the execution code is from the last record position until the end of the whole generator code operation. Bundle.

4. Application of Generator

1)

def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        # print(a)
        yield a
        a, b = b, a+b
        current_num += 1


obj = create_num(10)
while True:
    try:
        ret = next(obj)
        print(ret)
    except Exception as ret:
        break


2) Start the generator by send
send is not typically placed in the first boot generator. If you have to do so, pass None.
Error demonstration:

def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        ret = yield a
        print(">>>ret>>>", ret)
        a, b = b, a+b
        current_num += 1


obj = create_num(10)

ret = obj.send("hello") #The first one calls the send method
print(ret)

ret = next(obj)
print(ret)

Demonstrate correctly:

def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        ret = yield a
        print(">>>ret>>>", ret)
        a, b = b, a+b
        current_num += 1


obj = create_num(10)

ret = next(obj)
print(ret)

ret = obj.send("hello")
print(ret)

def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        ret = yield a
        print(">>>ret>>>", ret)
        a, b = b, a+b
        current_num += 1


obj = create_num(10)

ret = obj.send(None)
print(ret)

ret = next(obj)
print(ret)


3. Use Generator to Complete Multitasks (Concurrent)

import time


def task_1():
    while True:
        print("----1----")
        time.sleep(0.1)
        yield


def task_2():
    while True:
        print("----2----")
        time.sleep(1)
        yield


def main():
    t1 = task_1()
    t2 = task_2()
    while True:
        next(t1)
        next(t2)


if __name__ == '__main__':
    main()

4).gevent uses generators

Import genvent Library

import gevent
import time


def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)


def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)


def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)


print("----1----")
g1 = gevent.spawn(f1,5)
print("----2----")
g2 = gevent.spawn(f2,5)
print("----3----")
g3 = gevent.spawn(f3,5)
g1.join()
g2.join()
g3.join()


Simple way to modify time.sleep () to gevent.sleep (): (patching)
Just import monkey and write a code monkey.patch_all()
At runtime, it will be replaced automatically

import gevent
import time
from gevent import monkey

monkey.patch_all()

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


print("----1----")
g1 = gevent.spawn(f1,5)
print("----2----")
g2 = gevent.spawn(f2,5)
print("----3----")
g3 = gevent.spawn(f3,5)
g1.join()
g2.join()
g3.join()


There is no need to add join s one by one when creating multiple gevent s

import gevent
import time
from gevent import monkey

monkey.patch_all()

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)


gevent.joinall([
    gevent.spawn(f1,5),
    gevent.spawn(f2,5),
    gevent.spawn(f3,5)])

Posted by Gugel on Sun, 28 Jul 2019 03:20:37 -0700