python迭代器生成器使用技巧(2):切片、遍历、索引值、多序列、多容器对象
1. 迭代器切片
迭代器和生成器不能使用標(biāo)準(zhǔn)的切片操作,因為它們的長度事先并不知道(并且也沒有實現(xiàn)索引)。 函數(shù) islice() 返回一個可以生成指定元素的迭代器,通過遍歷并丟棄直到切片開始索引位置的所有元素,然后開始一個個的返回元素,并直到切片結(jié)束索引位置。
import itertools def count(n):while True:yield n n += 1c = count(0) # print( c[10:20] ) # TypeError: 'generator' object is not subscriptablefor num in itertools.islice(c, 10, 15):print(num) # >>> 10, 11, 12, 13, 14這里需要強(qiáng)調(diào)的一點是 islice() 會消耗掉傳入的迭代器中的數(shù)據(jù)。 而迭代器是不可逆的。 所以如果需要之后再次訪問這個迭代器的話,就得先將它里面的數(shù)據(jù)放入一個列表中了。
2. 排列組合的迭代遍歷
如果我們想迭代遍歷集合中元素的所有可能的排列或組合,可以用itertools模塊提供兩函數(shù)來解決這類問題。
- itertools.permutations() , 接受集合并產(chǎn)生一個元組序列,每個元組由集合中所有元素的一個可能排列組成。 也就是說通過打亂集合中元素排列順序生成一個元組。如果想得到指定長度的排列,可以傳遞長度參數(shù)permutation(items, length)。
- itertools.combinations() 得到輸入集合中元素的所有的組合
對于 combinations() ,元素的順序已經(jīng)不重要了。 也就是說,組合 ('a', 'b') 跟 ('b', 'a') 其實是一樣的.
3. 序列上索引值迭代?enumerate()
如果我們想在迭代一個序列的同時跟蹤正在被處理的元素索引時可以采用這種方法。這種情況在遍歷文件時想在錯誤消息中使用行號定位時候非常有用。
my_list = ['a', 'b', 'c'] for idx, val in enumerate(my_list):print(idx, val) # >>> 0 a # 1 b # 2 c遍歷文件消息時,可以直接用于發(fā)現(xiàn)文件消息發(fā)生錯誤所處的位置(行號):
def parse_data(filename):with open(filename, 'rt') as f:for idx, line in enumerate(f,1): # from Line 1fields = line.split()try:# cnt = int (fields[1])passexcept ValueError as e:print('Line{}:Parse error: {}'.format(idx, e))parse_data('test.txt')4. 同時迭代多個序列 zip()
如何同時迭代多個序列,每次分別從一個序列中取一個元素?zip()函數(shù)就是為了解決多個序列同時迭代而設(shè)計的。
- zip() 最小迭代終止
zip(a, b) 會生成一個可返回元組 (x, y) 的迭代器,其中x來自a,y來自b。 一旦其中某個序列到底結(jié)尾,迭代宣告結(jié)束。 因此迭代長度跟參數(shù)中最短序列長度一致。
- zip_longest() 最大迭代終止
zip() 函數(shù)對于同時處理兩個、兩個以上的序列非常有用。需要注意的一點是:zip() 會創(chuàng)建一個迭代器來作為結(jié)果返回。 如果需要將結(jié)對的值存儲在列表中,要使用list() 函數(shù)。
xpts = [1, 5, 4, 2, 10] ypts = [101, 78, 37, 15, 62, 99, 56, 22] print(zip(xpts, ypts)) # >>> <zip object at 0x0000000007505F88> print(list(zip(xpts, ypts))) # >>> [(1, 101), (5, 78), (4, 37), (2, 15), (10, 62)]5. 不同集合上元素的迭代
如果我們想在多個對象執(zhí)行相同的操作,但是這些對象在不同的容器中。在不失可讀性的情況下如何避免寫重復(fù)的循環(huán)?itertools.chain() 可以用來簡化這個任務(wù)。 它接受可迭代對象列表作為輸入,并返回一個迭代器,有效的屏蔽掉在多個容器中迭代細(xì)節(jié)。?
from itertools import chaina = [1, 2] b = ['x', 'y', 'z'] for x in chain(a, b):print(x) # >>> 1 2 x y zprint(chain(a, b)) # >>> <itertools.chain object at 0x0000000008B18978>print(list(chain(a,b))) # >>> [1, 2, 'x', 'y', 'z']itertools.chain() 接受一個或多個可迭代對象作為輸入?yún)?shù)。 然后創(chuàng)建一個迭代器,依次連續(xù)的返回每個可迭代對象中的元素。 這種方式(chain(a,b))要比先將序列合并(a+b)再迭代要高效的多。a + b 操作會創(chuàng)建一個全新的序列并要求a和b的類型一致。 chian() 不會有這一步,所以如果輸入序列非常大的時候會很省內(nèi)存。 并且當(dāng)可迭代對象類型不一樣的時候 chain() 同樣可以很好的工作。
文章參考《python3-cookbook》
總結(jié)
以上是生活随笔為你收集整理的python迭代器生成器使用技巧(2):切片、遍历、索引值、多序列、多容器对象的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员自我提高情绪10招
- 下一篇: 透彻理解RPN: 从候选区域搜索到候选区