我正在尝试理解python中迭代器的概念,并在Python 3.5.2中尝试了这一点。
x = list(range(1000)) # size of x is 9112 bytes
y = iter(x) # size of y is 56 bytes
del x
x = list(y) # size of x is again 9112 bytes迭代器如何存储关于它必须生成的序列的信息?
它不包含所有元素,但即使在删除原始列表之后,我们仍然能够从迭代器中重新生成原始列表?
如果它不包含所有元素,那么即使在删除x之后,它如何知道哪个是下一个元素
发布于 2016-10-01 23:10:44
因为迭代器中存储了足够的细节,使它们能够生成序列的下一个元素,而不需要内存中的“下一个元素”。
为了理解到底发生了什么,让我们创建我们自己的伪迭代器
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对象,在内部存储x。x仍然存储,但不再使用名称x。
关于为什么getsizeof返回一个较小的大小,正如您所预期的那样,它应该大于或至少等于原始列表的大小。从文档中
sys.getsizeof( object,默认值)返回对象的字节大小。对象可以是任何类型的对象。所有内置对象都将返回正确的结果,但这不一定适用于第三方扩展,因为它是特定于实现的。
只考虑直接归因于对象的内存消耗,而不考虑它引用的对象的内存消耗。
如果给定,则当对象不提供检索大小的方法时,将返回默认值。否则将引发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不会自动删除y.x所指向的[1,2,3],即使它们的id显示它们都指向内存中的同一对象。
发布于 2016-10-01 23:21:03
据我所知,del x不会del内存中的值,因为y还在引用它。它是一种指针。X和y指的是相同的内存。
当您执行del x时,python将取消对x的引用并执行垃圾收集。
而通过执行x=list(y),您再次将内存指向x。
https://stackoverflow.com/questions/39807948
复制相似问题