首頁  >  文章  >  後端開發  >  python3中的range回傳的是迭代器嗎?

python3中的range回傳的是迭代器嗎?

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼轉載
2019-06-03 15:31:132930瀏覽

Pyhton3的range是回傳的什麼?很多人都會不假思索的說,這還不簡單,在Python2中range()會返回list,到了Python3range已經使用xrange替換,返回的是一個迭代器(Iterator)。

恭喜你,答錯了。

python3中的range回傳的是迭代器嗎?

range()回傳的是一個Iterable,不是一個Iterator.

a  Python 3.6.3 (default, Nov  3 2017, 14:41:25)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: a = range(10) 
In [2]: a
Out[2]: range(0, 10)
In [3]: import collections
In [4]: isinstance(a, collections.Iterable)
Out[4]: True 
In [5]: isinstance(a, collections.Iterator)
Out[5]: False

   

原理很簡單,先簡單說一下Iterable和Iterator,不要試圖比較二者有什麼不同,因為二者根本就是不同的概念。二者字面意思都非常明確:Iterable就是一個可迭代的對象,對其調用iter(Iterable)將會得到一個迭代器;而Iterator就是一個迭代器,對其調用next(Iterator)將會得到下一個元素。

Python推崇協議,說白了就是鴨子類型。你如果實作了__iter__(),(即對你呼叫iter()可以得到一個Iterator)那你就是一個Iterable;如果實作了__next__()和__iter__()就是一個Iterator。

等等,Iterator不就是呼叫next()得到下一個元素就可以了?為什麼Iterator也要實作Iterable的__iter__()方法,這不純粹啊!

為什麼Python的Iterator要實作__iter__()呢(通常的實作都是return self)。官方文檔中說的相當清楚。

Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted.

簡單翻譯一下,就是說Iterator也要求實作__iter__(),因為很多地方接收的參數是一個Iterable,如果所有的Iterator都是Iterable,那麼這些用Iterable地方都可以無障礙地使用Iterator了。比如說for循環吧,關於for循環,我在Python的wiki中(已經比較老了)找到這樣的描述:

Basically, any object with an iterable method can be used in a for loop. Even strings, despite not having an iterable method – but we’ll not get on to that here.

即,for循環拿到一個Iterable的Iterator,然後使用這個Iterator進行迭代。如果Iterator實作了__iter__()方法,那麼for迴圈就可以無障礙地對Iterator進行迭代了,Neat!想像一下,Python的生成器也是Iterator,如果for迴圈不能支援對Iterator迭代,生不如死啊。

所以對Iterator就有了這樣一個「過分」的要求。我們可以認為,所有的Iterator都是Iterable。那麼回到最初的問題,為什麼range()反回的是一個Iterable而不是Iterator呢?

考慮我們平常使用range(),我們認為這是一個表示範圍的一個容器。可以使用這個容器去初始化成別的容器,這沒有任何問題。

>>> numbers = range(3)
>>> tuple(numbers)
(0, 1, 2)
>>> tuple(numbers)
(0, 1, 2)

   

倘若range()回傳的是迭代器,那麼上面這個看起來在正常不過的程式碼就有麻煩了:

>>> numbers = iter(range(3))
>>> tuple(numbers)
(0, 1, 2)
>>> tuple(numbers)
()

#總結   

Iterator是有狀態的,只能遍歷一次,是「消費型」的,不可以「二次消費」。 Iterable是沒有狀態的(這裡不太嚴謹,這句話暫且不提是Iterator的Iterable),每次對Iterable呼叫iter()都會得到一個新的迭代器。

以上是python3中的range回傳的是迭代器嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:kawabangga.com。如有侵權,請聯絡admin@php.cn刪除