我正在用python编写一个动态数组实现(类似于内置的list类),为此我需要观察容量的增长(每次达到限制时,容量都会增加一倍)。为此,我有以下代码,但输出是奇怪的。看起来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

最佳答案

你的__sizeof__被调用了,只是增加了垃圾收集器的开销,所以结果不是零。
From the docs on 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;

垃圾收集器使用的。
之所以将其添加到总大小中,可能是因为它确实表示对象所需的额外内存。在Python级别上,您不需要担心垃圾的收集,并将其视为魔法,但是,当您询问有关对象大小的信息时,不应该牺牲正确的结果,而仅仅是为了保持幻觉的存在。

关于python - __sizeof__没有被sys.getsizeof调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42051378/

10-13 07:24