Python中列表和迭代器的区别是什么?

28 投票
6 回答
30574 浏览
提问于 2025-04-19 16:44

我正在阅读一本书,叫做《Think Python: How to think like a computer scientist》,书中提到在Python 3.x中,dict([list of tuples])会返回一个迭代器,而不是像Python 2.7那样返回一个列表

书里没有进一步解释这个问题,这让我有点困惑。特别是,我想知道:

  1. 迭代器和列表有什么不同?

  2. 返回一个迭代器有什么好处,而不是返回一个列表?

6 个回答

2

迭代器是一种可以逐个提供值的对象,但它不一定要和一个在内存中存储所有值的数据结构关联在一起。相比之下,列表是完全构建好的,并且存储在内存中的。简单来说,迭代器通常更节省内存,而且在性能上也往往比同样的数据以内存结构的形式创建要好,因为每个元素的计算可以在访问这个元素的时候进行,而不是提前计算,并且所有元素不需要同时存储在内存中。

5

迭代器是一种机制,可以让你用 for 循环来遍历一个列表或其他一些对象/值的集合。列表本身就实现了迭代器。不过,你也可以自己创建迭代器,比如返回数字序列、随机字符串等等。

当你返回一个迭代器时,其实就是在返回一个迭代对象;接收这个对象的代码并不知道它背后是哪个容器或者生成算法。

迭代器是懒惰的;它们只会在你请求的时候返回序列或列表中的下一个元素。因此,你可以用它们来实现无限的序列。

进一步阅读
迭代器类型
关于 for 循环的说明

5

这里有几个重要的定义:

  • 列表(List):完全存储在内存中,并且它也是一个迭代器——也就是说,你可以从一个元素移动到下一个元素。
  • 可迭代对象(Iterable):任何实现了迭代器协议的对象——也就是说,它允许你从一个元素移动到下一个元素。它可以使用存储在内存中的数据,也可以是一个文件,或者每一步都可以通过计算得出。

很多东西是可迭代的,但并不是列表,所有的列表都是可迭代的。

23

列表是一种数据结构,用来存储一系列的值。迭代器是一个对象,它提供了一种接口,可以通过 next 函数一次获取一个值。

可迭代对象是指那些提供了 __iter__ 方法的对象。当你把一个可迭代对象传给 iter 函数时,这个方法就会被调用。你通常不需要手动去做这件事;比如说,for 循环会自动处理这个过程。像这样的循环:

for x in [1,2,3]:
    print x

会自动调用列表的 __iter__ 方法。你也可以手动调用它,像这样:

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

或者更明确地这样:

for x in [1,2,3].__iter__():
    print x

一种观察它们之间区别的方法是从一个列表创建 两个 迭代器。

l = [1, 2, 3, 4, 5]
i1 = iter(l)
i2 = iter(l)
print next(i1)   # 1
print next(i1)   # 2
print next(i2)   # 1 again; i2 is separate from i1
print l          # [1, 2, 3, 4, 5]; l is unaffected by i1 or i2
48

首先,你的书是错的(或者你理解错了):

>>> dict([(1, 2), (3, 4), (5, 6)])
{1: 2, 3: 4, 5: 6}

正如你所看到的,dict([元组列表]) 在 Python 2.x 和 3.x 中都会返回一个字典。

列表和迭代器之间的根本区别在于,列表是包含了一定数量的对象,并且这些对象是有特定顺序的——所以你可以从中间的某个位置取出一个对象:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list[3]
'd'

... 而迭代器是生成了一定数量的对象,这些对象也是有特定顺序的,通常是在你需要的时候动态创建:

>>> my_iter = iter(range(1000000000000))
>>> my_iter
<range_iterator object at 0x7fa291c22600>
>>> next(my_iter)
0
>>> next(my_iter)
1
>>> next(my_iter)
2

我在这里使用 next() 来做演示;在实际代码中,通常会用 for 循环来遍历一个迭代器:

for x in my_iter:
    # do something with x

注意这个权衡:如果你有一个包含万亿个整数的列表,它会占用比大多数机器可用内存还要多的空间,这使得迭代器在效率上更胜一筹……但代价是你不能随便从中间取出一个对象:

>>> my_iter[37104]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'range_iterator' object is not subscriptable

撰写回答