提问人:henveloper 提问时间:11/5/2023 最后编辑:wjandreahenveloper 更新时间:11/5/2023 访问量:84
什么决定了发电机的尺寸?
What determines the size of a generator?
问:
import sys
num_gen = (num for num in range(1))
print(sys.getsizeof(num_gen))
num_gen = (num for num in range(100))
print(sys.getsizeof(num_gen))
num_gen = (num+1 for num in range(100))
print(sys.getsizeof(num_gen))
num_gen = (num+1+1 for num in range(100))
print(sys.getsizeof(num_gen))
num_gen = (num+num for num in range(100))
print(sys.getsizeof(num_gen))
num_gen = (num+num+1 for num in range(100))
print(sys.getsizeof(num_gen))
输出
200
200
208
208
208
208
为什么下面的 4 个生成器多用了 8 个字节?
答:
1赞
chepner
11/5/2023
#1
生成器对象的“大小”不是它将生成的元素(如列表或其他类型的序列)的函数,而是它执行以生成元素的代码的函数。
评论
2赞
Jeff Mercado
11/5/2023
还可能发现在向表达式正文添加更多代码时需要更多代码的阈值,并填充以进行对齐。表达式正文中的附加 和 将需要额外的指令,并且对于某些版本来说,可能需要额外的开销。+1
+num
0赞
Brian61354270
11/5/2023
@JeffMercado AFAIK,生成器对象的大小与其代码对象的大小无关。生成器本身只需要存储一个指向它的指针。如果查看问题中的每个生成器,您可以看到代码对象大小在报告相同 .如果你看一下,你可以看到指令的数量变化比可以解释的要多。num_gen.gi_code
sys.getsizeof(num_size)
len(g.gi_code.co_code)
sys.getsizeof(num_gen)
0赞
Jeff Mercado
11/5/2023
@Brian61354270嗯,这似乎是我系统上表达式复杂性的函数。3.11.5 x64 i.stack.imgur.com/njeFA.png 如果你看一下拆卸,可能会计算出它的数学。
0赞
Brian61354270
11/5/2023
@JeffMercado我可以复制这些结果。但有趣的是,导致差异的不是代码对象大小。如果你创建一个像 这样的大体,即使代码对象有几千字节,你仍然会得到。如果以不影响指令数的方式在括号周围移动,则大小也会发生变化。而这只发生在 CPython 3.11+ 中。CPython 3.{8.9.10} 无论主体复杂程度如何,都不会看到生成器对象的大小有任何变化。AA+AB+AC+...+ZY+ZZ for _ in range(l)
sys.getsizeof(num_gen) == 200
0赞
Brian61354270
11/5/2023
我猜这是 CPython 3.11/12 引入的改进异常回溯的产物。生成器可能需要存储有关括号/子表达式布局的额外信息,以便知道在发生异常时用 s 下划线的正文的哪个部分。^
评论
112
104
192
200
sys.getsizeof