1期丰、列表生成式
舉個(gè)例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11)):
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循環(huán):
>>> L = []
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
但是循環(huán)太繁瑣钝荡,而列表生成式則可以用一行語句代替循環(huán)生成上面的list:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
for循環(huán)后面還可以加上if判斷街立,這樣我們就可以篩選出僅偶數(shù)的平方:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
還可以使用兩層循環(huán),可以生成全排列:
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
2埠通、迭代器
迭代器是訪問集合元素的一種方式赎离。迭代器對象從集合的第一個(gè)元素開始訪問,直到所有的元素被訪問完結(jié)束端辱。迭代器只能往前不會后退梁剔,不過這也沒什么,因?yàn)槿藗兒苌僭诘局型笸寺邮帧A硗夂镀樱鞯囊淮髢?yōu)點(diǎn)是不要求事先準(zhǔn)備好整個(gè)迭代過程中所有的元素。迭代器僅僅在迭代到某個(gè)元素時(shí)才計(jì)算該元素喷鸽,而在這之前或之后众雷,元素可以不存在或者被銷毀。這個(gè)特點(diǎn)使得它特別適合用于遍歷一些巨大的或是無限的集合做祝,比如幾個(gè)G的文件
特點(diǎn):
1. 訪問者不需要關(guān)心迭代器內(nèi)部的結(jié)構(gòu)砾省,僅需通過next()方法不斷去取下一個(gè)內(nèi)容
2. 不能隨機(jī)訪問集合中的某個(gè)值 ,只能從頭到尾依次訪問
3. 訪問到一半時(shí)不能往回退
4. 便于循環(huán)比較大的數(shù)據(jù)集合混槐,節(jié)省內(nèi)存
>>> a = iter([1,2,3,4,5])
>>> a
<list_iterator object at 0x101402630>
>>> a.__next__()
1
>>> a.__next__()
2
>>> a.__next__()
3
>>> a.__next__()
4
>>> a.__next__()
5
>>> a.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
3编兄、 生成器
(1)
一個(gè)函數(shù)調(diào)用時(shí)返回一個(gè)迭代器,那這個(gè)函數(shù)就叫做生成器(generator)声登;如果函數(shù)中包含yield語法狠鸳,那這個(gè)函數(shù)就會變成生成器;
def fun ():
yield 1
yield 2
yield 3
yield 4
上述代碼中:func是函數(shù)稱為生成器悯嗓,當(dāng)執(zhí)行此函數(shù)func()時(shí)會得到一個(gè)迭代器件舵。
>>> fun
<function fun at 0x000001B3528A7158>
>>> fun()
<generator object fun at 0x000001B3528A56D0>
>>> temp = fun()
>>> temp.__next__()
1
>>>
KeyboardInterrupt
>>> temp.__next__()
2
>>> temp.__next__()
3
>>> temp.__next__()
4
>>> temp.__next__()
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
temp.__next__()
StopIteration
(2)
要?jiǎng)?chuàng)建一個(gè)generator,有很多種方法脯厨。第一種方法很簡單铅祸,只要把一個(gè)列表生成式的[]改成(),就創(chuàng)建了一個(gè)generator:
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
創(chuàng)建L和g的區(qū)別僅在于最外層的[]和()合武,L是一個(gè)list临梗,而g是一個(gè)generator。
我們可以直接打印出list的每一個(gè)元素稼跳,但我們怎么打印出generator的每一個(gè)元素呢盟庞?
如果要一個(gè)一個(gè)打印出來,可以通過next()函數(shù)獲得generator的下一個(gè)返回值:
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
我們講過汤善,generator保存的是算法茫经,每次調(diào)用next(g)巷波,就計(jì)算出g的下一個(gè)元素的值,直到計(jì)算到最后一個(gè)元素卸伞,沒有更多的元素時(shí)抹镊,拋出StopIteration的錯(cuò)誤。
當(dāng)然荤傲,上面這種不斷調(diào)用next(g)實(shí)在是太變態(tài)了垮耳,正確的方法是使用for循環(huán),因?yàn)間enerator也是可迭代對象:
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
...
0
1
4
9
16
25
36
49
64
81
所以遂黍,我們創(chuàng)建了一個(gè)generator后终佛,基本上永遠(yuǎn)不會調(diào)用next(),而是通過for循環(huán)來迭代它雾家,并且不需要關(guān)心StopIteration的錯(cuò)誤铃彰。
編寫斐波拉契數(shù)列:
。芯咧。牙捉。
4、實(shí)例
a敬飒、利用生成器自定義range
def nrange(num):
temp = -1
while True:
temp = temp + 1
if temp >= num:
return
else:
yield temp
b邪铲、利用迭代器訪問range
...