Python PEP342

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/

posted @ 2017-04-04 23:41  autoria  阅读(213)  评论(0)    收藏  举报