红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【CS61A】CS61A——Generators

Generators

Generator Functions

  • 生成器函数是用来生成(yields)值而非返回值的函数
  • 生成器函数使用yield关键字返回生成的值
  • 生成器可以多次生成值,而普通函数只能返回一次值
  • 生成器是调用生成器函数时自动创建的迭代器
  • 调用生成器函数,它会返回一个生成器来迭代该函数生成的值
  • 当函数执行到yield时,生成的值将会作为下次迭代器的数值,而此时执行在yield处执行,但会记住当前环境,以便下次继续执行 e.g.
1
2
3
4
5
6
7
8
9
10
def evens(start, end):
    even = start + (start%2)
    while even<end:
        yield even
        even+=2

if __name__ == "__main__":
    t = evens(2,10)
    for i in t:
        print(i)
2
4
6
8

Generators & Iterators

yield from语句 yield from语句允许从一个迭代器或可迭代变量中生成所有值 两个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def countdown(k):
    if k>0:
        yield k
        yield from countdown(k-1)
        '''
        等价于 
        for i in countdown(k-1):
            yield i
        '''
    else:
        yield 'Blast off'
if __name__ == "__main__":
    t = countdown(3)
    for i in t:
        print(i)
3
2
1
Blast of
1
2
3
4
5
6
7
8
9
10
11
def prefixes(s):
    if s:
        yield from prefixes(s[:-1])
        yield s
def substrings(s):
    if s:
        yield from prefixes(s)
        yield from substrings(s[1:])
if __name__ == "__main__":
    print(list(prefixes("both")))
    print(list(substrings("top")))
['b', 'bo', 'bot', 'both']
['t', 'to', 'top', 'o', 'op', 'p']

Example: Partitions

详见递归时的数字分割例子 使用列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
def partitions(n,m):
    if n<0 or m==0:
        return []
    else:
        exact_match = []
        if n==m:
            exact_match = [str(m)]
        with_m = [p+'+'+str(m) for p in partitions(n-m,m)]
        without_m = partitions(n,m-1)
        return exact_match+with_m+without_m
if __name__ == "__main__":
    for p in partitions(6,4):
        print(p)
2+4
1+1+4
3+3
1+2+3
1+1+1+3
2+2+2
1+1+2+2
1+1+1+1+2
1+1+1+1+1+1

使用生成器: 使代码更优雅,而且可以输出指定个数的可能结果

1
2
3
4
5
6
7
8
9
10
11
def partitions(n,m):
    if n>0 and m>0:
        if n==m:
            yield str(m)
        for p in partitions(n-m,m):
            yield p+'+'+str(m)
        yield from partitions(n,m-1)
if __name__ == "__main__":
    t = partitions(6,4)
    for p in range(5):
        print(next(t))
2+4
1+1+4
3+3
1+2+3
1+1+1+3