目录
生成器函数是包含yield语句的函数。在生成器函数中,不能包含带参的return语句。
调用生成器函数,会返回一个生成器对象。
第一次启动生成器的时候,需要使用None作为参数调用生成器的send()方法,或者调用生成器的next()方法(next()等价于send(None))。生成器会从头开始执行,一直到:
之后,可以使用send(<value>)或next()重新启动生成器,send的参数会作为上个yield语句的返回值,然后生成器会从上次yield的位置,继续执行,一直到:
也可以通过生成器对象的throw(<exc_value>)方法,向生成器内部传递异常。
下面是一个用生成器,模拟生产者-消费者的例子:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py import time class MainLoop: def __init__(self): self._gens = [] self._is_stop = False def add_gen(self, gen_factory): if self._is_stop: return self._gens.append(gen_factory(self)) def delete_gen(self, gen): while self._gens.find(gen) != -1: self._gens.remove(gen) def _run(self): cursor = 0 while cursor < len(self._gens): try: self._gens[cursor].next() except Exception as ex: self._gens.pop(cursor) cursor = cursor - 1 if not isinstance(ex, StopIteration): print ex finally: cursor = cursor + 1 def start(self): while not self._is_stop: self._run() if not self._gens: time.sleep(0.001) while self._gens: self._run() def stop(self): self._is_stop = True current_count = 0 will_stop = False batch_count = 10 max_count = 100 def producer(loop): global current_count, max_count, batch_count, will_stop produced_count = 0 while produced_count < max_count: while current_count >= max_count / 2: print "[producer] threshold is reached..." yield print "[producer] begin producing" start_time = time.time() now = start_time while now - start_time < 0.2: yield now = time.time() current_count = current_count + batch_count produced_count = produced_count + batch_count print "[producer] produced %d/%d" % (produced_count, max_count) yield print "[producer] stop" will_stop = True loop.stop() def consumer(loop): global current_count, will_stop consumed_count = 0 while current_count > 0 or not will_stop: while current_count <= 0: print "[consumer] no goods, sleep 0.1" start_time = time.time() now = start_time while now - start_time < 1: yield now = time.time() current_count = current_count - 1 consumed_count = consumed_count + 1 print "[consumer] consumed %d/%d" % (consumed_count, max_count) yield print "[consumer] stop" loop = MainLoop() loop.add_gen(producer) loop.add_gen(consumer) loop.start() [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py [producer] begin producing [consumer] no goods, sleep 0.1 [producer] produced 10/100 [producer] begin producing [producer] produced 20/100 [producer] begin producing [producer] produced 30/100 [producer] begin producing [producer] produced 40/100 [producer] begin producing [consumer] consumed 1/100 [consumer] consumed 2/100 [consumer] consumed 3/100 [consumer] consumed 4/100 [consumer] consumed 5/100 [consumer] consumed 6/100 [consumer] consumed 7/100 [consumer] consumed 8/100 [consumer] consumed 9/100 [consumer] consumed 10/100 [consumer] consumed 11/100 [producer] produced 50/100 [consumer] consumed 12/100 [producer] begin producing [consumer] consumed 13/100 [consumer] consumed 14/100 [consumer] consumed 15/100 [consumer] consumed 16/100 [consumer] consumed 17/100 [consumer] consumed 18/100 [consumer] consumed 19/100 [consumer] consumed 20/100 [consumer] consumed 21/100 [consumer] consumed 22/100 [consumer] consumed 23/100 [consumer] consumed 24/100 [consumer] consumed 25/100 [consumer] consumed 26/100 [consumer] consumed 27/100 [consumer] consumed 28/100 [consumer] consumed 29/100 [consumer] consumed 30/100 [consumer] consumed 31/100 [consumer] consumed 32/100 [consumer] consumed 33/100 [consumer] consumed 34/100 [consumer] consumed 35/100 [consumer] consumed 36/100 [consumer] consumed 37/100 [consumer] consumed 38/100 [consumer] consumed 39/100 [consumer] consumed 40/100 [consumer] consumed 41/100 [consumer] consumed 42/100 [consumer] consumed 43/100 [consumer] consumed 44/100 [consumer] consumed 45/100 [consumer] consumed 46/100 [consumer] consumed 47/100 [consumer] consumed 48/100 [consumer] consumed 49/100 [consumer] consumed 50/100 [consumer] no goods, sleep 0.1 [producer] produced 60/100 [producer] begin producing [producer] produced 70/100 [producer] begin producing [producer] produced 80/100 [producer] begin producing [producer] produced 90/100 [producer] begin producing [producer] produced 100/100 [producer] stop [consumer] consumed 51/100 [consumer] consumed 52/100 [consumer] consumed 53/100 [consumer] consumed 54/100 [consumer] consumed 55/100 [consumer] consumed 56/100 [consumer] consumed 57/100 [consumer] consumed 58/100 [consumer] consumed 59/100 [consumer] consumed 60/100 [consumer] consumed 61/100 [consumer] consumed 62/100 [consumer] consumed 63/100 [consumer] consumed 64/100 [consumer] consumed 65/100 [consumer] consumed 66/100 [consumer] consumed 67/100 [consumer] consumed 68/100 [consumer] consumed 69/100 [consumer] consumed 70/100 [consumer] consumed 71/100 [consumer] consumed 72/100 [consumer] consumed 73/100 [consumer] consumed 74/100 [consumer] consumed 75/100 [consumer] consumed 76/100 [consumer] consumed 77/100 [consumer] consumed 78/100 [consumer] consumed 79/100 [consumer] consumed 80/100 [consumer] consumed 81/100 [consumer] consumed 82/100 [consumer] consumed 83/100 [consumer] consumed 84/100 [consumer] consumed 85/100 [consumer] consumed 86/100 [consumer] consumed 87/100 [consumer] consumed 88/100 [consumer] consumed 89/100 [consumer] consumed 90/100 [consumer] consumed 91/100 [consumer] consumed 92/100 [consumer] consumed 93/100 [consumer] consumed 94/100 [consumer] consumed 95/100 [consumer] consumed 96/100 [consumer] consumed 97/100 [consumer] consumed 98/100 [consumer] consumed 99/100 [consumer] consumed 100/100 [consumer] stop