Python進階-魔術方法(2)


3樓貓 發佈時間:2024-08-13 00:55:06 作者:贏贏贏贏麻 Language

前言

前篇:

魔術方法(1):使用__str__與__repr__進行字符串操作

正文

魔術方法(2):使用__iter__與__next__實現可迭代

for循環可能是我們最熟悉的循環操作,但是你是否思考過,for循環內部做了些什麼?它怎麼知道什麼時候停止循環?又是如何保證元素的遍歷不會出錯?

突然講原理可能難以理解,先仔細觀察下列代碼和運行結果,認真分析一下打印的先後情況

Python進階-魔術方法(2)-第0張

一個基於魔術方法實現的平方迭代器

Python進階-魔術方法(2)-第1張

運行結果

在開始講解之前,我們先補充幾個知識點:

Python進階-魔術方法(2)-第2張

專業術語的定義

  1. 可迭代對象:實現了__iter__方法,也就是可以使用for循環的對象

  2. 迭代器:如果一個可迭代對象裡面也實現了__next__方法,那麼這就是一個迭代器,也就是可以使用next()函數的對象

  3. 生成器:一種特殊的迭代器,自動實現了__iter____next__方法,也就是調用包含yield的函數所返回的對象(這種用法後面會在高級語法中講解)

順帶一提,Python的三大基本序列類型就是list,tuple和range,怎麼樣,沒想到吧,range的位格這麼高,這可是官方文檔(點擊查看)自己說的

--------分割--------

接下來讓我們逐步分析上述代碼:

  1. 當我們對一個對象使用for i in XXX的時候,在這一步就會調用該對象的__iter__方法。因為返回的對象會交給for循環處理,所以通常我們會返回的其實就是對象本身即return self

  2. 在接下來每次讀取值的時候,就會調用對象的__next__方法來得到下一個值,當返回的是停止信號(即StopIteration異常)時,讀取結束,這也是為什麼會多打印出一個__next__

也就是說使用__iter__來返回一個東西交給for循環,而__next__來逐步獲得下一個值,直到拋出StopIteration

請務必理解上述執行過程,然後讓我們用於實踐

--------分割--------

假如有一個班級類,裡面保存了很多學生的姓名,基本代碼如下

Python進階-魔術方法(2)-第3張

一個簡單的教室類,用來保存學生姓名

如果我們希望遍歷這些學生信息,你也許會使用

for student in classroom.students:

但是我個人來說並不喜歡這樣,這並不優雅,而且暴露變量的引用往往意味著危險,外部的改變隨時會改變對象內部的狀態:

my_student = classroom.students

my_student.pop()

print(classroom.students)

當我將對象classroom的學生列表引用暴露出去,再使用這個引用彈出一個元素,對象內部的學生列表也發生了變化,這正是需要警惕的地方(誰說python沒指針.doge)

現在我們來給Classroom類實現一個迭代屬性,讓我們可以對教室進行for循環!

Python進階-魔術方法(2)-第3張

可迭代的教室類

Python進階-魔術方法(2)-第3張

運行結果

這裡有一個取巧的方法,不同於上面所說的“__iter__通常返回對象本身”,這裡我們完全可以將遍歷委託給students列表來實現,我們也不需要關心__next__的返回內容和跳出判斷。


© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com