字典大小在迭代过程中更改(运行时错误)

时间:2019-07-14 11:19:43

标签: python python-3.x dictionary recursion

我得到RuntimeError:字典在迭代过程中更改了大小,我浏览了一些堆栈溢出帖子,发现当您在循环(插入/删除)时修改字典的大小时会发生这种情况。

但是,在我的情况下,我只是遍历字典,所以我不确定为什么会收到错误消息。

我发现使用非集合字典时没有出现任何问题,但是这使得添加新顶点比使用集合复杂得多。

我知道我可以制作一个字典的深层副本并对其进行迭代,但是我想首先了解为什么首先出现此错误。

在下面的示例中,我剪切了大多数非必需的代码。

from collections import defaultdict 


class Graph: 

    def __init__(self,vertices): 

        self.graph = defaultdict(list)  

    def addEdge(self,u,v): 
        self.graph[u].append(v) 

    def fillOrder(self,v,visited, stack): 

        visited.add(v)
        for neighbour in self.graph[v]:
          if neighbour not in visited:
            self.fillOrder(neighbour, visited, stack)
        stack.append(v)


    def printSCCs(self): 

        stack = [] 

        visited = set()

        for key in self.graph:
          print(key)
          self.fillOrder(key, visited, stack)

g = Graph(5) 
g.addEdge(1, 0) 
g.addEdge(0, 2) 
g.addEdge(2, 1) 
g.addEdge(0, 3) 
g.addEdge(3, 4) 
g.printSCCs() 

我希望不会引发任何错误,并且堆栈中将填充图中的顶点。

1 个答案:

答案 0 :(得分:1)

您使用的是defaultdict,因此,如果您尝试访问不存在的条目,则会在隐式插入中出现。

尤其是:

def fillOrder(self,v,visited, stack): 
    # ...
    for neighbour in self.graph[v]:
        # ...

您的密钥v不保证存在,因此对self.graph[v]的访问导致将新条目添加到字典中。如果您将defaultdict替换为普通字典,并根据需要在addEdge中创建新列表,那么很明显失败了:

1
Traceback (most recent call last):
  File "test.py", line 38, in <module>
    g.printSCCs()
  File "test.py", line 30, in printSCCs
    self.fillOrder(key, visited, stack)
  File "test.py", line 21, in fillOrder
    self.fillOrder(neighbour, visited, stack)
  File "test.py", line 21, in fillOrder
    self.fillOrder(neighbour, visited, stack)
  File "test.py", line 21, in fillOrder
    self.fillOrder(neighbour, visited, stack)
  File "test.py", line 19, in fillOrder
    for neighbour in self.graph[v]:
KeyError: 4

如果要保证两个边缘端点都在字典中,则可能需要修改addEdge来做到这一点:

self.graph[u].append(v) 
self.graph[v].append(u)