Python的迭代是否真的将所有值存储在内存中?

kis*_*ssg 2 python iterable

我正在阅读e-satisf'回答"yield"关键字在Python中的作用?.他说:

这些迭代很方便,因为你可以根据自己的意愿阅读它们,但是你将所有的值存储在内存中,当你有很多值时,这并不总是你想要的

我真的不同意.但我不能在那里发表评论.

然后是这个问题:Python的迭代是否真的将所有值存储在内存中?

我曾经这么认为.但是自从我昨天看到Python的详细文档以来,我改变了我的观点.

>>> import sys
>>> def gen(): 
...   n = 0                                                                                          
...   while n < 10:                                                                                 
...     yield n                                                                                     
...     n += 1
...
>>> a = [0,1,2,3,4,5,6,7,8,9]
>>> b = range(10)  # b is a range object, which is a iterable
>>> c = gen(10)    # c is a iterator, which is a iterable too
>>> sys.getsizeof(a)
144
>>> sys.getsizeof(b)
48
>>> sys.getsizeof(c)
72
>>> B = list(b)                                                                                     
>>> C = list(c)                                                                                     
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> B
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> C
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> sys.getsizeof(B)                                                                                
200                                                                                                
>>> sys.getsizeof(C)                                                                           
160
Run Code Online (Sandbox Code Playgroud)

我们错误地认为iterable将所有值存储在内存中,因为我们习惯在使用iterable时获取所有值.

我对吗?

Dun*_*can 6

在引用该答案时,您剥离了太多的上下文.它是专门在列表等迭代的上下文中制作的.生成器和yield关键字将在答案的下方单独介绍.

扩大你的报价:

您可以使用"for ... in ..."的所有内容都是可迭代的; 列表,字符串,文件......

这些迭代很方便,因为您可以根据需要阅读它们,但是您将所有值存储在内存中,当您拥有大量值时,这并不总是您想要的.

对于列表和字符串,声明是正确的,它们存储在内存中.但是对于文件是不正确的,因为您可以迭代文件而不将其全部存储在内存中.

python iterable可能会也可能不会将值存储在内存中.它逐步执行一个值,并且在每个步骤中它可以从内存中提取值,从头创建它,或从另一个源(如文件)中读取它.

range()是一个很好的例子:在Python 2.x中它预先生成所有值并将它们存储在内存中,在Python 3.x中它根据需要生成它们.两者都返回一个可迭代对象.