电竞比分网-中国电竞赛事及体育赛事平台

分享

Python迭代和生成操作小結(jié)

 quasiceo 2017-08-13

最近在使用Python進(jìn)行數(shù)據(jù)處理的過(guò)程中,使用for循環(huán)來(lái)進(jìn)行迭代處理的次數(shù)比較多,于是萌發(fā)了要寫一篇文章來(lái)總結(jié)python中迭代和生成操作,一方面加深對(duì)Python中這塊知識(shí)的理解,另一方面也鍛煉自己寫技術(shù)類博文的能力,這篇文章算是一次嘗試吧。

迭代

迭代的概念

維基百科中 迭代(Iteration) 的一個(gè)通用概念是:重復(fù)某個(gè)過(guò)程的行為,這個(gè)過(guò)程中的每次重復(fù)稱為一次迭代。具體對(duì)應(yīng)到Python編程中就是,對(duì)于一個(gè)可迭代對(duì)象,比如Python中的list、tuple、string、dictionary,set等,使用某種循環(huán)結(jié)構(gòu)來(lái)遍歷其中的元素,這種遍歷就是迭代。

迭代的形式

while

python編程中可以使用while循環(huán)進(jìn)行迭代。

i = 0
total = 0
while i < 100:
     total = total + i
     i = i + 1
print(total)

for

在Python編程中,利用for循環(huán)進(jìn)行迭代是比較常見的一種形式。Python使用for...in...的語(yǔ)法結(jié)構(gòu)。這點(diǎn)和C、Java等語(yǔ)言利用下標(biāo)進(jìn)行迭代有點(diǎn)不一樣。下面給出幾個(gè)例子。

for i in range(2):
    print(i)
# output
0
1
for s in "Max":
    print(s)
# output
M
a
x
for key in {"Python":90, "java"88, "C++":85}:
    print(key)
# output
Python
java
C++

除了上面的幾種比較常見的迭代使用形式,for...in...循環(huán)中還有一些tricks。下面總結(jié)的是一些比較常見的,不一定全面。

enumerate

當(dāng)我們想在一次迭代中不僅返回迭代對(duì)象中的元素的值,同時(shí)還想返回該元素對(duì)應(yīng)的下標(biāo),那么就可以使用enumerate()函數(shù),該函數(shù)能在一次迭代中同時(shí)返回元素值和對(duì)應(yīng)的下標(biāo)。當(dāng)想建立兩個(gè)迭代對(duì)象元素之間的對(duì)應(yīng)關(guān)系時(shí),enumerate可以作為一種方法。

for i, item in enumerate(['Tom', 'Tony', 'Max']):
    print("The index of {} is {}".format(item, i))
sub = ['Math', 'English']
score = [90, 88]
for i, item in enumerate(sub):
    print("The subject {} got {}".format(item, score[i]))
zip

zip是python的一個(gè)內(nèi)建函數(shù),接收一系列可迭代對(duì)象作為參數(shù),將對(duì)象中對(duì)應(yīng)的元素打包成一個(gè)個(gè)tuple(元組),然后返回由這些元組組成的list列表。若傳入的對(duì)象的長(zhǎng)度不等,則返回的list與參數(shù)中長(zhǎng)度最短的對(duì)象相同。

z1 = [1,2,3]
z2 = [4,5,6]
for i,j in zip(z1,z2):
    print(i,j)
# output
1 4
2 5
3 6
item()

item()方法允許我們同時(shí)操作dictionary的key和value, 用起來(lái)也十分方便。

sc = {"Python":90, "java"88, "C++":85}
for key, value in sc.item():
    print(key)
    print(value)

迭代器(iterator)

迭代器是訪問(wèn)集合中元素的一種方式,從集合中的第一個(gè)元素開始訪問(wèn),直到所有的元素都被訪問(wèn)一遍后結(jié)束。迭代器不能回退,只能往前進(jìn)行迭代。迭代器的一個(gè)優(yōu)點(diǎn)是不需要事先準(zhǔn)備好集合中的所有元素,僅僅在迭代至某個(gè)元素時(shí)才計(jì)算該元素。適合用于遍歷一些大的文件或集合。同時(shí)迭代器提供了一個(gè)統(tǒng)一的訪問(wèn)集合的接口,只要是定義了iter()方法的對(duì)象,就可以使用迭代器進(jìn)行訪問(wèn)??梢员籲ext()方法調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器,換句話說(shuō),迭代器對(duì)象具有next()方法。生成器就是迭代器對(duì)象,list、tuple、str等雖然是可迭代對(duì)象(Iterable),但不是迭代器(Iterator)。要把一個(gè)可迭代對(duì)象轉(zhuǎn)換成迭代器,可以使用iter()函數(shù)。另外可以使用isinstance()函數(shù)來(lái)判斷一個(gè)對(duì)象是可迭代對(duì)象還是迭代器對(duì)象。

對(duì)于迭代器的理解,可以把迭代器看成是一個(gè)數(shù)據(jù)流,迭代器對(duì)象被next()函數(shù)調(diào)用不斷返回下一個(gè)數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤。把這個(gè)數(shù)據(jù)流看做是一個(gè)有序序列,但卻不能提前知道這個(gè)數(shù)據(jù)流到底有多長(zhǎng),而對(duì)于list、tuple等可迭代對(duì)象來(lái)說(shuō),對(duì)象的長(zhǎng)度是可知的。這也是可迭代對(duì)象和迭代器的區(qū)別所在。

from collections import Iterator, Iterable
a = [1, 2, 3]
b = iter(a)
isinstance(a, Iterable)  
isinstance(a, Iterator)
isinstance(b, Iterable)
isinstance(b, Iterator)
isinstance((x*x for x in range(3)), Iterator)
isinstance((x*x for x in range(3)), Iterable)

# output
True
False
True
True
True
True

生成

生成的意思是說(shuō)通過(guò)某種規(guī)則產(chǎn)生一定的序列,在生成的過(guò)程中可能也會(huì)用到迭代操作。

列表生成式(list comprehension)

列表生成式是一種方便簡(jiǎn)潔的創(chuàng)建List的方式。創(chuàng)建一個(gè)List的一般思路可能是先創(chuàng)建一個(gè)空的List,然后再使用for循環(huán)進(jìn)行迭代,將每次迭代生成的值通過(guò)append方法添加到List中去。

a = []
for i in range(6):
    a.append(i)
print(a)

如果使用列表生成式,代碼則會(huì)相當(dāng)簡(jiǎn)潔。

a = [i*2 for i in range(6)]
b = [a + b for a in range(3) for b in range(4)]

生成器(generator)

使用列表生成式的確可以生成一定規(guī)則的列表,但同時(shí)由于內(nèi)存限制,列表容量是有限的。有時(shí)我們可能不想讓一個(gè)列表占用太大的內(nèi)存空間,我們希望在循環(huán)的過(guò)程中值是不斷推算不斷生成的,不必一次性創(chuàng)建完整的序列,從而節(jié)省內(nèi)存空間。Python中就有這種一邊循環(huán)一邊計(jì)算的機(jī)制,這種機(jī)制叫生成器。關(guān)于生成器,還有一種定義說(shuō),帶有yield的函數(shù)就被稱為生成器。帶有yield的函數(shù)不再是一個(gè)普通函數(shù),python解釋器會(huì)把它視為生成器。值得注意的是,生成器是可迭代對(duì)象,也是迭代器對(duì)象。

先講一種簡(jiǎn)單的創(chuàng)建一個(gè)生成器的方法,就是直接把列表生成式的[]換成()就創(chuàng)建了一個(gè)生成器。生成器具有next()方法,用于輸出每次迭代值。

a = (x*x for x in range(4))
next(a)
next(a)
for i in a:
    print(i)

值得注意的是。使用next()方法,當(dāng)?shù)阶詈笠粋€(gè)元素,沒(méi)有更多的元素時(shí),生成器會(huì)拋出StopIteration錯(cuò)誤。下面通過(guò)在函數(shù)中插入yield的方法來(lái)創(chuàng)建生成器。

def fab(m):
    i, a, b = 0, 0, 1
    while i < m:
        yield b
        a, b = b, a+b
        i = i + 1

yield把fab函數(shù)變成了一個(gè)生成器,每次循環(huán)執(zhí)行到語(yǔ)句 yield b 時(shí),fab函數(shù)就返回一個(gè)迭代值,下次迭代時(shí),代碼會(huì)從 yield b 語(yǔ)句的下一條語(yǔ)句繼續(xù)執(zhí)行,就好像是函數(shù)執(zhí)行過(guò)程中被yield中斷了數(shù)次,每次中斷都會(huì)通過(guò)yield返回當(dāng)前的迭代值。這個(gè)過(guò)程可以通過(guò)在代碼中嵌入打印一些標(biāo)記來(lái)進(jìn)行可視化。

def foo():
    print("begin")
    for i in range(2):
        print("before yield", i)
        yield i
        print("after yield", i)
    print("end")

f = foo()
next(f)
next(f)
next(f)

# output
begin
before yield 0
0

after yield 0
before yield 1
1

after yield 1
end
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

小結(jié)

可以使用for循環(huán)進(jìn)行迭代的對(duì)象都是可迭代(Iterable)類型,可以調(diào)用next()方法的對(duì)象都是迭代器(Iterator)類型,生成器(generator)既是可迭代類型,也是迭代器類型。

參考

  1. Python Practice Book(iterator & Generator)
  2. Python迭代器 生成器
  3. 廖雪峰的Python教程
  4. Python的函數(shù)式編程指南(三):迭代器

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多