Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python有序垃圾收集字典?_Python_Garbage Collection_Ordereddictionary - Fatal编程技术网

Python有序垃圾收集字典?

Python有序垃圾收集字典?,python,garbage-collection,ordereddictionary,Python,Garbage Collection,Ordereddictionary,我希望我的Python程序是确定性的,因此我在整个代码中广泛使用了OrderedDicts。不幸的是,今天在调试内存泄漏时,我发现OrderedDicts有一个自定义的\uu del\uuu方法,使得它们在有周期时无法收集。很不幸,文档中没有关于这一点的警告 那我该怎么办?Python标准库中是否有任何与gc配合良好的确定性词典?我真的不想自己翻滚,尤其是像这样愚蠢的单行函数 还有,这是我应该提交错误报告的东西吗?我不熟悉Python库的程序,他们认为什么是bug。< /P> 编辑:我想最好的方

我希望我的Python程序是确定性的,因此我在整个代码中广泛使用了
OrderedDicts
。不幸的是,今天在调试内存泄漏时,我发现OrderedDicts有一个自定义的
\uu del\uuu
方法,使得它们在有周期时无法收集。很不幸,文档中没有关于这一点的警告

那我该怎么办?Python标准库中是否有任何与gc配合良好的确定性词典?我真的不想自己翻滚,尤其是像这样愚蠢的单行函数

还有,这是我应该提交错误报告的东西吗?我不熟悉Python库的程序,他们认为什么是bug。< /P>
编辑:我想最好的方法是只包含一个猴子补丁,以防用户碰巧运行像我这样的坏版本。

听起来你已经在
orderedict
中找到了一个bug,它在你的2.7版本之后的某个时候被修复了。如果它不是在任何实际发布的版本中,也许你可以忽略它。但除此之外,是的,你需要一个变通办法

我建议您不要使用monkeypatching
collections.OrderedDict
,而应该使用链接到的
collections.OrderedDict
(它没有多余的
\uu del\uu
)。如果没有其他问题,当有人说“我需要在2.6上运行这个,移植需要多少工作量”时,答案将是“少一点”

但还有两点:

重写所有内容以避免循环是一项巨大的工作

字典中有循环这一事实表明您做错了什么(通常对缓存或后向指针使用强引用),这可能会导致其他内存问题,也可能导致其他错误。因此,无论如何,这种努力可能是必要的

你还没有解释你想要完成什么;我怀疑“确定性”的东西只是一条红鲱鱼(特别是因为
dict
s实际上是确定性的),所以最好的解决方案是
s/orderedict/dict/g

但是,如果必须使用确定性,那么就不能依赖于循环收集器,因为它不是确定性的,这意味着终结器排序等都变得不确定性。这也意味着你的内存使用是不确定的,你可能最终得到的程序99.999%的时间都在你想要的内存范围内,但不是100%;如果这些界限非常重要,那可能比每次都失败更糟糕

同时,没有指定字典的迭代顺序,但在实践中,CPython和PyPy按照散列桶的顺序进行迭代,而不是值或键的id(内存位置),以及Jython和IronPython所做的任何事情(它们可能使用的是一些具有不同行为的底层Java或.NET集合;我还没有测试),钥匙的记忆顺序不太可能相关。(如何有效地基于类似的内容迭代散列表?)您可能会对使用
id
进行
散列的对象进行测试而感到困惑,但大多数对象都是基于值进行散列的

例如,以这个简单的程序为例:

d={}
d[0] = 0
d[1] = 1
d[2] = 2
for k in d:
  print(k, d[k], id(k), id(d[k]), hash(k))
如果使用CPython 2.7、CPython 3.2和PyPy 1.9重复运行它,这些键将始终按0、1、2的顺序迭代。
id
列也可能每次都相同(这取决于您的平台),但您可以通过多种方式修复此问题:以不同的顺序插入,颠倒值的顺序,使用字符串值而不是整数,将值分配给变量,然后插入这些变量而不是文字,等等。充分利用它,您可以获得
id
列的每一个可能的顺序,但是每次键仍然以相同的顺序迭代

迭代的顺序是不可预测的,因为要预测它,您需要将
hash(k)
转换为bucket索引的函数,这取决于您无法从Python访问的信息。即使它只是
散列(k)%self.\u table\u size
,除非该
\u table\u size
被公开给Python接口,否则它是没有帮助的。(这是一个复杂的插入和删除序列函数,原则上可以计算,但在实践中尝试是愚蠢的。)


但它是确定性的;如果您每次都以相同的顺序插入和删除相同的键,那么每次的迭代顺序都是相同的。

听起来好像您在
orderedict
中找到了一个bug,该bug在2.7版之后的某个时候被修复了。如果它不是在任何实际发布的版本中,也许你可以忽略它。但除此之外,是的,你需要一个变通办法

我建议您不要使用monkeypatching
collections.OrderedDict
,而应该使用链接到的
collections.OrderedDict
(它没有多余的
\uu del\uu
)。如果没有其他问题,当有人说“我需要在2.6上运行这个,移植需要多少工作量”时,答案将是“少一点”

但还有两点:

重写所有内容以避免循环是一项巨大的工作

字典中有循环这一事实表明您做错了什么(通常对缓存或后向指针使用强引用),这可能会导致其他内存问题,也可能导致其他错误。因此,无论如何,这种努力可能是必要的

你还没有解释你想要完成什么;我怀疑“确定性”的东西只是一条红鲱鱼(特别是因为
dict
s实际上是确定性的),所以最好的解决方案是
s/orderedict/dict/g

但是如果决定论是必要的,你就不能依赖于循环收集器,因为它不是决定论的
>>> import collections
>>> del collections.OrderedDict.__del__