dictionary的clear()方法是否从内存中删除了所有与项目相关的对象?

0xc*_*0de 24 python memory dictionary

如果字典包含可变对象或自定义类的对象(比如一个查询集,甚至是一个DateTime),那么调用clear()字典会从内存中删除这些对象吗?它是否与循环通过dict并del使用它们的行为不同?

例如.考虑

class MyClass(object):
    '''Test Class.'''

my_obj_1 = MyClass()
my_obj_2 = MyClass()

my_dict = { 'foo' : my_obj_1, 'bar' : my_obj_2 }
Run Code Online (Sandbox Code Playgroud)

然后是

my_dict.clear()
Run Code Online (Sandbox Code Playgroud)

与...一样

for key in my_dict.keys():
    del my_dict[key]
Run Code Online (Sandbox Code Playgroud)

San*_*dri 46

在类型的字典Python文档指出,del d[key]除去d[key]从字典,而d.clear()删除了每个键,所以基本上他们的行为是一样的.

关于内存问题,在Python中"删除"时,基本上是删除对象的引用.当一个对象没有被任何变量或其他对象引用或变得无法访问时,它就会变成垃圾并且可以从内存中删除.Python有一个垃圾收集器,它不时地检查哪些对象是垃圾并释放为它们分配的内存.如果您从字典中删除的对象被其他变量引用,那么它仍然可以访问,因此它不是垃圾,因此不会被删除.如果你有兴趣阅读一般的垃圾收集和特别是python的垃圾收集,我会给你留下一些链接.


Air*_*Air 5

它是否与循环通过dict并del使用它们的行为不同?

值得注意的是,任何实现MutableMapping抽象基类的自定义类clear()都是一个"免费"的mixin方法.

为了实例化子MutableMapping类,您需要覆盖的唯一方法是:

__getitem__, __setitem__, __delitem__, __iter__, __len__
Run Code Online (Sandbox Code Playgroud)

由于您可以按照自己喜欢的方式将数据存储在映射类中,因此唯一的方法clear()是通过使用这五种方法中的一种或多种来确定如何实际清除数据.现在,您可能会猜测哪些方法clear()正在使用,但为什么我们可以进行实验?

import collections

class MyMap(collections.MutableMapping):
    def __init__(self, mydict):
        self._top_secret_data = mydict

    def __getitem__(self, key):
        print 'getitem'
        return self._top_secret_data[key]

    def __setitem__(self, key, value):
        raise Exception('where did you want that?')

    def __len__(self):
        raise Exception('a gentleman never tells')

    def __delitem__(self, key):
        print '[shredding intensifies]'
        del self._top_secret_data[key]

    def __iter__(self):
        def keygen():
            for key in self._top_secret_data:
                print 'faster! faster!'
                yield key
        return iter(keygen())
Run Code Online (Sandbox Code Playgroud)

使用上面定义的类,很容易看出如何clear()实现:

>>> m = MyMap({1:'a', 2:'b', 3:'c'})
>>> m.clear()
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
>>> 
Run Code Online (Sandbox Code Playgroud)

换句话说,clear()mixin方法基本上实现为for key in self: del self[key].

现在,免责声明:内置类型如dict用C实现,因此该dict.clear方法可能与字面上完全相同for key in mydict: del mydict[key].我希望在幕后进行一些优化,也许是一个完全不同的策略 - 但希望这个例子可以让你对如何期望一个clear()方法在Python中工作有所了解.


317*_*070 5

实际上两者之间存在很小的差异.clear()将释放dict中使用的hashset的内存,而删除密钥则不会.

a = dict.fromkeys(range(1000))

In [10]: sys.getsizeof(a)
Out[10]: 49432

In [11]: a.clear()

In [12]: sys.getsizeof(a)
Out[12]: 280

In [13]: a = dict.fromkeys(range(1000))

In [14]: for i in range(1000):
   ....:     del a[i]
   ....:     

In [15]: sys.getsizeof(a)
Out[15]: 49432
Run Code Online (Sandbox Code Playgroud)