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.
