-1

I'm working on a problem given in chapter 5 of the book Automate Boring Stuff with Python in which I have to define a function (addToInventory) which is supposed to add items in a list (named dragonLoot) to a dictionary (called inv) and another function (displayInventory) which is supposed to display the new dictionary (inv). The displayInventory function works fine when I test it separately, but when I run the complete program I'm getting RuntimeError: dictionary size changed during iteration. Here is my code:

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)

here is the error:

    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

please tell me where I'm making a mistake and also what kind of mistakes can cause such error.I have also found different solution to this problem but i want to know problem in this program.

chb
  • 1,727
  • 7
  • 25
  • 47
  • 1
    The error is pretty clear. You are not allowed to change the dictionary that you are iterating over. In your case that would be `inv` – rdas Mar 29 '20 at 18:30
  • Does this answer your question? [Dictionary changed size during iteration - Code works in Py2 Not in Py3](https://stackoverflow.com/questions/45830124/dictionary-changed-size-during-iteration-code-works-in-py2-not-in-py3) – Shane Creedon Mar 29 '20 at 18:35

1 Answers1

0

The issue you're having has to do with calling setdefault on your dictionary (which might add a new item to it) while you're already iterating over the dictionary's items. But there's really no reason for you to be iterating. Dictionaries are most powerful when you're indexing them with a key to see what their value is. Iterating over all the keys is much less efficient.

Here's how I'd do it. First we have only one loop, over the dragonLoot sequence. We don't need to mess with a range to get an index here, just naming the list directly will let us iterate directly over its items. The get method on the dictionary does some indexing, checking if the key is in the dictionary, and it either returns to us the associated existing value, or a default value we give it (as the second argument to get, 0 in this case). Finally, we add one to the value, and do an assignment back to the dictionary, using the loot item as the key again:

def addToInventory(inv, dragonLoot):
    for loot_item in dragonLoot:
        inv[loot_item] = inv.get(loot_item, 0) + 1
    return inv
Blckknght
  • 100,903
  • 11
  • 120
  • 169