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.