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)])