[notes]chap14 Iterator Generator-expression 生成器表达式

来源:互联网 发布:农业普查数据 编辑:程序博客网 时间:2024/06/05 00:10

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 reimport reprlibRE_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 itertoolsgen = 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.

0 0
原创粉丝点击