1. 程式人生 > >Python學習日記(5)簡單了解叠代器、生成器、裝飾器、上下文管理器

Python學習日記(5)簡單了解叠代器、生成器、裝飾器、上下文管理器

進行 strong 生成器 __next__ 後繼 with while 並且 本質

叠代器

叠代器只不過是一個實現了叠代器協議的容器對象。它基於以下兩個方法。

__ 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)簡單了解叠代器、生成器、裝飾器、上下文管理器