首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调试Python 3运行时错误

调试Python 3运行时错误
EN

Stack Overflow用户
提问于 2018-01-16 23:43:35
回答 1查看 1.5K关注 0票数 1

所以我一直在做一个学校项目,这个函数给我带来了很多麻烦。它从index (x,y)中获取字典中的对象,并将其移动到新的索引中。我每次运行它时都会得到一个RuntimeError,我认为这是因为我向字典中添加了一个新的索引,但我不知道如何解决这个问题。enemydict中的敌人具有'leap‘属性(一个整数),并且位于索引(xlocation,ylocation)。这是代码;

代码语言:javascript
复制
def moveEnemies(self):
    keys = self.enemydict.keys()
    for key in keys:
        leap = self.enemydict[key].leap

        if self.enemydict[key].attacked == False:
            self.enemydict[key].counter -= 1

        if self.enemydict[key].counter <= 0 and self.enemydict[key].attacked == False:

            self.enemydict[key].counter = self.enemydict[key].turncount
            for i in range(leap):

                option = random.randint(0, 9)
                if option == 1:
                    goingTo = [key[0]+1,key[1]]

                elif option == 2:
                    goingTo = [key[0]+1,key[1]+1]

                ...

                elif option == 8:
                    goingTo = [key[0]-1,key[1]-1]
                else:
                    goingTo = key

                if self.getMapSquare(goingTo[1], goingTo[0]) == '#':
                    self.genSquare(goingTo[1], goingTo[0])
                try:
                    self.enemydict[(goingTo[0], goingTo[1])] = self.enemydict[key]
                    self.enemydict[key] = ' '
                except: #this fixed a smaller problem, but it just gave the runtimeerror
                    pass

                continue

下面是错误回溯:

代码语言:javascript
复制
Traceback (most recent call last):
  File "/home/ubuntu/workspace/cp1-workspace/semester-1 - Python/unit-06 - oop and game/p1-pyzork/not_quite_zork/game.py", line 442, in <module>
    gm.mainloop()
  File "/home/ubuntu/workspace/cp1-workspace/semester-1 - Python/unit-06 - oop and game/p1-pyzork/not_quite_zork/game.py", line 423, in mainloop
    self.moveEnemies()
  File "/home/ubuntu/workspace/cp1-workspace/semester-1 - Python/unit-06 - oop and game/p1-pyzork/not_quite_zork/game.py", line 365, in moveEnemies
    for key in keys:
RuntimeError: dictionary changed size during iteration

非常感谢任何能提供帮助的人!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-18 07:26:10

错误消息的意思正如它所说的:您在迭代字典时更改了字典的大小。

这发生在下面这行代码中:

代码语言:javascript
复制
self.enemydict[(goingTo[0], goingTo[1])] = self.enemydict[key]

这将向self.enemydict添加一个新值,该值位于循环中,您可以在其中迭代该字典:

代码语言:javascript
复制
keys = self.enemydict.keys()
for key in keys:

以下是Python控制台中的一个简化示例:

代码语言:javascript
复制
>>> d = { 'a': 'A', 'b': 'B' }
>>> d
{'a': 'A', 'b': 'B'}
>>> keys = d.keys()
>>> for k in keys:
...     print( k )
...     if k == 'a':
...         d['c'] = 'C'
...
a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

请注意,即使我们已经将d.keys()赋给了它自己的变量keys,Python仍然知道keys与原始字典相关联,所以当我们向d添加新元素时,它会使迭代无效。

解决这个问题的一种简单方法是使用list()keys()转换为简单的列表。然后,您将迭代该列表而不是原始字典,并且修改字典不会使迭代无效。(当然,迭代不会触及您在本例中添加的新元素。)下面是一个例子:

代码语言:javascript
复制
>>> d = { 'a': 'A', 'b': 'B' }
>>> for k in list(d.keys()):
...     print( k )
...     if k == 'a':
...         d['c'] = 'C'
...
a
b
>>> d
{'a': 'A', 'b': 'B', 'c': 'C'}

下面是它在你的代码中的样子。我还将向您展示一个使代码更简单、更易于阅读的技巧。不是反复引用self.enemydict[key],而是在一个名为enemy的变量中保存一次,然后使用它。

因此,循环的第一部分如下所示:

代码语言:javascript
复制
keys = self.enemydict.keys()
for key in keys:
    leap = self.enemydict[key].leap
    if self.enemydict[key].attacked == False:
        self.enemydict[key].counter -= 1
    if self.enemydict[key].counter <= 0 and self.enemydict[key].attacked == False:
        self.enemydict[key].counter = self.enemydict[key].turncount

应该是这样的:

代码语言:javascript
复制
for key in list(self.enemydict.keys()):
    enemy = self.enemydict[key]
    leap = enemy.leap
    if enemy.attacked == False:
        enemy.counter -= 1
    if enemy.counter <= 0 and enemy.attacked == False:
        enemy.counter = enemy.turncount

在循环后面的位置,您可以进行类似的更改,如下所示:

代码语言:javascript
复制
                self.enemydict[(goingTo[0], goingTo[1])] = self.enemydict[key]
                self.enemydict[key] = ' '

至:

代码语言:javascript
复制
                self.enemydict[(goingTo[0], goingTo[1])] = enemy
                self.enemydict[key] = ' '

但请注意,我只更改了这两行中的第一行。我没有将第二行改为:

代码语言:javascript
复制
                enemy = ' '

这将不会做与原始代码相同的事情。它不是在self.enemydict中更新或添加值,而是更改enemy变量,使其不再是对self.enemydict[key]的引用。

当你这样做的时候,这不是问题:

代码语言:javascript
复制
        enemy.counter = enemy.turncount

因为我们不会更改enemy变量本身,只会更改.counter属性。enemy继续引用字典条目。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48284976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档