1. 程式人生 > >python3:迭代物件和迭代器的區別 (翻看原始碼進行解釋)

python3:迭代物件和迭代器的區別 (翻看原始碼進行解釋)

迭代器和生成器都是很重要的知識,因為在後邊的同步非同步都要用到.

python的迭代協議構成了迭代器.

迭代器是訪問集合內元素的一種方式,一般用來遍歷資料.

要記住 迭代器和 下標的訪問方式不一樣,迭代器沒有返回值,它取值的方式就是用next().

迭代器提供了一種惰性訪問資料方式,訪問資料時候才能計算和返回資料.

list 的訪問方式是用 getitem 協議,
list 和迭代器 可以用for 迴圈都是實現迭代協議(iter)這個方法.

我們查詢下原始碼 :

from collections.abc import Iterable,Iterator
class Iterable(metaclass=ABCMeta):
    __slots__ = ()
    @abstractmethod
    def __iter__(self):
        while False:
            yield None

只要有這個 __iter__抽象魔法函式一定可迭代, 咱們再看下Iterator

class Iterator(Iterable):
    __slots__ = ()
    def __iter__(self):
        return  self
     @abstractmethod
    def __next__(self):
        raise StopIteration

大家看下 Iterator 比Iterable 多了一個抽象魔法函式 next,
並且繼承了Iterable也重寫了iter 抽象方法.

其中 iter 是返回個迭代物件,next 返回下一個資料,在我們訪問資料的時候就變成一個迭代器,

迭代器只是比迭代物件多了抽象魔法函式 next, 要記住迭代器也是迭代物件.

咱們 看下 list 原始碼 :

class list(object):
    """
    list() -> new empty list
    list(iterable) -> new list initialized from iterable's items
    """
    def append(self, p_object): # real signature unknown; restored from __doc__
        """ L.append(object) -> None -- append object to end """
        pass

    def __iter__(self, *args, **kwargs): # real signature unknown
        """ Implement iter(self). """
        pass

list 只重寫了 iter 這個魔法函式,所以list 只是個可迭代物件.

具體有什麼區別,我們看下邊的例子:

>>> x = [1,2,3]
>>> y = iter(x)  #inter是特殊的方法可以把迭代物件變成迭代器,可以查下
>>> z = iter(x)
>>> next(y)   #通過inter方法變成迭代器之後就可以用next方法,如果用 next(x)會報錯
1
>>> next(y)
2
>>> next(z)
1
>>> type(x)
<class 'list'>
>>> type(y)   #inter是特殊的方法可以把迭代物件變成迭代器,可以查下
<class 'list_iterator'>

上邊的iter 和next 與魔法函式的__inter__ 和__next__ 是不一樣的,自己可以查下.
只要迭代物件呼叫了next方法就可以變成迭代器.
迭代器是可以迴圈輸出,直到報錯為止.

有人說了 list 是個迭代物件,為什麼可以用for迴圈.

for i in [0,2,3]:
    print(i)

1.首先list 是迭代物件,它只是重寫了iter魔法函式,
2.那為什麼可以迴圈輸出呢,答案是for 迴圈自帶next 魔法函式

咱們debug 看下:

Iterator = {ABCMeta} <class 'collections.abc.Iterator'>
Iterable = {ABCMeta} <class 'collections.abc.Iterable'>

list 用到了for迴圈的 next,變成個迭代器可以迴圈輸出.

for  i in [1,2,3]:
    print(i)

就相當於 :

a=iter([1,2,3,4])

while True:

    try:
      x = next(a);
    except StopIteration:
        break
    print(x)

先呼叫了iter 從迭代物件變成一個迭代器,然後呼叫了next 方法.進行遍歷.

有什麼問題請在下邊留言, 謝謝