本文首發於知乎專欄,歡迎關注。 知乎專欄傳送門python
如下測試代碼所有基於 Python3。bash
想要反向迭代一個序列很容易,使用內置函數 reversed() 即可以作到,以下:函數
In [1]: a = [1, 2, 3, 4]
In [2]: for x in reversed(a):
...: print(x)
...:
4
3
2
1
複製代碼
反向迭代的特色是,須要預先知道迭代對象的大小,或者對象實現了 __reversed__()
方法,若是二者都不符合,那麼,必須先將對象轉換成一個列表才能夠。測試
# Print a file backwards
f = open('somefile')
for line in reversed(list(f)):
print(line, end='')
複製代碼
有一個須要注意的問題就是,若是迭代對象元素不少的話,在轉換成列表的過程當中會耗費大量的內存。ui
想解決這個問題,能夠在自定義類上實現 __reversed__()
方法來解決,代碼以下:spa
#!/usr/bin/env python
#-*- encoding: utf-8 -*-
def reverse_iterate():
for rr in reversed(Countdown(30)):
print(rr)
for rr in Countdown(30):
print(rr)
class Countdown:
def __init__(self, start):
self.start = start
# Forward iterator
def __iter__(self):
n = self.start
while n > 0:
yield n
n -= 1
# Reverse iterator 當使用reversed函數翻轉對象時調用
def __reversed__(self):
n = 1
while n <= self.start:
yield n
n += 1
if __name__ == '__main__':
reverse_iterate()
複製代碼
這個方法可使代碼很是的高效,由於它再也不須要將數據填充到一個列表中,而後再去反向迭代這個列表。code
在處理列表相關問題時,使用切片操做很是方便,但遺憾的是,迭代器並不支持標準的切片操做,主要緣由就是由於,咱們事先並不知道迭代器和生成器的長度。對象
In [3]: def count(n):
...: while True:
...: yield n
...: n += 1
...:
In [4]: c = count(0)
In [5]: c[10: 20]
-----------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-60489cd5ce42> in <module>()
> 1 c[10: 20]
TypeError: 'generator' object is not subscriptable
複製代碼
想在迭代器和生成器上使用切片操做,可使用 itertools.islice() 函數:排序
In [6]: import itertools
In [7]: for x in itertools.islice(c, 10, 20):
...: print(x)
...:
10
11
12
13
14
15
16
17
18
19
複製代碼
可是這裏有一個問題,islice() 函數會消耗掉傳入的數據,好比我再調用一次這個函數,返回的結果就發生了變化。ip
In [8]: for x in itertools.islice(c, 10, 20):
...: print(x)
...:
...:
30
31
32
33
34
35
36
37
38
39
複製代碼
因此,若是想屢次使用切片的結果,就須要把數據存起來。
假設如今有多個排序序列,如今想把它們合併,而且獲得一個新的排序序列,應該怎麼作呢?
heapq.merge() 函數能夠完美解決這個問題:
In [9]: import heapq
In [10]: a = [1, 4, 7, 10]
In [11]: b = [2, 5, 6, 11]
In [12]: heapq.merge(a, b)
Out[12]: <generator object merge at 0x1087ab570>
In [13]: for x in heapq.merge(a, b):
...: print(x)
...:
1
2
4
5
6
7
10
11
複製代碼
須要注意的一點是,傳入的序列必須是排過序的。
若是序列中元素過多,也並不須要擔憂效率問題,經過上面代碼也能夠看出,heapq.merge() 函數的返回結果依然是一個生成器,並不是是列表。
未完待續。。。