Python 字典';s clear()方法是否从内存中删除所有与项相关的对象?
如果字典包含可变对象或自定义类的对象(比如queryset,甚至DateTime),那么在字典上调用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']相同-它只是删除条目,但不影响键或值本身 当然,如果没有其他引用,它们可能会变成垃圾回收对象。在您的例子中,这两
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的垃圾收集感兴趣,我会在这里给您留下一些链接
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]