混乱于Python列表:它们是迭代器还是不是迭代器?

12 浏览
0 Comments

混乱于Python列表:它们是迭代器还是不是迭代器?

我正在学习《Python速查手册》(Alex Marteli著),这本书提到任何具有next()方法的对象都是(或至少可以被用作)迭代器。书中还提到,大多数迭代器都是通过隐式或显式调用一个名为iter的方法来构建的。

在读到这段内容后,我有一种尝试的冲动。我打开了一个Python 2.7.3解释器,并进行了如下操作:

>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for number in range(0, 10):
...     print x.next()

然而结果是这样的:

Traceback (most recent call last):
  File "", line 2, in 
AttributeError: 'list' object has no attribute 'next'

混淆不解之际,我尝试通过dir(x)来研究x对象的结构,我注意到它有一个__iter__函数对象。所以我想出来了一个办法,只要它支持这种类型的接口,它就可以被用作一个迭代器。

所以当我再次尝试时,这次稍微有些不同,试图做到这一点:

>>> _temp_iter = next(x)

我得到了这个错误:

Traceback (most recent call last):
  File "", line 1, in 
TypeError: list object is not an iterator

但是一个列表怎么可能不是一个迭代器呢?因为它看起来支持这个接口,并且在以下上下文中肯定可以被用作一个迭代器:

>>> for number in x:
...     print x

有人能帮我澄清一下这个问题吗?

0
0 Comments

Python中的列表是可迭代对象(iterable),可以通过使用迭代器(iterator)来对列表进行多次遍历。迭代器是一种表示数据流的对象,它实现了迭代器协议(iterator protocol),包括`__iter__`方法和`next`方法。通过多次调用迭代器的`next()`方法,可以依次返回数据流中的每个元素。当没有更多的数据可用时,迭代器对象将耗尽,并且对其`next()`方法的进一步调用将引发StopIteration异常。

相反,可迭代对象实现了`__iter__`方法,当调用该方法时,返回一个迭代器,允许对其数据进行多次遍历。可迭代对象是可重复使用的,一旦耗尽,可以再次进行迭代。可以使用`iter`函数将可迭代对象转换为迭代器。

如果你有一个列表(可迭代对象),你可以这样做:

l = [1, 2, 3, 4]
for i in l:
    print(i, end=' ')
# 输出:1 2 3 4
for i in l:
    print(i, end=' ')
# 输出:1 2 3 4

如果将列表转换为迭代器:

il = l.__iter__()  # 等同于 iter(l)
for i in il:
    print(i, end=' ')
# 输出:1 2 3 4
for i in il:
    print(i, end=' ')
# 没有输出

出现混淆的原因是,当使用迭代器对列表进行遍历后,再次使用同一个迭代器进行遍历时,并没有输出任何结果。这是因为迭代器对象已经耗尽,再次调用其`next()`方法时并没有可用的数据。

解决这个问题的方法是重新创建一个迭代器对象,或者将列表转换为可迭代对象再进行遍历。

il = iter(l)  # 创建新的迭代器对象
for i in il:
    print(i, end=' ')
# 输出:1 2 3 4
for i in il:
    print(i, end=' ')
# 输出:1 2 3 4

或者直接使用可迭代对象进行遍历:

l = [1, 2, 3, 4]
for i in l:
    print(i, end=' ')
# 输出:1 2 3 4
for i in l:
    print(i, end=' ')
# 输出:1 2 3 4

通过理解列表作为可迭代对象和迭代器之间的区别,以及如何正确使用它们,可以避免对列表遍历时出现的混淆。

0
0 Comments

在Python中,列表(list)和迭代器(iterator)是两个不同的概念。列表是一种可迭代对象(iterable),而迭代器是可迭代对象的一个特殊实例。

上述代码中的问题是对列表进行迭代时出现的。在使用for循环迭代列表时,会发现不能使用列表的next()方法。为了解决这个问题,需要将列表转换为迭代器,可以使用iter()函数来实现转换。通过将列表传递给iter()函数,可以得到一个迭代器对象。

下面是解决这个问题的代码片段:

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
it = iter(x)
for i in range(10):
    it.next()

在这个例子中,先将列表x转换为迭代器it,然后通过for循环迭代该迭代器。通过调用next()方法,可以获取迭代器的下一个元素。

另外,可以使用isinstance()函数来检查一个对象是否是迭代器或可迭代对象。在上述代码中,使用isinstance()函数检查列表和迭代器的类型。可以看到,列表是可迭代对象,而迭代器既是可迭代对象也是迭代器。

下面是检查对象是否为迭代器或可迭代对象的代码片段:

import collections
isinstance(x, collections.Iterator)  # 检查x是否是迭代器
isinstance(x, collections.Iterable)  # 检查x是否是可迭代对象
isinstance(it, collections.Iterable)  # 检查it是否是可迭代对象
isinstance(it, collections.Iterator)  # 检查it是否是迭代器

通过使用isinstance()函数,可以确定一个对象的类型是否符合预期。

列表和迭代器是两个不同的概念。在使用for循环迭代列表时,需要先将列表转换为迭代器。通过使用iter()函数将列表转换为迭代器对象,可以解决这个问题。同时,使用isinstance()函数可以检查一个对象是否是迭代器或可迭代对象。

0
0 Comments

在Python中,列表(list)是可迭代的(iterable),但它们本身不是迭代器(iterator)。可以通过将列表传递给iter()函数来隐式或显式地获取迭代器(iterator),但它们本身并不是迭代器。

需要注意的是,所有的迭代器(well-behaved)都是可迭代的,它们的next方法只是返回self,因此可以调用iter(iter(iter(iter(x))))并得到与iter(x)相同的结果。这就是为什么for循环既可以用于可迭代对象(iterables)也可以用于迭代器(iterators),而无需类型检查(忽略性能优化)。

为什么设计成可迭代对象(iterables)不是迭代器(iterators)呢?因为迭代器不支持随机访问。

关于列表类(list)的实现,虽然list类的定义中没有明确继承可迭代对象,但实际上它是可迭代的。这是因为Python在实现列表类时,内部实现了__iter__方法,该方法返回一个迭代器对象。所以虽然列表类没有直接继承可迭代对象,但它仍然可以被视为可迭代的对象。

总结一下,Python的列表是可迭代的,但不是迭代器。它们可以通过iter()函数获取迭代器。列表类虽然没有直接继承可迭代对象,但实际上它是可迭代的,因为它实现了__iter__方法返回一个迭代器对象。

0