Python中的“iterable”、“iterator”和“iteration”是什么?它们是如何定义的?


当前回答

下面是我的小抄:

 sequence
  +
  |
  v
   def __getitem__(self, index: int):
  +    ...
  |    raise IndexError
  |
  |
  |              def __iter__(self):
  |             +     ...
  |             |     return <iterator>
  |             |
  |             |
  +--> or <-----+        def __next__(self):
       +        |       +    ...
       |        |       |    raise StopIteration
       v        |       |
    iterable    |       |
           +    |       |
           |    |       v
           |    +----> and +-------> iterator
           |                               ^
           v                               |
   iter(<iterable>) +----------------------+
                                           |
   def generator():                        |
  +    yield 1                             |
  |                 generator_expression +-+
  |                                        |
  +-> generator() +-> generator_iterator +-+

小测验:你看到…

每个迭代器都是可迭代对象? 容器对象的__iter__()方法可以实现为生成器? 具有__next__方法的迭代器不一定是迭代器?

答案:

Every iterator must have an __iter__ method. Having __iter__ is enough to be an iterable. Therefore every iterator is an iterable. When __iter__ is called it should return an iterator (return <iterator> in the diagram above). Calling a generator returns a generator iterator which is a type of iterator. class Iterable1: def __iter__(self): # a method (which is a function defined inside a class body) # calling iter() converts iterable (tuple) to iterator return iter((1,2,3)) class Iterable2: def __iter__(self): # a generator for i in (1, 2, 3): yield i class Iterable3: def __iter__(self): # with PEP 380 syntax yield from (1, 2, 3) # passes assert list(Iterable1()) == list(Iterable2()) == list(Iterable3()) == [1, 2, 3] Here is an example: class MyIterable: def __init__(self): self.n = 0 def __getitem__(self, index: int): return (1, 2, 3)[index] def __next__(self): n = self.n = self.n + 1 if n > 3: raise StopIteration return n # if you can iter it without raising a TypeError, then it's an iterable. iter(MyIterable()) # but obviously `MyIterable()` is not an iterator since it does not have # an `__iter__` method. from collections.abc import Iterator assert isinstance(MyIterable(), Iterator) # AssertionError

其他回答

这是另一个使用collections.abc的视图。这个视图在第二次或以后可能会有用。

从集合。ABC我们可以看到下面的层次结构:

builtins.object
    Iterable
        Iterator
            Generator

例如,Generator是由Iterator派生的Iterable是由基对象派生的。

因此,

Every iterator is an iterable, but not every iterable is an iterator. For example, [1, 2, 3] and range(10) are iterables, but not iterators. x = iter([1, 2, 3]) is an iterator and an iterable. A similar relationship exists between Iterator and Generator. Calling iter() on an iterator or a generator returns itself. Thus, if it is an iterator, then iter(it) is it is True. Under the hood, a list comprehension like [2 * x for x in nums] or a for loop like for x in nums:, acts as though iter() is called on the iterable (nums) and then iterates over nums using that iterator. Hence, all of the following are functionally equivalent (with, say, nums=[1, 2, 3]): for x in nums: for x in iter(nums): for x in iter(iter(nums)): for x in iter(iter(iter(iter(iter(nums))))):

iterable = [1, 2] 

iterator = iter(iterable)

print(iterator.__next__())   

print(iterator.__next__())   

so,

Iterable是一个可以循环的对象。例如,列表,字符串,元组等。 在iterable对象上使用iter函数将返回一个迭代器对象。 现在这个迭代器对象有一个名为__next__的方法(在Python 3中,或者在Python 2中只是next),通过它你可以访问iterable的每个元素。

所以, 以上代码的输出为:

1

2

以下是我在教授Python课程时使用的解释:

ITERABLE是:

任何可以循环的东西(例如,你可以循环一个字符串或文件)或 任何可以出现在for循环右边的东西:for x in iterable:…或 任何你可以用iter()调用并返回ITERATOR: iter(obj)或 一个定义__iter__的对象,该对象返回一个新的ITERATOR, 或者它可能有一个适合索引查找的__getitem__方法。

ITERATOR是一个对象:

在迭代过程中,state会记住它的位置, 使用__next__方法: 返回迭代中的下一个值 更新状态以指向下一个值 信号,当它完成时,引发StopIteration 并且它是可自迭代的(意味着它有一个返回self的__iter__方法)。

注:

Python 3中的__next__方法在Python 2中拼写为next,并且 内置函数next()在传递给它的对象上调用该方法。

例如:

>>> s = 'cat'      # s is an ITERABLE
                   # s is a str object that is immutable
                   # s has no state
                   # s has a __getitem__() method 

>>> t = iter(s)    # t is an ITERATOR
                   # t has state (it starts by pointing at the "c"
                   # t has a next() method and an __iter__() method

>>> next(t)        # the next() function returns the next value and advances the state
'c'
>>> next(t)        # the next() function returns the next value and advances
'a'
>>> next(t)        # the next() function returns the next value and advances
't'
>>> next(t)        # next() raises StopIteration to signal that iteration is complete
Traceback (most recent call last):
...
StopIteration

>>> iter(t) is t   # the iterator is self-iterable

Iterable:-可迭代的东西是可迭代的;比如序列,比如列表,字符串等等。 它也有__getitem__方法或__iter__方法。现在如果我们对该对象使用iter()函数,我们将得到一个迭代器。

迭代器:-当我们从iter()函数获得迭代器对象;我们调用__next__()方法(在python3中)或简单地调用next()(在python2中)来逐个获取元素。该类或该类的实例称为迭代器。

从文档:

迭代器的使用遍及并统一了Python。在后台,for语句在容器对象上调用iter()。该函数返回一个迭代器对象,该对象定义了__next__()方法,该方法每次访问容器中的一个元素。当没有更多的元素时,__next__()会引发一个StopIteration异常,告诉for循环终止。你可以使用next()内置函数调用__next__()方法;这个例子展示了它是如何工作的:

>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    next(it)
StopIteration

一个类的前:-

class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]


>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
...     print(char)
...
m
a
p
s

迭代对象有一个__iter__方法,每次都会实例化一个新的迭代器。 迭代器实现了一个__next__方法返回单个项,以及一个__iter__方法返回self。 因此,迭代器也是可迭代的,但可迭代的不是迭代器。

卢西亚诺·拉马略,流利的蟒蛇。