Python生成器对象:__sizeof __()

时间:2012-09-18 13:16:24

标签: python generator internals

这可能是一个愚蠢的问题,但无论如何我都会问。我有一个生成器对象:

>>> def gen():
...     for i in range(10):
...         yield i
...         
>>> obj=gen()

我可以测量它的大小:

>>> obj.__sizeof__()
24

据说发电机被消耗了:

>>> for i in obj:
...     print i
...     
0
1
2
3
4
5
6
7
8
9
>>> obj.__sizeof__()
24

...但obj.__sizeof__()保持不变。

使用字符串可以按预期工作:

>>> 'longstring'.__sizeof__()
34
>>> 'str'.__sizeof__()
27

如果有人能够启发我,我将感激不尽。

5 个答案:

答案 0 :(得分:27)

__sizeof__()没有按照您的想法行事。该方法返回给定对象的内部大小(以字节为单位),而不是生成器将返回的项目数。

Python无法预先知道生成器的大小。以下面的无限生成器为例(例如,有更好的方法来创建计数器):

def count():
    count = 0
    while True:
        yield count
        count += 1

那个发电机是无止境的;没有可分配的大小。然而,生成器对象本身需要记忆:

>>> count.__sizeof__()
88

您通常不会将__sizeof__()留给sys.getsizeof() function,这也会增加垃圾收集器的开销。

如果您知道某个生成器将是有限的,并且您 知道它返回了多少项,请使用:

sum(1 for item in generator)

但请注意耗尽生成器。

答案 1 :(得分:6)

如其他答案所述,__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

答案 2 :(得分:1)

__sizeof__以字节为单位返回对象的内存大小,而不是生成器的长度,由于生成器可以无限增长,因此无法预先确定。

答案 3 :(得分:0)

如果您确定您创建的生成器是“有限的”(具有可数数量的元素)并且您不介意等待一段时间,您可以使用以下内容来获得您想要的内容:

len(list(gen()))

正如其他海报所说,__sizeof__()衡量一些内存占用了多少(一个你可能很少需要的低级别概念),而不是它的长度(这不是发电机的一个特征,因为它有不保证他们有可数的长度。)

答案 4 :(得分:0)

@Martijn Pieters您可能还不愿意使用 sizeof ()函数,我们可以在此处实现此功能。但是它不适用于int或float这类数据类型。

class GetLen():
    def __sizeof__(self, x):
        return len(x)

因此对于int或float,如果类型为int或float,我们还可以放置一些转义函数。