詳解Python中for迴圈的工作原理

零下一度
發布: 2017-07-02 10:45:00
原創
5072 人瀏覽過

如果你對python中的for循環不是很清楚,那麼建議你看看這篇文章,本文主要給大家介紹了關於Python中for循環是如何工作的相關資料,介紹的非常詳細,對大家有一定的參考學習價值,需要的朋友們下面來一起看看吧。

前言

for...in 是Python程式設計師使用最多的語句,for 迴圈用於迭代容器物件中的元素,這些物件可以是列表、元組、字典、集合、文件,甚至可以是自訂類別或函數,例如:

作用於列表


#
>>> for elem in [1,2,3]:
...  print(elem)
...
1
2
3
登入後複製

作用於元組


#
>>> for i in ("zhang", "san", 30):
...  print(i)
...
zhang
san
30
登入後複製

作用於字串


>>> for c in "abc":
...  print(c)
...
a
b
c
登入後複製

作用於字典


>>> for i in {"a","b","c"}:
...  print(i)
...
b
a
c
登入後複製

作用於檔案


>>> for k in {"age":10, "name":"wang"}:
...  print(k)
...
age
name
登入後複製

可能有人不經要問,為什麼這麼多不同類型物件都支援for 語句,還有哪些類型的物件可以作用在for 語句中呢?在回答這個問題之前,我們先要了解 for 迴圈背後的執行原理。 for 迴圈是對容器進行迭代的過程,什麼是迭代?迭代就是從某個容器物件逐一讀取元素,直到容器中沒有更多元素為止。那麼,哪些物件支援迭代操作?任何物件都可以嗎?先隨便自訂一個類別試試,看行不行:


>>> for line in open("requirement.txt"):
...  print(line, end="")
...
Fabric==1.12.0
Markdown==2.6.7
登入後複製

錯誤堆疊日誌非常清楚地告訴我們,MyRange 不是一個可迭代對象,所以它不能用於迭代,那麼到底是什麼樣的物件才稱得上是可迭代物件(iterable)呢?

可迭代物件需要實作iter方法,並傳回一個迭代器,什麼是迭代器呢?迭代器只需要實作 next方法。現在我們就來驗證一下列表為什麼支持迭代:


>>> class MyRange:
...  def init(self, num):
...   self.num = num
...
>>> for i in MyRange(10):
...  print(i)
...
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: &#39;MyRange&#39; object is not iterable
登入後複製

從試驗結果來看,列表是一個可迭代對象,因為它實現了iter方法,並且返回了一個迭代器物件(list_iterator),因為它實作了next方法。我們看到它不斷地呼叫next方法,其實就是不斷地迭代取得容器中的元素,直到容器中沒有更多元素拋出 StopIteration 異常為止。

那麼 for 語句又是如何循環的呢?到這裡,恐怕你也猜到了,它的步驟是:


先判斷對像是否為可迭代對象,不是的話直接報錯,拋出TypeError異常,是的話,呼叫iter方法,傳回一個迭代器

不斷地呼叫迭代器的next方法,每次依序傳回迭代器中的一個值
  • 迭代到最後,沒有更多元素了,就
  • 拋出異常
  • StopIteration,這個異常python 自己會處理,不會暴露給開發者


  • 對於元組,字典,字串也是同樣的道理,弄清楚了for 的執行原理之後,我們就可以實作自己的迭代器用在for 迴圈中。

  • 前面的MyRange 錯誤是因為它沒有實作迭代器協定裡面的這兩個方法,現在繼續改進:

>>> x = [1,2,3]
>>> its = x.iter() # x有此方法,说明列表是可迭代对象
>>> its
<list_iterator object at 0x100f32198>

>>> its.next() # its有此方法,说明its是迭代器
1
>>> its.next()
2
>>> its.next()
3
>>> its.next()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration
登入後複製

因為它實作了next方法,所以MyRange 本身已經是一個迭代器了,所以iter回傳的就是物件本身self。現在用在 for 迴圈中試試:

class MyRange:
 def init(self, num):
  self.i = 0
  self.num = num

 def iter(self):
  return self

 def next(self):
  if self.i < self.num:
   i = self.i
   self.i += 1
   return i
  else:
   # 达到某个条件时必须抛出此异常,否则会无止境地迭代下去
   raise StopIteration()
登入後複製

有沒有發現,自訂的 MyRange 功能和內建函數 range很相似。 for 迴圈本質是不斷地呼叫迭代器的next方法,直到有 StopIteration 異常為止,所以任何可迭代物件都可以作用在for迴圈中。

以上是詳解Python中for迴圈的工作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!