Specification Summary
1. Redefine "yield" to be an expression, rather than a statement. The current yield statement would become a yield expression whose value is thrown away. A yield expression's value is None whenever the generator is resumed by a normal next() call.
除了作为一个statement将一个函数变成一个generator以外,yield可以被视为是一个表达式,并用于赋值。
比如
>>> def whizbang(): for i in range(10): x = yield i print 'got sent:', x >>> i = whizbang() >>> next(i) 0 >>> next(i) got sent: None 1 >>> i.send("hi") got sent: hi 2
2. Add a new send() method for generator-iterators, which resumes the generator and "sends" a value that becomes the result of the current yield-expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value.
见1,一个yield expression如果不通过send传入一个值,那么其值就默认是None
举例:
给出各基数下的最小的素数(比如给出iterations = 3, base = 10,就相当于分别求出大于10^1,10^2,10^3的最小的素数)
1 import math 2 def is_prime(number): 3 if number > 1: 4 if number == 2: 5 return True 6 elif number % 2 == 0: 7 return False 8 for current in range(3, int(math.sqrt(number) + 1), 2): 9 if number % current == 0: 10 return False 11 return True 12 return False 13 14 def print_successive_primes(iterations, base=10): 15 prime_generator = get_primes(base) 16 prime_generator.send(None) 17 for power in range(iterations): 18 print(prime_generator.send(base ** power)) 19 20 21 def get_primes(number): 22 while True: 23 if is_prime(number): 24 number = yield number 25 number += 1
可以看到我们在访问迭代器之前需要首先对迭代器get_primes的实例使用send,传入None,为什么呢?因为:
Because generator-iterators begin execution at the top of the generator's function body, there is no yield expression to receive a value when the generator has just been created. Therefore, calling send() with a non-None argument is prohibited when the generator iterator has just started, and a TypeError is raised if this occurs (presumably due to a logic error of some kind). Thus, before you can communicate with a coroutine you must first call next() or send(None) to advance its execution to the first yield expression.
send()会访问一个yield expression,而generator实例化之后并没有执行到yield expression,需要执行一个next()或者与其等价的send(None)来访问到yield expression
其余见https://www.python.org/dev/peps/pep-0342/