2012-09-18 5 views
11

これは愚かな質問かもしれませんが、とにかく質問します。私はジェネレータオブジェクトを持っている:Pythonジェネレータオブジェクト:__sizeof __()

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

私はそれがサイズだ測ることができます。

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

...しかしobj.__sizeof__()は同じまま:

>>> obj.__sizeof__() 
24 

発電機が消費されます。と言われています。

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

誰かが私を啓発することができれば、私は感謝するだろう:それは私が期待どおりに動作文字列で

+1

ます。また、[ 'sys.getsizeof()'](http://docs.python.org/library/sys.html#sys.getsizeofに興味があるかもしれません:たとえばlistiteratorについて対応__length_hint__方法があります)。それはまたgcのオーバーヘッドを考慮します(それはあなたにとって重要です)。 – mhawke

+0

@mhawke:実際には、OPは '__sizeof__'にも興味がありませんでした! :) –

+0

@NedBatchelder:はい、そうです! – mhawke

答えて

23

__sizeof__()あなたはそう思わないと思います。このメソッドは、ジェネレータが返すアイテムの数ではなく、指定されたオブジェクトの内部サイズをバイト単位で返します。

Pythonは、ジェネレータのサイズを事前に知ることができません。例えば、次の無限の発電ください(例を、カウンタを作成するためのより良い方法があります):

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

発電機が無限であること。割り当て可能なサイズはありません。しかし、ジェネレータオブジェクト自体がメモリを取る:

>>> count.__sizeof__() 
88 

あなたは通常、あなたはまた、ガベージコレクタのオーバーヘッドを追加しsys.getsizeof() functionにあることを残し__sizeof__()呼び出すことはありません。

あなたがを知っ場合ジェネレータは有限であることを行っている、あなたは、それが返されますどのように多くのアイテムの使用を知ってを持っている

sum(1 for item in generator) 

それ排気発電ことに注意してください。

+1

実際に無限のジェネレータや非決定論的ジェネレータを使用することは可能です –

+0

合理的な音:)ありがとうございます。 – root

1

__sizeof__は、ジェネレータの長さではなく、バイト単位でオブジェクトのメモリサイズを返します。これは、ジェネレータが無期限に増加するため、正面から判断できません。

0

あなたが作成した発電機が「有限」であることが確実な場合には(要素の可算数を持っている)、あなたはしばらくの間は、あなたが望む結果を得るために、以下を使用することができます待っている気にしない:

len(list(gen())) 

__sizeof__()は、何かが覚えているメモリの量の尺度です(おそらくめったに必要ないはずの非常に低いレベルの概念です)。長さではありません(発電機の特徴ではありません。長さは数えます)。

6

他の回答で述べたように、__sizeof__は別のものを返します。

一部のイテレータでは、返されない要素の数を返すメソッドしかありません。

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

__length_hint__に感謝します。また、len(list(it))はイテレータを消費しますが、__length_hint__は消費しません。 – root

+0

@rootはい、 'list'はそれを消費し、リストに変換し(メモリを使います)、作成されたリストの長さだけを計算します。 'length_hint'はリストイテレータオブジェクトのためだけに特別に実装されたメソッドです。 – ovgolovin

関連する問題