连Python产生器(Generator)的原理都解释不了,还敢说Python用了5年?

mylist = [1, 2, 3] for i in mylist: print(i, end = ' ')
mylist = [x*x for x in range(3)] for i in mylist: print(i, end=' ')
# 创建产生器 data_generator = (x*x for x in range(3)) print(data_generator) for i in data_generator: print(i, end=' ') print() print('第二次迭代data_generator,什么都不会输出') print() for i in data_generator: print(i, end=' ')

<generator object <genexpr> at 0x7f95e0154150> 0 1 4 第二次迭代data_generator,什么都不会输出
# 编写产生器函数 def generate_even(max): for i in range(0, max + 1): if i % 2 == 0: yield i print(generate_even(10)) even_generator = generate_even(10) for n in even_generator: print(n, end=' ')
<generator object generate_even at 0x7f814826c450>
0 2 4 6 8 10
even_generator = generate_even(10) print(even_generator.__next__()) print(even_generator.__next__()) print(even_generator.__next__()) print(even_generator.__next__()) print(even_generator.__next__()) print(even_generator.__next__()) # print(even_generator.__next__()) # 抛出StopIteration异常
总结:产生器本质上就是动态产生待迭代的值,使用完就直接扔掉了,这样非常节省内存空间,但这些值只能被迭代一次。
result = []
result.append(expr)
# 产生不大于max的偶数 def generate_even(max): for i in range(0, max + 1): if i % 2 == 0: yield i even_generator = generate_even(10) for n in even_generator: print(n, end=' ') # 将产生器函数改造成普通函数,实际上,就是将yield后面表达式的值都添加在列表中 def generate_even1(max): evens = [] for i in range(0, max + 1): if i % 2 == 0: evens.append(i) return evens print() even_list = generate_even1(10) for n in even_list: print(n, end=' ')
在这段代码中有两个函数:generate_even和generate_even1,其中generate_even是产生器函数,generate_even1是普通函数(与generate_even函数的功能完全相同)。按着前面的步骤,将所有产生的偶数都添加到了列表变量evens中,最后返回这个列表变量。这两个函数在使用方式上完全相同。不过从本质上说,generate_even函数是动态生成的偶数,用完了就扔,而generate_even1函数事先将所有产生的偶数都添加到列表中,最后返回。所以从generate_even1函数的改造过程来看,yield的作用就相当于使用append方法将表达式的值添加到列表中,只不过yield并不会保存表达式的值,而append方法会保存表达式的值。
from itertools import * # 这里每一个yield的值必须是可迭代的,才能用chain.from_iterable方法合并 def make_iterables_to_chain(): yield [1,2,3] yield ['a','b','c'] yield ['hello','world'] for v in make_iterables_to_chain(): print(v) # 将所有可迭代对象合并成一个可迭代对象 for v in chain.from_iterable(make_iterables_to_chain()): print('<',v,'>', end = ' ') print('-------上面的代码相当于下面的写法-------') a = [1,2,3] a.extend(['a','b','c']) a.extend(['hello','world']) print(a) for v in a: print('[',v,']', end = ' ') # 以可迭代对象形式返回列表的全排列 values = [1,2,3,4] values_permutations = permutations(values) for p in values_permutations: print(p)
[1, 2, 3] ['a', 'b', 'c'] ['hello', 'world'] < 1 > < 2 > < 3 > < a > < b > < c > < hello > < world > -------上面的代码相当于下面的写法------- [1, 2, 3, 'a', 'b', 'c', 'hello', 'world'] [ 1 ] [ 2 ] [ 3 ] [ a ] [ b ] [ c ] [ hello ] [ world ] (1, 2, 3, 4) (1, 2, 4, 3) (1, 3, 2, 4) (1, 3, 4, 2) (1, 4, 2, 3) (1, 4, 3, 2) (2, 1, 3, 4) (2, 1, 4, 3) (2, 3, 1, 4) (2, 3, 4, 1) (2, 4, 1, 3) (2, 4, 3, 1) (3, 1, 2, 4) (3, 1, 4, 2) (3, 2, 1, 4) (3, 2, 4, 1) (3, 4, 1, 2) (3, 4, 2, 1) (4, 1, 2, 3) (4, 1, 3, 2) (4, 2, 1, 3) (4, 2, 3, 1) (4, 3, 1, 2) (4, 3, 2, 1)

对本文感兴趣,可以加李宁老师微信公众号(unitymarvel)

关注 「极客起源」 公众号,获得更多免费技术视频和文章。