迭代器、iterable和iteration到底是什么?

2024-04-24 10:28:56 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

下面是我在教授Python类时使用的解释:

ITERABLE是:

  • 可以循环的任何内容(即可以循环字符串或文件)或
  • 可以出现在for循环右侧的任何内容:for x in iterable: ...
  • 可以用iter()调用的任何返回迭代器的函数:iter(obj)
  • 一个定义__iter__的对象,它返回一个新的迭代器, 或者它可能有一个适合索引查找的__getitem__方法。

迭代器是一个对象:

  • 在迭代过程中记住它在哪里的状态
  • 使用__next__方法:
    • 返回迭代中的下一个值
    • 更新状态以指向下一个值
    • 通过提高StopIteration来发出信号
  • 这是自iterable(意味着它有一个返回__iter__self方法)。

注:

  • 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

上面的答案很好,但正如我所看到的,对于像我这样的人来说,不要过分强调区分。

此外,人们倾向于把“X是一个之前有__foo__()方法的对象”这样的定义放在前面,从而得到“太Pythonic”。这样的定义是正确的——它们基于duck类型哲学,但是当试图以简单的方式理解这个概念时,对方法的关注往往介于两者之间。

所以我添加了我的版本。


在自然语言中

  • 迭代是在一行元素中一次获取一个元素的过程。

在Python中

  • iterable是一个对象,好吧,iterable,简单地说,就是 它可以在迭代中使用,例如与for循环一起使用。怎样?通过使用迭代器。 我在下面解释。

  • 。。。而迭代器是一个定义如何实际操作的对象 迭代——特别是下一个元素是什么。所以它一定有 next()方法。

迭代器本身也是可iterable的,区别在于它们的__iter__()方法返回相同的对象(self),而不管以前对next()的调用是否使用了它的项。


那么,当Python解释器看到for x in obj:语句时,它会怎么想呢?

Look, a for loop. Looks like a job for an iterator... Let's get one. ... There's this obj guy, so let's ask him.

"Mr. obj, do you have your iterator?" (... calls iter(obj), which calls obj.__iter__(), which happily hands out a shiny new iterator _i.)

OK, that was easy... Let's start iterating then. (x = _i.next() ... x = _i.next()...)

由于obj先生成功地完成了这个测试(通过使用返回有效迭代器的特定方法),我们用形容词奖励他:您现在可以称他为“iterable先生obj”。

然而,在简单的情况下,您通常不会从分别使用iterator和iterable中获益。所以您只定义了一个对象,它也是它自己的迭代器。(Python并不真的在乎由obj发出的_i不是那么闪亮,而是obj本身。)

这就是为什么在我所见过的大多数例子中(以及那些让我一次又一次困惑的例子), 你可以看到:

class IterableExample(object):

    def __iter__(self):
        return self

    def next(self):
        pass

而不是

class Iterator(object):
    def next(self):
        pass

class Iterable(object):
    def __iter__(self):
        return Iterator()

不过,有些情况下,当迭代器与iterable分离时,您可以从中受益,例如当您希望有一行项,但有更多的“游标”时。例如,当您想使用“current”和“coming”元素时,可以为这两个元素分别使用迭代器。或者从一个巨大的列表中提取多个线程:每个线程都可以有自己的迭代器来遍历所有项。请参阅上面的@Raymond's@glglgl's答案。

想象一下你能做什么:

class SmartIterableExample(object):

    def create_iterator(self):
        # An amazingly powerful yet simple way to create arbitrary
        # iterator, utilizing object state (or not, if you are fan
        # of functional), magic and nuclear waste--no kittens hurt.
        pass    # don't forget to add the next() method

    def __iter__(self):
        return self.create_iterator()

注:

  • 我再重复一遍:迭代器不可迭代。迭代器不能用作 for循环中的“源”。for循环主要需要的是__iter__() (返回带有next()的内容)。

  • 当然,for不是唯一的迭代循环,所以上面的方法适用于其他一些循环 构造(while…)。

  • 迭代器的next()可以抛出StopIteration来停止迭代。不必, 不过,它可以永远迭代或使用其他方法。

  • 在上述“思维过程”中,_i并不真正存在。这个名字是我编的。

  • Python 3.x:next()方法(不是内置的)现在有了一个小小的变化 必须调用__next__()。是的,应该一直都是这样的。

  • 你也可以这样想:iterable有数据,迭代器拉下一个 项目

免责声明:我不是任何Python解释器的开发人员,所以我不知道解释器的“想法”。上面的思考仅仅是展示了我是如何从一个Python新手的其他解释、实验和真实体验中理解这个主题的。

迭代是一个通用术语,用来表示一个接一个地获取某物的每一项。无论何时使用显式或隐式循环遍历一组项,即迭代。

在Python中,iterable和iterator有特定的含义。

iterable是一个具有__iter__方法的对象,该方法返回一个迭代器,或者定义一个__getitem__方法,该方法可以从零开始获取顺序索引(当索引不再有效时,引发一个IndexError)。因此iterable是一个可以从中获取迭代器的对象。

迭代器是具有next(Python 2)或__next__(Python 3)方法的对象。

每当在Python中使用for循环、或map或列表理解等时,都会自动调用next方法以从迭代器中获取每个项,从而经历迭代的过程。

开始学习的好地方是iterators section of the tutorialiterator types section of the standard types page。了解基本知识后,尝试iterators section of the Functional Programming HOWTO

相关问题 更多 >