目录
生成器函数是包含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