__sizeof__没有被sys.getsizeof调用

时间:2017-02-05 11:14:06

标签: python python-3.x class

我在Python中编写动态数组实现(类似于内置列表类),我需要观察容量的增长(每次达到限制时都会增加一倍)。为此,我有以下代码,但输出很奇怪。看起来sys.getsizeof()从未调用过我的班级__sizeof__()。出于测试目的,我将__sizeof__()返回0,但根据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

1 个答案:

答案 0 :(得分:5)

你的__sizeof__ 调用,它只是向它添加垃圾收集器开销,这就是结果不为零的原因。

From the docs on sys.getsizeof

  

getsizeof()调用对象的__sizeof__方法,如果对象由垃圾收集器管理,则会增加额外的垃圾收集器开销。

返回0是一种让你自己很难理解它被调用的方法,因为你总会得到相同的结果(0 +开销)。

根据动态数组的内容返回一个大小,以查看它的变化。

进一步阐述:

CPython中的每个对象都在PyGC_head结构that gets added中附加了一些管理信息:

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

垃圾收集器使用的。

为什么将此添加到整体大小可能是因为 表示对象所需的额外内存。在Python级别,您不需要担心垃圾的收集并将其视为魔法,但是,当要求获取有关对象大小的信息时,您不应该牺牲正确的结果来保持幻觉。< / p>