如果字典包含可变对象或自定义类的对象(比如查询集,甚至是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 }
然后是
my_dict.clear()
与
相同for key in my_dict.keys():
del my_dict[key]
答案 0 :(得分:44)
Python documentation on dicts声明del d[key]
从字典中删除d[key]
,而d.clear()
删除了所有密钥,所以基本上他们的行为是相同的。
关于内存问题,在Python中“删除”时,基本上是删除了对象的引用。当某个对象未被任何变量或其他对象引用或变得无法访问时,它将变为垃圾,并且可以从内存中删除。 Python有一个垃圾收集器不时它完成了检查哪些对象是垃圾并释放为它们分配的内存的工作。 如果您从字典中删除的对象被其他变量引用,那么它仍然可以访问,因此它不是垃圾,因此不会被删除。如果你有兴趣阅读一般的垃圾收集和特别是python的垃圾收集,我会给你留下一些链接。
答案 1 :(得分:5)
它的行为与循环通过dict和
del
是否有所不同?
值得注意的是,任何实现MutableMapping
抽象基类的自定义类都将clear()
作为" free" mixin方法。
为了实例化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
方法可能与for key in mydict: del mydict[key]
字面上不一致。我希望在幕后进行一些优化,也许是一个完全不同的策略 - 但希望这个例子可以让你了解如何期望 clear()
方法在Python中工作。
答案 2 :(得分: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
答案 3 :(得分:3)
它与调用del d['foo']
相同 - 它只是删除条目,但它不会影响键或值本身。
当然,如果没有其他参考,它们可能会成为垃圾收集品。
答案 4 :(得分:1)
在您的情况下,共享两个MyClass
个对象。仍然可以通过my_obj_1
和my_obj_2
访问它们。
答案 5 :(得分:1)
del命令删除列表中特定项的引用,clear命令清除所有键值对,所以功能相同它们都是取消引用和休息任务从内存中删除它是由垃圾完成的集电极
答案 6 :(得分:0)
您是否尝试过运行代码? Python 3.7的以下代码会引发异常! “ RuntimeError:字典在迭代过程中更改了大小” :
for key in my_dict.keys():
del my_dict[key]
所有先前的答案都是好的。我只是想补充一些关于del和clear区别的观点:
此外,您还声明了两个变量my_obj_1和my_obj_2;即使删除/清除my_dict,这两个变量仍保留对MyClass对象的引用,直到my_obj_1和my_obj_2超出范围时,它们才会消失。因此,如果MyClass对象保存内存(例如列表或其他内容),那么如果您打算通过删除/清除my_dict释放内存,则不会发生!
class MyClass(object): '''测试班。'''
my_obj_1 = MyClass() my_obj_2 = MyClass()