Python 字典';s clear()方法是否从内存中删除所有与项相关的对象?

Python 字典';s clear()方法是否从内存中删除所有与项相关的对象?,python,memory,dictionary,Python,Memory,Dictionary,如果字典包含可变对象或自定义类的对象(比如queryset,甚至DateTime),那么在字典上调用clear()会从内存中删除这些对象吗? 它的行为是否与在dict中循环并对其进行del操作不同 例如。 考虑 那就是 my_dict.clear() 同 for key in my_dict.keys(): del my_dict[key] ?这与调用deld['foo']相同-它只是删除条目,但不影响键或值本身 当然,如果没有其他引用,它们可能会变成垃圾回收对象。在您的例子中,这两

如果字典包含可变对象或自定义类的对象(比如queryset,甚至DateTime),那么在字典上调用
clear()
会从内存中删除这些对象吗? 它的行为是否与在dict中循环并对其进行
del
操作不同

例如。 考虑

那就是

my_dict.clear()

for key in my_dict.keys():
    del my_dict[key]

这与调用
deld['foo']
相同-它只是删除条目,但不影响键或值本身


当然,如果没有其他引用,它们可能会变成垃圾回收对象。

在您的例子中,这两个
MyClass
对象是共享的。它们仍然可以通过
my_obj_1
my_obj_2
从字典中删除
d[key]
,而
d.clear()
删除每个键,因此它们的行为基本相同

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

它的行为是否与在dict中循环并对其进行
del
操作不同

这里值得注意的是,任何实现
MutableMapping
抽象基类的自定义类都将
clear()

要实例化
MutableMapping
子类,您需要重写的唯一方法是:

__getitem__, __setitem__, __delitem__, __iter__, __len__
由于您可以按自己喜欢的方式将数据存储在映射类中,因此
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())
使用上面定义的类,很容易看到
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]
>>> 
换句话说,
clear()
mixin方法基本上实现为
for key-In-self:del-self[key]


现在,免责声明:内置类型,如
dict
是用C实现的,因此
dict.clear
方法可能与mydict中key的
方法不同:del mydict[key]
。我希望在幕后进行一些优化,也许是一种完全不同的策略——但希望这个示例能够让您了解到,在Python中如何使用
clear()
方法。

实际上,这两者之间的差别很小
clear()
将释放dict中使用的哈希集的内存,而删除密钥则不会

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

del命令删除列表中特定项的引用,clear命令清除go中的所有键值对,使功能相同。它们都是由垃圾收集器完成从内存中删除它的解除引用和rest任务。

您是否尝试运行该代码?以下使用Python 3.7的代码引发异常“运行时错误:在迭代过程中更改了字典大小”

for key in my_dict.keys():
    del my_dict[key]
以前的答案都是好的。我只是想就del和clear的区别补充几点:

  • 我的命令清除()删除字典中的所有项,并使其等效于空字典。注意:如果需要,您仍然可以向其中添加项目
  • 删除我的命令使my_dict的对象被删除并符合垃圾收集条件(my_dict不再可用)!因此,如果您尝试添加/访问任何项目,那么您将得到一个异常
  • 此外,您还声明了两个变量my_obj_1和my_obj_2;即使删除/清除my_dict,这两个变量仍保留对MyClass对象的引用,并且在my_obj_1和my_obj_2超出范围之前不会消失;因此,如果MyClass对象拥有内存(比如list或其他),那么如果您打算通过删除/清除my_dict来释放内存,那么它就不会发生

    类MyClass(对象): “考试班”

    my_obj_1=MyClass() my_obj_2=MyClass()


  • 换句话说,如果或键或值共享(分配给另一个变量),则它们的对象不会被删除,也不会被
    d.clear()
    ,也不会被
    del d[key]
    删除。字典存储对键和值的引用。引用被操作删除。是的,所以我在这里缺少的关键是删除操作只删除引用,内存清除由垃圾收集器处理!我发现了同样的事情,这非常重要,当你处理一个非常大的dict时。我从不使用
    for
    循环来删除所有键,因为它不会释放内存,因此没有意义。问题从来没有说它在python 3中,因为它在python 2中。请检查问题的日期,Python3.7在当时从未存在过,因此使用它运行代码是不明智的。
    for key in my_dict.keys():
        del my_dict[key]