連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)

關注 「極客起源」 公眾號,獲得更多免費技術影片和文章。