Pyhton3的range是回傳的什麼?很多人都會不假思索的說,這還不簡單,在Python2中range()會返回list,到了Python3range已經使用xrange替換,返回的是一個迭代器(Iterator)。
恭喜你,答錯了。
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中文網其他相關文章!