流暢的迭代器03.png
通過一個簡單類的實現及優(yōu)化過程猿妈,慢慢深入迭代的概念师脂。
該類的主要功能如下:
- 傳入一段話
- 可以迭代輸出這段話的中所包含的每個詞
惰性單詞序列
前面的兩個版本單詞序列,都是我們事先就把所有的單詞全部找了出來趟济。
這種情況下庐杨,如果我只用到前面幾個單詞,或者我傳入一串很長的文字招刨,解析出來的所有單詞當前內存都不夠存放霎俩,那該怎么辦?
最好我們用到的時候再去計算所需的單詞是什么沉眶,Python re
模塊的 finditer
就是 findall
的惰性實現版本打却。
使用 finditer
后,我們的代碼就變成了這樣:
import re
import reprlib
RE_WORD = re.compile(r'\w+')
class Sentence(object):
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
這時候我們就不需要 self.words
列表來存放我們事先算出來的所有單詞沦寂,通過 finditer
拿到一個可迭代對象学密,然后通過 yield
關鍵字使得 __iter__
方法返回一個生成器(生成器實現了 __iter__
和 __next__
接口)。
OK传藏,我們惰性版本的單詞序列就完成了腻暮。
生成器表達式
看一個很有意思的例子:
In [1]: def gen_AB():
...: print('start')
...: yield 'A'
...: print('continue')
...: yield 'B'
...: print('end.')
...:
In [2]: res1 = [x*3 for x in gen_AB()]
start
continue
end.
In [3]: for i in res1:
...: print('-->', i)
...:
--> AAA
--> BBB
In [4]: res2 = (x*3 for x in gen_AB())
In [5]: res2
Out[5]: <generator object <genexpr> at 0x000001CCFAE7E518>
In [6]: for i in res2:
...: print('-->', i)
...:
start
--> AAA
continue
--> BBB
end.
列表推導式和生成器表達式雖然只是 []
和 ()
的區(qū)別彤守,但是從上面這個例子直觀的看到,列表推導式是直接把整個 gen_AB()
運行一遍哭靖,而 res2
只是生成一個生成器具垫,只有當真正迭代 res2
的時候才會去運行指定的代碼。
我們的惰性版單詞序列也可以使用生成器表達式:
import re
import reprlib
RE_WORD = re.compile(r'\w+')
class Sentence(object):
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
return (match.group() for match in RE_WORD.finditer(self.text))
看起來是不是又簡潔了一點 (? ?_?)?
總結
- 使用生成器的時候需要考慮其他哪些相關代碼可以有相應的惰性實現方法试幽。
- 生成器表達式和列表推導式類似筝蚕,但是生成器表達式是惰性的。