因为迭代器有足够的细节存储在它们中,使它们能够生成序列的下一个元素,而不在内存中具有“下一个元素”。
明白什么是对,让我们创造我们自己的假迭代
class Fakeiterator:
def __init__(self, range_list):
self.current = range_list[0]
self.high = range_list[-1]
def __iter__(self):
return self
def __next__(self):
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
在我们__init__
方法,我们已经储存足够的细节去(起点和我们的迭代的终点),使我们产生下一个但实际上并没有将它存储在内存中。至于我们有这个信息,即使我们假定有一个包含2000元,我们只需要知道的起点和终点在我们__next__
方法随时
我们在迭代器的下一个元素问列表,迭代器只需增加当前的计数器并将其还给我们即可。
让测试我们的迭代器:
>>> x = list(range(5))
>>> y = Fakeiterator(x)
>>> del x
>>> list(y)
[0, 1, 2, 3, 4]
>>>
的list
构造反复调用__next__
直到StopIteration
是由我们的迭代提出,这就是在那里当前元素比我们存储在创建的最大元素高点迭代器。
但在你的情况下调用列表iter(x)
,返回list_iterator
对象STORES X内部。 x
仍然存储,但不是名称x
了。
为什么getsizeof
返回一个较小的大小,正如您所期望的那样,该大小应该大于或等于原始列表的大小。从文档
sys.getsizeof(object [,default])以 字节返回对象的大小。该对象可以是任何类型的对象。所有内置对象 都会返回正确的结果,但这不一定适用于 第三方扩展,因为它是特定于实现的。
只有直接归因于该对象的内存消耗是 的原因,而不是它引用的对象的内存消耗。
如果给出,如果对象没有提供 意味着检索大小,将返回默认值。否则会引发TypeError。
getsizeof()调用对象的的sizeof方法,如果目的是通过 垃圾收集器管理增加了一个附加的 垃圾收集器的开销。
为了证明让我们写一个快速脚本
import sys
x = [1, 2, 3]
print(sys.getsizeof(x))
class storex():
def __init__(self, param):
self.param = param
y = storex(x)
print(sys.getsizeof(y))
print(y.param, sys.getsizeof(y.param))
当你运行该脚本。这是输出(在我的机器上,但它应该是与你相同),即使
88
56
[1, 2, 3] 88
列表[1, 2, 2]
是88个字节长,当我们把它存储为的storex
属性它不会自动使storex
变得比它大。因为storex
引用它。它不是storex
一部分直接
但上打印y.param
的大小,我们可以看到,它仍然是大小为原[1, 2, 3]
列表
而且del
不会删除内存中的对象,它只是解除绑定相同名称x
所以x不会引用内存中的任何对象。 x的值才会被丢弃(垃圾回收)时,有它没有提及再次
这里是我的意思
>>> x = [1,2,3]
>>> class y: pass
...
>>> y.x = x
>>> id(x), id(y.x)
(140177507371016, 140177507371016)
>>> del x
>>> id(y.x)
140177507371016
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>>
删除x
不会自动删除[1,2,3]
这y.x
点示范即使他们的id表明他们都指向内存中的同一个对象。
简短的回答....因为它有足够的信息封装在它里面重新创建原始序列...当你消耗它 – danidee