проблема в программе инвентаризации фэнтезийной игры (RuntimeError: размер словаря изменялся во время итерации) - PullRequest
0 голосов
/ 29 марта 2020

Я работаю над проблемой, приведенной в главе 5 книги Автоматизация скучного материала с помощью Python, в которой мне нужно определить функцию (addToInventory), которая должна добавлять элементы в список (с именем dragonLoot) для словаря (с именем inv) и другой функции (displayInventory), которая должна отображать новый словарь (inv). Функция displayInventory прекрасно работает, когда я тестирую ее отдельно, но когда я запускаю полную программу, я получаю RuntimeError: dictionary size changed during iteration. Вот мой код:

def displayInventory(inv):
    for k,j in inv.items(): #to display inv in format of a game inventory
        print(k,end=':')
        print(j)
def addToInventory(inv,dragonLoot):
    for a,b in inv.items(): #a represents key and b represents values
        for c in range(len(dragonLoot)-1):
            if a==dragonLoot[c]: #to check items in dragonLoot
                b+=1 #adding 1 to value if its corresponding key exists in dragonloot
            else:
                inv.setdefault(dragonLoot[c],1) #adding the new item if it dosent exist in dragonLoot 
    return inv
inv = {'gold coin':42,'rope':1}
dragonLoot = ['gold coin','dagger','gold coin','gold coin','ruby']
inv = addToInventory(inv,dragonLoot)
displayInventory(inv)

вот ошибка:

    Traceback (most recent call last):
  File "c:\users\murali\mu_code\addtoinventory.py", line 16, in <module>
    inv = addToInventory(inv,dragonLoot)
  File "c:\users\murali\mu_code\addtoinventory.py", line 7, in addToInventory
    for a,b in inv.items():
RuntimeError: dictionary changed size during iteration

, пожалуйста, скажите мне, где я делаю ошибку, а также, какие ошибки могут вызвать такую ​​ошибку. Я также нашел другое решение этой проблемы, но я хочу знать проблему в этой программе.

1 Ответ

0 голосов
/ 30 марта 2020

Проблема, с которой вы столкнулись, связана с вызовом setdefault в вашем словаре (который может добавить в него новый элемент), пока вы уже перебираете словарь items. Но на самом деле нет причин для того, чтобы вы итерировали. Словари являются наиболее эффективными, когда вы индексируете их ключом, чтобы увидеть их значение. Перебор всех ключей гораздо менее эффективен.

Вот как я это сделаю. Сначала у нас есть только один l oop поверх последовательности dragonLoot. Нам не нужно связываться с range, чтобы получить индекс здесь, просто присвоение имени списку напрямую позволит нам выполнять итерации непосредственно по его элементам. Метод get в словаре выполняет некоторую индексацию, проверяя, находится ли ключ в словаре, и возвращает либо соответствующее ему существующее значение, либо значение по умолчанию, которое мы ему передаем (как второй аргумент get, 0 в данном случае). Наконец, мы добавляем единицу к значению и делаем присвоение обратно в словарь, снова используя элемент добычи в качестве ключа:

def addToInventory(inv, dragonLoot):
    for loot_item in dragonLoot:
        inv[loot_item] = inv.get(loot_item, 0) + 1
    return inv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...