roo*_*oot 14 python generator internals
这可能是一个愚蠢的问题,但无论如何我都会问.我有一个生成器对象:
>>> def gen():
... for i in range(10):
... yield i
...
>>> obj=gen()
Run Code Online (Sandbox Code Playgroud)
我可以测量它的大小:
>>> obj.__sizeof__()
24
Run Code Online (Sandbox Code Playgroud)
据说发电机被消耗掉了:
>>> for i in obj:
... print i
...
0
1
2
3
4
5
6
7
8
9
>>> obj.__sizeof__()
24
Run Code Online (Sandbox Code Playgroud)
......但obj.__sizeof__()仍然是一样的.
使用字符串它按预期工作:
>>> 'longstring'.__sizeof__()
34
>>> 'str'.__sizeof__()
27
Run Code Online (Sandbox Code Playgroud)
如果有人能够启发我,我将感激不尽.
Mar*_*ers 28
__sizeof__()不会做你认为它做的事情.该方法返回给定对象的内部大小(以字节为单位),而不是生成器要返回的项目数.
Python无法事先知道生成器的大小.以下面的无限生成器为例(例如,有更好的方法来创建计数器):
def count():
count = 0
while True:
yield count
count += 1
Run Code Online (Sandbox Code Playgroud)
那台发电机是无止境的 没有可分配的大小.然而,生成器对象本身占用内存:
>>> count.__sizeof__()
88
Run Code Online (Sandbox Code Playgroud)
你通常不会叫__sizeof__()你把它留给sys.getsizeof()函数,这也增加了垃圾收集器的开销.
如果您知道生成器将是有限的并且您必须知道它返回了多少项,请使用:
sum(1 for item in generator)
Run Code Online (Sandbox Code Playgroud)
但请注意,这会耗尽发电机.
正如在其他答案中所说,__sizeof__返回一个不同的东西.
只有一些迭代器具有返回未返回元素数的方法.例如listiterator有一个相应的__length_hint__方法:
>>> L = [1,2,3,4,5]
>>> it = iter(L)
>>> it
<listiterator object at 0x00E65350>
>>> it.__length_hint__()
5
>>> help(it.__length_hint__)
Help on built-in function __length_hint__:
__length_hint__(...)
Private method returning an estimate of len(list(it)).
>>> it.next()
1
>>> it.__length_hint__()
4
Run Code Online (Sandbox Code Playgroud)