__sizeof__没有被sys.getsizeof调用

ank*_*981 3 python class python-3.x

我正在用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
Run Code Online (Sandbox Code Playgroud)

用于测试调整大小的代码:

arr2 = DynamicArray()

import sys

for i in range(100):
    print(len(arr2), " ", sys.getsizeof(arr2))
    arr2.append(i)
Run Code Online (Sandbox Code Playgroud)

并输出:

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
Run Code Online (Sandbox Code Playgroud)

Jim*_*ard 5

__sizeof__ 获取调用,它只是增加垃圾收集开销它这就是为什么结果不是零.

来自以下文档sys.getsizeof:

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

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

返回基于动态数组内容的大小以查看其更改.


进一步阐述:

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

/* add gc_head size */
if (PyObject_IS_GC(o))
    return ((size_t)size) + sizeof(PyGC_Head);
return (size_t)size;
Run Code Online (Sandbox Code Playgroud)

垃圾收集器使用的.

为什么将它添加到整体大小可能是因为它确实代表了对象所需的额外内存.在Python级别,您不需要担心垃圾的收集并将其视为魔法,但是,当询问有关对象大小的信息时,您不应该牺牲正确的结果来保持幻觉生存.

  • +1使你的`__sizeof __()`返回一个非零值,你会看到观察值增加了这个数量 (4认同)