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