Python學習日記(5)簡單了解叠代器、生成器、裝飾器、上下文管理器
叠代器
叠代器只不過是一個實現了叠代器協議的容器對象。它基於以下兩個方法。
__ next __
:返回容器的下一個元素。
__ iter __
:返回叠代器本身。
實際上,叠代器表現了程序底層的概念和特性,在程序中,你可以不必使用叠代器,但是理解叠代器,卻是對生成器這樣一個常用特性理解很有幫助。
學習叠代器,我基本上通過2個例子來理解叠代器的特性。(PS:我發現我之前記得筆記不是很詳細,所以這一篇記錄詳細一些……不然我有時候一些點我自己看的時候都要想一下,吐血,果然沒什麽靈性……)
好了,上代碼:
a = iter([11,22,33])
print(next(a))
print(next(a))
print(next(a))
-------------------------
11
22
33
[Finished in 0.2s]
這裏,我創建了一個非常簡陋的叠代器,使用iter()函數,這個函數在上述的代碼中接收了一個列表作為參數,並賦值給a這個變量。
那麽此時,a就是一個叠代器了。當然,此時創建的這個a的叠代器非常的簡陋,就好比我要造飛機,結果你用紙給我疊了一個。不過飛機的特性還是有的,可以算是飛機了,只不過是紙飛機。
叠代器使用:通過函數next()來使用,next()函數參數接收一個叠代器,並在每一次執行的時候,依次調取叠代器中的值,並返回出來。
簡單理解:next()函數呢,就好比遊戲登錄器,遊戲就好比叠代器,沒有登錄器你玩不了遊戲,所以,沒next()這玩意你用不了叠代器,想用叠代器,你需要用next()這個方法調,next()這個方法有一個特點,從頭開始調,每次調一個。
那麽,為什麽說我們用iter()創建的叠代器是紙飛機呢?
看代碼思考2個問題:
1,每次調用是進行依次調用的,上述代碼調用的剛好是個列表,如果,調用列表中最後一個值之後,繼續調用,會怎麽樣呢?
a = iter([11,22,33]) print(next(a)) print(next(a)) print(next(a)) print(next(a)) ------------------------- StopIteration [Finished in 0.2s with exit code 1]
可以看到,叠代器中只有3個值,而我調用了4次,所以在第四次調用的時候,返回了一個StopIteration異常。這是好事,異常代表著叠代的完結,我們可以利用異常做點事情。
2,為什麽說紙飛機呢,這個叠代器有一個非常不好的點,那就是叠代的次數並非我們想要的,如果我們想叠代100次,總不至於寫一個有100個元素的列表吧?當然,你可以說我可以用range()來解決這個問題呀。
a = iter(range(4)) print(next(a)) print(next(a)) print(next(a)) print(next(a)) ------------------------------- 0 1 2 3 [Finished in 0.2s]
可是,實際上,並沒有解決觸發異常的問題。並且每一次的叠代,都需要next()來手工進行,那麽,我們來做一個真正的叠代器。
class CountDown(): def __init__(self,step): self.step = step def __next__(self): if self.step <= 0: raise StopIteration self.step = self.step - 1 return self.step def __iter__(self): return self ff = CountDown(5) for i in ff: print(i) ------------------------------------- 4 3 2 1 0 [Finished in 0.2s]
__ next __
:返回容器的下一個元素。
__ iter __
:返回叠代器本身。
這個類就非常明確了,接收叠代次數,並且每次叠代減1,觸發異常停止叠代。實際上,叠代只是一種概念,叠代器則提供了一種專門的方法,並非在python程序中唯一的叠代動作!
生成器
生成器是一種優雅的方法,他可以讓編寫返回元素序列的函數代碼變得簡單,高效。
實際上,我們常用的方法:range()
for i in range(10): print(i)
也是生成了一個列表來供我們遍歷,在python3中,本質也是生成器。
當然,我們也可以自己寫一個列表生成器,不使用range()
def Maker(num): a = 0 while True: b = a a = a + 1 num = num - 1 yield b if num <= 0: break ff = Maker(10) a = [i for i in Maker(10)] b = [x for x in range(10)] print(a) print(b) -------------------------------------------- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [Finished in 0.2s]
看,我們自己寫了一個生成器方法Maker(),這個方法接收一個參數,來表示生成列表數量,與range()函數的方法是一樣的。(起碼在調用看來是的)
代碼中的:yield語句,表示暫停生成器,返回結果。是不是有點像return?可以想一想,是有區別的,一個是暫停,返回後繼續執行後面的代碼,return返回後就不在執行啦。
實際上,生成器可以執行復雜的生成過程,不過具體還是要看你要實現什麽需求。
Python學習日記(5)簡單了解叠代器、生成器、裝飾器、上下文管理器