generator-expression生成器表达式
the differences between list comprehension and generator expression
def gen_AB():
    print("start")
    yield 'A'
    print("continue")
    yield 'B'
    print("end.")
res1 = [x*3 for x in gen_AB()]  执行结果为: 
 start 
 continue 
 end. 
说明列表推导式会析取yield返回的结果,并存储于列表中,其他的便不会存储到列表中。
for i in res1:
    print("-->",i)  执行结果为: 
 –> AAA 
 –> BBB 
但是,生成器表达式却不是这样的。
res2 = (x*3 for x in gen_AB())  这时,输入res2,会返回:
<generator object <genexpr> at 0x10063c20>    for i in res2:
    print("-->", i)  执行结果为: 
 start 
 –> AAA 
 continue 
 –> BBB 
 end. 
**only when the for loop iterates over res2, the body of gen_AB actually executes. 
 Each iteration of the for loop implicitly calls the next(res2), advancing gen_AB to the next yield. 
 Note the output of gen_AB with the output of the print in the for loop**
import re
import reprlib
RE_WORD = re.compile("\w+")
class Sentence(object):
    def __init__(self, text):
        self.text = text
    def __repr__(self):
        return "Sentence({})".format(reprlib.repr(self.text))
    def __iter__(self):
        return (match.group() for match in RE_WORD.finditer(self.text))  when to use generator expression?
if the generator expression spans more than a couple of lines, I prefer to code a generator function for the sake of readability.
Also, because generator function have a name, they can be reused.
You can always name a generator expression and use it later by assigning it to a variable, of course, but that is stretching its intended usage as a one-off generator.
Syntax Tip
when a generator expression is passed as the single argument to a function or constructor, you don’t need to 
 write a set of parentheses for the function call and another to enclose the generator expression. 
def __mul__(self, scalar):
    if isinstance(scalar, numbers.Real):
        return Vector(n*scalar for n in self)# the parentheses is omitted
    else:
        return NotImplemented  look at the generator expression power!
def gen_Arithmetic(start, step, end=None):
    start = type(start+step)(start)
    index = 0
    result = start
    foever = end is None
    while foever or result < end:
        yield result
        index += 1
        result = start + index*step  there is a standard library that can be used.
import itertools
gen = itertools.count(1, 0.5)  next(gen)   1
next(gen)   1.5
however, itertools.count never stops. 
 tertools.takewhile function : it produces a generator that consumer another generator and stop when a given 
 predicate evaluates to False. 
gen = itertools.takewhile(lambda n:n<3, itertools.count(1,0.5))  list(gen)   [1,1.5,2.0,2.5]
def gen_Arithmetic(start, step, end=None):
    start = type(start + step)(start)
    gen = itertools.count(start,step)
    if end is None:
        return gen
    return itertools.takewhile(lambda v:v<end, gen)  Note that gen_Arithmetic function is not a generator function; 
 it has no yield in its body. 
 But it returns a generator, so it operates as a generator factory, just as a generator function does. 

京公网安备 11010502036488号