Python中列表和迭代器的区别是什么?
我正在阅读一本书,叫做《Think Python: How to think like a computer scientist》,书中提到在Python 3.x中,dict([list of tuples])
会返回一个迭代器
,而不是像Python 2.7那样返回一个列表
。
书里没有进一步解释这个问题,这让我有点困惑。特别是,我想知道:
迭代器和列表有什么不同?
返回一个迭代器有什么好处,而不是返回一个列表?
6 个回答
迭代器是一种可以逐个提供值的对象,但它不一定要和一个在内存中存储所有值的数据结构关联在一起。相比之下,列表是完全构建好的,并且存储在内存中的。简单来说,迭代器通常更节省内存,而且在性能上也往往比同样的数据以内存结构的形式创建要好,因为每个元素的计算可以在访问这个元素的时候进行,而不是提前计算,并且所有元素不需要同时存储在内存中。
迭代器是一种机制,可以让你用 for
循环来遍历一个列表或其他一些对象/值的集合。列表本身就实现了迭代器。不过,你也可以自己创建迭代器,比如返回数字序列、随机字符串等等。
当你返回一个迭代器时,其实就是在返回一个迭代对象;接收这个对象的代码并不知道它背后是哪个容器或者生成算法。
迭代器是懒惰的;它们只会在你请求的时候返回序列或列表中的下一个元素。因此,你可以用它们来实现无限的序列。
进一步阅读
迭代器类型
关于 for
循环的说明
这里有几个重要的定义:
- 列表(List):完全存储在内存中,并且它也是一个迭代器——也就是说,你可以从一个元素移动到下一个元素。
- 可迭代对象(Iterable):任何实现了迭代器协议的对象——也就是说,它允许你从一个元素移动到下一个元素。它可以使用存储在内存中的数据,也可以是一个文件,或者每一步都可以通过计算得出。
很多东西是可迭代的,但并不是列表,所有的列表都是可迭代的。
列表是一种数据结构,用来存储一系列的值。迭代器是一个对象,它提供了一种接口,可以通过 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
首先,你的书是错的(或者你理解错了):
>>> 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