【问题标题】:Python generator objects: __sizeof__()Python 生成器对象:__sizeof__()
【发布时间】:2012-09-10 18:22:46
【问题描述】:

这可能是一个愚蠢的问题,但我还是会问。我有一个生成器对象:

>>> 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

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

【问题讨论】:

  • 您可能还对sys.getsizeof() 感兴趣。它还考虑了 gc 开销(如果这对您很重要),并且不那么骇人听闻。
  • @mhawke:实际上,OP 甚至对__sizeof__ 都不感兴趣! :)
  • @NedBatchelder:是的,你是对的!

标签: python generator internals


【解决方案1】:

__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)

但请注意,耗尽发电机。

【讨论】:

  • 确实可以有无限的生成器或非确定性的生成器
【解决方案2】:

正如在其他答案中所说,__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

【讨论】:

  • 感谢 length_hint。 len(list(it)) 也使用迭代器,但 length_hint 没有。
  • @root 是的,list 使用它,转换为列表(需要一些内存),然后才计算创建列表的长度。而length_hint 是专门为列表迭代器对象实现的方法。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    len(list(gen()))
    

    正如其他发帖人所说,__sizeof__() 是衡量某物占用多少内存(一个您可能很少需要的低级概念),而不是它的长度(这不是生成器的一个特性,因为无法保证它们有可数的长度)。

    【讨论】:

      【解决方案5】:

      @Martijn Pieters 你也可以重写 sizeof() 函数,我们可以实现我们在这里尝试做的事情。但它不适用于某些数据类型,如 int 或 float。

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

      所以这里对于int或float,如果类型是int或float,我们也可以放置一些转义函数。

      【讨论】:

        猜你喜欢
        • 2013-01-05
        • 2010-10-31
        • 2019-10-18
        • 2020-03-09
        • 2017-07-24
        • 2015-03-03
        • 2022-01-15
        • 2010-11-19
        • 2012-07-25
        相关资源
        最近更新 更多