Python 迭代器與生成器 - PyTips 0x01

PyTips

項(xiàng)目地址:https://git.io/pytips

迭代器與生成器

迭代器(iterator)與生成器(generator)是 Python 中比較常用又很容易混淆的兩個(gè)概念煮寡,今天就把它們梳理一遍虹蓄,并舉一些常用的例子。

for 語句與可迭代對象(iterable object):

for i in [1, 2, 3]:
    print(i)
1
2
3
obj = {"a": 123, "b": 456}
for k in obj:
    print(k)
b
a

這些可以用在 for 語句進(jìn)行循環(huán)的對象就是可迭代對象幸撕。除了內(nèi)置的數(shù)據(jù)類型(列表薇组、元組、字符串坐儿、字典等)可以通過 for 語句進(jìn)行迭代律胀,我們也可以自己創(chuàng)建一個(gè)容器,包含一系列元素貌矿,可以通過 for 語句依次循環(huán)取出每一個(gè)元素炭菌,這種容器就是迭代器(iterator)。除了用 for 遍歷逛漫,迭代器還可以通過 next() 方法逐一讀取下一個(gè)元素黑低。要?jiǎng)?chuàng)建一個(gè)迭代器有3種方法,其中前兩種分別是:

  1. 為容器對象添加 __iter__()__next__() 方法(Python 2.7 中是 next())酌毡;__iter__() 返回迭代器對象本身 self克握,__next__() 則返回每次調(diào)用 next() 或迭代時(shí)的元素;
  2. 內(nèi)置函數(shù) iter() 將可迭代對象轉(zhuǎn)化為迭代器
# iter(IterableObject)
ita = iter([1, 2, 3])
print(type(ita))

print(next(ita))
print(next(ita))
print(next(ita))

# Create iterator Object
class Container:
    def __init__(self, start = 0, end = 0):
        self.start = start
        self.end = end
    def __iter__(self):
        print("[LOG] I made this iterator!")
        return self
    def __next__(self):
        print("[LOG] Calling __next__ method!")
        if self.start < self.end:
            i = self.start
            self.start += 1
            return i
        else:
            raise StopIteration()
c = Container(0, 5)
for i in c:
    print(i)
        
<class 'list_iterator'>
1
2
3
[LOG] I made this iterator!
[LOG] Calling __next__ method!
0
[LOG] Calling __next__ method!
1
[LOG] Calling __next__ method!
2
[LOG] Calling __next__ method!
3
[LOG] Calling __next__ method!
4
[LOG] Calling __next__ method!

創(chuàng)建迭代器對象的好處是當(dāng)序列長度很大時(shí)枷踏,可以減少內(nèi)存消耗菩暗,因?yàn)槊看沃恍枰涗浺粋€(gè)值即刻(經(jīng)常看到人們介紹 Python 2.7 的 range 函數(shù)時(shí)旭蠕,建議當(dāng)長度太大時(shí)用 xrange 更快停团,在 Python 3.5 中已經(jīng)去除了 xrange 只有一個(gè)類似迭代器一樣的 range)婴梧。

生成器

前面說到創(chuàng)建迭代器有3種方法,其中第三種就是生成器(generator)客蹋。生成器通過 yield 語句快速生成迭代器,省略了復(fù)雜的 __iter__() & __next__() 方式:

def container(start, end):
    while start < end:
        yield start
        start += 1
c = container(0, 5)
print(type(c))
print(next(c))
next(c)
for i in c:
    print(i)
<class 'generator'>
0
2
3
4

簡單來說孽江,yield 語句可以讓普通函數(shù)變成一個(gè)生成器讶坯,并且相應(yīng)的 __next__() 方法返回的是 yield 后面的值。一種更直觀的解釋是:程序執(zhí)行到 yield 會返回值并暫停岗屏,再次調(diào)用 next() 時(shí)會從上次暫停的地方繼續(xù)開始執(zhí)行:

def gen():
    yield 5
    yield "Hello"
    yield "World"
    yield 4
for i in gen():
    print(i)
5
Hello
World
4

Python 3.5 (準(zhǔn)確地說應(yīng)該是 3.3 以后)中為生成器添加了更多特性辆琅,包括 yield from 以及在暫停的地方傳值回生成器的 send()等,為了保持簡潔這里就不深入介紹了这刷,有興趣可以閱讀官方文檔說明以及參考鏈接2婉烟。

參考

  1. Iterators & Generators
  2. How the heck does async/await work in Python 3.5?
  3. Python's yield from
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市暇屋,隨后出現(xiàn)的幾起案子似袁,更是在濱河造成了極大的恐慌,老刑警劉巖咐刨,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昙衅,死亡現(xiàn)場離奇詭異,居然都是意外死亡定鸟,警方通過查閱死者的電腦和手機(jī)而涉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來联予,“玉大人啼县,你說我怎么就攤上這事》芯茫” “怎么了季眷?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卷胯。 經(jīng)常有香客問我瘟裸,道長,這世上最難降的妖魔是什么诵竭? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任话告,我火速辦了婚禮,結(jié)果婚禮上卵慰,老公的妹妹穿的比我還像新娘沙郭。我一直安慰自己,他們只是感情好裳朋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布病线。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪送挑。 梳的紋絲不亂的頭發(fā)上绑莺,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音惕耕,去河邊找鬼纺裁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛司澎,可吹牛的內(nèi)容都是我干的欺缘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挤安,長吁一口氣:“原來是場噩夢啊……” “哼谚殊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛤铜,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嫩絮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后围肥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體絮记,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忧陪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年戳气,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片癌压。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛹批,死狀恐怖撰洗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腐芍,我是刑警寧澤差导,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站猪勇,受9級特大地震影響设褐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泣刹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一助析、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧椅您,春花似錦外冀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽西轩。三九已至,卻和暖如春脑沿,著一層夾襖步出監(jiān)牢的瞬間藕畔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工庄拇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留注服,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓丛忆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仍秤。 傳聞我的和親對象是個(gè)殘疾皇子熄诡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容