【发布时间】:2018-01-11 09:10:17
【问题描述】:
我有一个for thing in a_set: 形式的循环。它工作不正确,因为它偶尔会不一致地从集合中拉出相同的东西两次。 (这不会导致程序崩溃。它只是得到错误的答案。)我无法确定任何关于错误行为的确定性;但我调试它的尝试清楚地表明,有时会发生奇怪的事情。在我最仔细观察的情况下,集合中有 3 个项目(之前和之后),循环执行了 4 次,其中一个项目重复了一次。这些项目是对我创建的类的对象的引用(更像是 C 结构)。当我将 for 语句更改为 for thing in list(a_set): 时,不良行为消失了。
我完全无法解释错误的行为。我非常确定循环体中的任何内容都不会导致它正在执行的操作发生两次或更改事物变量的值。我相当肯定循环中发生的事情不会试图影响集合的组成。此外,即使可以,我相信这会导致RuntimeError。对于可能导致这种情况的假设,我完全不知所措。连续运行相同代码缺乏可重复性尤其神秘。我在更简单的场景中重新创建症状的尝试失败了。尽管如此,我会觉得将list() 调用留在那里只是为了解决我无法解释的问题很愚蠢。任何其他人的假设都会受到欢迎。我需要了解在调试时应该尝试消除哪些类型的事情。
更新:我认为这个问题被错误地搁置了,因为它声称它是题外话。在这种情况下,缺乏可重复性是问题所在,我怀疑我缺少的语言有一些细微差别。事实上,事实证明确实如此,MSeifert 的回答让我了解了导致它的原因。然而,正如我在对他的回答的评论中指出的那样,这并不像他推测的那么简单。
我还说集合中的对象是可变的,从而混淆了这个问题。他们不是。它们是对属性可变的对象的引用。 (这可以从我写的内容中推断出来,但是我在一般意义上而不是在 Python 技术意义上错误地使用了“可变”这个词。)散列的是对象的地址,与它的值无关属性。如果这些对象引用是可变的,Python 一开始就不会让我把它们放在一个集合中。
【问题讨论】:
-
你需要一些方法来重现这个。你的集合是否有你正在改变的可变对象?
-
@matt。问题在于缺乏可重复性。是的,集合中的对象是可变的。它们具有正在改变的属性;但它们仍然是相同的对象。在大多数没有发生不良行为的情况下(没有列表),它们的属性也会发生这种变化。
-
你是如何创建你的集合的?
-
@matt。我从一个空集开始,并使用 add 函数一次添加一个项目。
-
"是的,集合中的对象是可变的。它们具有正在更改的属性" - 集合元素不应该是可变的,或者至少不应该以影响
==和@987654326 的方式可变@。如果您没有立即意识到这将是一个问题,那么您应该完全避免将可变对象放入集合中。
标签: python python-2.7 set iteration