2017-02-05 6 views
3

私はPythonで動的配列の実装を作成しています(組み込みのリストクラスに似ています)。容量の増加を監視する必要があります(制限時間は2倍になります)。到達した)。そのために私は以下のコードを持っていますが、出力は奇妙です。 sys.getsizeof()は私のクラスの__sizeof__()を決して呼び出さないようです。テストの目的のために、私は__sizeof__()0に返すようにしていますが、sys.getsizeof()としてはゼロではありません。__sizeof__がsys.getsizeofによって呼び出されない

キャッチは何ですか?

import ctypes 

class DynamicArray(object): 
    ''' 
    DYNAMIC ARRAY CLASS (Similar to Python List) 
    ''' 

    def __init__(self): 
     self.n = 0 # Count actual elements (Default is 0) 
     self.capacity = 1 # Default Capacity 
     self.A = self.make_array(self.capacity) 

    def __len__(self): 
     """ 
     Return number of elements sorted in array 
     """ 
     return self.n 

    def __getitem__(self,k): 
     """ 
     Return element at index k 
     """ 
     if not 0 <= k <self.n: 
      return IndexError('K is out of bounds!') # Check it k index is in bounds of array 

     return self.A[k] #Retrieve from array at index k 

    def append(self, ele): 
     """ 
     Add element to end of the array 
     """ 
     if self.n == self.capacity: 
      self._resize(2*self.capacity) #Double capacity if not enough room 

     self.A[self.n] = ele #Set self.n index to element 
     self.n += 1 

    def _resize(self,new_cap): 
     """ 
     Resize internal array to capacity new_cap 
     """ 
     print("resize called!") 

     B = self.make_array(new_cap) # New bigger array 

     for k in range(self.n): # Reference all existing values 
      B[k] = self.A[k] 

     self.A = B # Call A the new bigger array 
     self.capacity = new_cap # Reset the capacity 

    def make_array(self,new_cap): 
     """ 
     Returns a new array with new_cap capacity 
     """ 
     return (new_cap * ctypes.py_object)() 

    def __sizeof__(self): 
     return 0 

サイズ変更をテストするために使用されるコード:

arr2 = DynamicArray() 

import sys 

for i in range(100): 
    print(len(arr2), " ", sys.getsizeof(arr2)) 
    arr2.append(i) 

そして出力:

0 24 
1 24 
resize called! 
2 24 
resize called! 
3 24 
4 24 
resize called! 
5 24 
6 24 
7 24 
8 24 
resize called! 
9 24 
10 24 
11 24 
12 24 
13 24 
14 24 
15 24 
16 24 
resize called! 
17 24 
18 24 
19 24 
20 24 
21 24 
22 24 
23 24 
24 24 
25 24 
26 24 
27 24 
28 24 
29 24 
30 24 
31 24 
32 24 
resize called! 
33 24 
34 24 
35 24 
36 24 
37 24 
38 24 
39 24 
40 24 
41 24 
42 24 
43 24 
44 24 
45 24 
46 24 
47 24 
48 24 
49 24 
50 24 
51 24 
52 24 
53 24 
54 24 
55 24 
56 24 
57 24 
58 24 
59 24 
60 24 
61 24 
62 24 
63 24 
64 24 
resize called! 
65 24 
66 24 
67 24 
68 24 
69 24 
70 24 
71 24 
72 24 
73 24 
74 24 
75 24 
76 24 
77 24 
78 24 
79 24 
80 24 
81 24 
82 24 
83 24 
84 24 
85 24 
86 24 
87 24 
88 24 
89 24 
90 24 
91 24 
92 24 
93 24 
94 24 
95 24 
96 24 
97 24 
98 24 
99 24 

答えて

5

あなた__sizeof__が呼び出さなっている、それはちょうどそれにガベージコレクタのオーバーヘッドを追加していますそれが結果がゼロでない理由です。

From the docs on sys.getsizeof

getsizeof()は、オブジェクトの__sizeof__メソッドを呼び出して、オブジェクトがガベージコレクタによって管理されている場合、追加のガベージコレクタのオーバーヘッドを追加します。 0を返す

は、あなたはそれが難しいあなたの自己は、あなたが常にバック(0 +オーバーヘッド)と同じ結果を得ることができますので、それを呼び出していることを理解できるようにするための1つの方法です。

ダイナミック配列の内容に基づいてサイズを返し、変更を確認します。さらに詳述すると


:ガベージコレクタによって使用さ

/* add gc_head size */ 
if (PyObject_IS_GC(o)) 
    return ((size_t)size) + sizeof(PyGC_Head); 
return (size_t)size; 

各オブジェクトをCPythonのではPyGC_head構造体that gets addedでそれに取り付けられたいくつかの管理情報を有しています。

がオブジェクトに必要な追加メモリを表すため、これが全体のサイズに追加されるのはおそらく理由でしょう。 Pythonレベルでは、ごみの収集について心配する必要はなく、すべてを魔法のように扱う必要はありませんが、オブジェクトのサイズに関する情報を求めるときは、錯覚を生き残るために正しい結果を犠牲にするべきではありません。

+3

+1あなたの '__sizeof __()'がゼロ以外の値を返すようにすると、観測値がその数値だけインクリメントされて表示されます。 – Leon

+0

@レーオンちょうど答えに追加されました:-) –

+0

ガベージコレクタ_overhead_ ?私は全く理解できないのか分かりません。どのようなオーバーヘッドですか?そして、なぜオーバーヘッドを整数として追加するべきですか?ガベージコレクションは自動的かつ暗黙的で魔法的で妨げにならないと思われますか? :) – dotslash

関連する問題