在python中的相同对象之间共享内存

2024-09-28 05:25:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我创建了一长串python对象,其中有许多相同的条目。为了节省一些内存,我想确保相同的元素共享它们的内存。例如:

In [1]: alist = [(3, 4), (3, 4)]

In [2]: alist[0] == alist[1]
Out[2]: True

In [3]: alist[0] is alist[1]
Out[3]: False

两个列表元素是相等的,但使用单独的内存。在这个简单的例子中,问题可以通过

In [4]: alist[1] = alist[0]

In [5]: alist[1] is alist[0]
Out[5]: True

如何以更普遍的方式做到这一点?列表没有排序,因此相同的元素通常不相邻。我想出的一个解决办法是:

g_dupdict = dict()
def dedup(x):
  try:
    return g_dupdict[x]
  except KeyError:
    g_dupdict[x] = x
    return x

for k in range(len(alist)):
  alist[k] = dedup(alist[k])

这是可行的,但会带来新的问题。用听写器似乎很傻,一套就行了,但我不知道怎么做。然后dict保存对每个对象的额外引用,因此当元素从列表中删除时,内存不会被释放。为了解决这个问题,我偶尔会删除dict,但是当新元素添加到列表中时,它必须被重新创建。 这个问题有更好的解决办法吗?谢谢


Tags: 对象内存intrue元素列表returnis
1条回答
网友
1楼 · 发布于 2024-09-28 05:25:44

我想你是在操纵巨大的数据结构来关心这个问题。将g_dedupdict范围限定到给定数据结构的一种方法是将其封装在自己的list实现中:

class CachedList(list):
    def __init__(self, iterable=(), cache=None):
        self.__cache = cache or {}
        super().__init__([self.__cached(item) for item in iterable])

    def append(self, e):
        super().append(self.__cached(e))

    def clear(self):
        self.__cache.clear()
        super().clear()

    def copy(self):
        return CachedList(self, self.__cache)

    def extend(self, iterable):
        super().extend([self.__cached(item) for item in iterable])

    def insert(self, index, e):
        super().insert(index, self.__cached(e))

    def remove(self, e):
        super().remove(self.__cached(e))
        del self.__cache[hash(e)]

    def __cached(self, e):
        if hash(e) not in self.__cache:
            self.__cache[hash(e)] = e
        return self.__cache[hash(e)]

    def __add__(self, iterable):
        cached_iterable = [self.__cached(item) for item in iterable]
        return CachedList(super().__add__(cached_iterable), self.__cache)

    def __delitem__(self, e):
        super().__delitem__(self.__cached(e))
        del self.__cache[hash(e)]

    def __iadd__(self, e):
        self.append(self.__cached(e))
        return self

    def __setitem__(self, index, e):
        super().__setitem__(index, self.__cached(e))


if __name__ == '__main__':
    e1 = (3, 4)
    e2 = (3, 4)
    assert e1 == e2
    assert e1 is not e2
    assert hash(e1) == hash(e2)

    alist = CachedList([(3, 4), (3, 4)])
    assert alist[0] == alist[1]
    assert alist[0] is alist[1]

    alist[0] = (3, 4)
    assert alist[0] == alist[1]
    assert alist[0] is alist[1]

    alist += (3, 4)
    assert alist[0] == alist[-1]
    assert alist[0] is alist[-1]

    newlist = alist + [(3, 4)]
    assert newlist[0] == newlist[-1]
    assert newlist[0] is newlist[-1]

实现可能不完整,但我认为您可以从上面的代码片段中获得想法

相关问题 更多 >

    热门问题