Home > Net >  How to remove a specific fox object from a dictionary while iterating through it
How to remove a specific fox object from a dictionary while iterating through it

Time:11-11

I get a runtime error when i try to remove a fox object from a dictionary when it has starved in my simulation program, how can i fix this?

I tried to use other methods i discovered online, but i kept getting the same error.

import random

class Simulation:
    def __init__(self):
        self.Foxes = {}
        for i in range(100): # Creates 100 foxes
            self.Foxes[i] = Fox()

        def Main(self):
            for i in range(100): # Forages for each fox and checks for starvation
                for i in self.Foxes.keys(): 
                    self.Foxes[i].Forage()
                    if self.Foxes[i].Hunger >= self.Foxes[i].HungerMaximum:
                        self.Foxes.pop(i)

            print("There are "   str(len(self.Foxes))   " foxes remaining.")

class Animal:
    def __init__(self): 
        self.Age = 0
        self.HungerMaximum = 50
        self.Hunger = 0
        self.ForagingChance = 20

    def Forage(self):
        if random.randint(1,self.ForagingChance) == self.ForagingChance:
            if self.Hunger > 10:
                self.Hunger = self.Hunger - 10
        else:
            self.Hunger = self.Hunger   10
        
class Fox(Animal):
    def __init__(self):
        Animal.__init__(self)

CodePudding user response:

In these lines:

            for i in self.Foxes.keys(): 
                self.Foxes[i].Forage()
                if self.Foxes[i].Hunger >= self.Foxes[i].HungerMaximum:
                    self.Foxes.pop(i)

By calling self.Foxes.pop(i) within the for loop over self.Foxes.keys(), you are changing the size of the dictionary during iteration over the elements of the dictionary. This is not allowed in Python and will generate a RuntimeError.

To get around this limitation, create a new list containing self.Foxes.keys() -> list(self.Foxes.keys()) and iterate over that:

            for i in list(self.Foxes.keys()): 
                self.Foxes[i].Forage()
                if self.Foxes[i].Hunger >= self.Foxes[i].HungerMaximum:
                    self.Foxes.pop(i)

See also the answers here: How do I delete items from a dictionary while iterating over it?

CodePudding user response:

Not sure if this is a copy/paste error but your indentation is incorrect. Lines 10-16 under the Main function need to be indented. The entire Main function might also need to be unintended to be equal with the __init__ function depending on how you want to use it.

class Simulation:
    def __init__(self):
        self.Foxes = {}
        for i in range(100): # Creates 100 foxes
            self.Foxes[i] = Fox()

    def Main(self):
        for i in range(100): # Forages for each fox and checks for starvation
            for i in self.Foxes.keys(): 
                self.Foxes[i].Forage()
                if self.Foxes[i].Hunger >= self.Foxes[i].HungerMaximum:
                    self.Foxes.pop(i)

            print("There are "   str(len(self.Foxes))   " foxes remaining.")

As the other answer mentioned, you also are going to get a RuntimeError: dictionary changed size during iteration due to modifying a dictionary while iterating over it.

  • Related