gpt4 book ai didi

python - python中生成器对象的大小

转载 作者:太空宇宙 更新时间:2023-11-03 12:59:29 25 4
gpt4 key购买 nike

对于下面的代码:

import sys
x=(i for i in range(1,11))
print x


print 'Before starting iterating generator size is' ,sys.getsizeof(x)

print 'For first time'
for i in x:
print i

print 'For second time , does not print anything'
for i in x:
print i # does not print anything

print 'After iterating generator size is' ,sys.getsizeof(x)

输出是:

<generator object <genexpr> at 0x014C1A80>
Before starting iterating generator size is 40
For first time
1
2
3
4
5
6
7
8
9
10
For second time
After iterating generator size is 40

最初生成器对象的大小是40,当我完成迭代时它仍然是40。但是没有从第二个循环中引用任何元素。

为什么生成器对象在创建时和完成迭代时占用相同的内存?

最佳答案

生成器在内存中占用的空间只是簿记信息。其中保留了对框架对象的引用(对正在运行的 Python 代码的管理,例如 locals),无论它是否正在运行,并且保留了对代码对象的引用。仅此而已:

>>> x=(i for i in range(1,11))
>>> dir(x)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
>>> x.gi_frame
<frame object at 0x1053b4ad0>
>>> x.gi_running
0
>>> x.gi_code
<code object <genexpr> at 0x1051af5b0, file "<stdin>", line 1>

这只是 3 个引用,加上常用的 Python 对象类型信息(想想引用计数)和一个弱引用列表;所以这大约是 4 个指针,一个整数和一个结构,在你的系统上占用 40 个字节(在我的系统上,64 位 OS X,它是 80 个字节)。 sys.getsizeof() 报告 C 中实现的结构的大小只是,它不会递归指针。

因此,当您运行生成器时,内存量不会改变。引用的帧可能会改变使用的内存量(如果生成器表达式向一端或另一端引用大对象)但是您不会看到 sys.getsizeof() 的结果生成器对象;改为查看框架局部变量:

>>> next(x)
1
>>> x.gi_frame.f_locals
{'i': 1, '.0': <listiterator object at 0x105339dd0>}

.0 对象是生成器在 for 循环中使用的 range() 迭代器,ifor 循环目标。 listiterator 是另一个可迭代对象,它具有对生成的列表 range() 的私有(private)引用以及一个位置计数器,因此它可以在您每次询问时生成下一个元素到。

您不能查询生成器的元素大小;它们无论如何都会根据需要生成元素,您无法先验地“知道”它们将生成多少,也不知道它们在运行后生成了多少。 sys.getsizeof() 肯定不会告诉你;无论如何,它都是一种测量内存占用量的工具,如果您想知道占用量,则必须递归地测量所有引用的对象。

可以从框架中看到生成器已完成运行;一旦完成,它就会被清除:

>>> x.gi_frame
<frame object at 0x1053b4ad0>
>>> list(x)
[2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x.gi_frame is None
True

所以最后,用于生成器的内存驻留在框架中的结构中(局部变量,也可能是全局变量,这些命名空间中的每个对象都可能再次引用其他对象),并且当生成器完成时,框架被清除并且生成器 .gi_frame 指针更改为指向 None 单例,如果引用计数已降至 0,则将清除该帧。

所有这些只适用于生成器,一般不适用于可迭代对象;生成器是 Python 代码,因此可以进行如此深入的反省。

关于python - python中生成器对象的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27794267/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com