Python 'Dictionary changed size during iteration' error even though size changes after iterations should be complete

StackOverflow https://stackoverflow.com/questions/22311020

Pergunta

I have a list of cities and I am trying to group them together based on distance. I am iterating through the list of cities. The first city in the list has nothing to compare to, so it automatically creates its own city group. The subsequent cities in the list are compared to all of the cities in the existing groups of cities. If the city is within a threshold distance of any of the cities in a city group, it is added to the city group. Otherwise, it creates a new group. My groups are being stored as dictionaries with one dictionary storing the city groups and then for each city group there is a dictionary storing all of the cities in that group.

I am calling findsetlist() where it checks to see if the city should belong to an existing city group or create a new one. After the calling of findsetlist(), I then update the city group dictionary with either the addition of the city to an existing group or the creation of the new group. When I run the code, I am getting an error that says "dictionary changed size during iteration". It is saying that I am changing the size of my dictionary while it is iterating inside of my 'for loops'. But I don't change the size until after it should have exited both 'for loops', so I don't understand why it is having a problem.

I appreciate any help that you can give me. Thank you.

class citySets:  
    def __init__(self,city,citysetdict,citysetnum):  
        self.city=city  
        self.citysetdict=citysetdict  
        self.citysetnum=citysetnum  
    def findsetlists(self):  
        if len (self.citysetdict)==0:  
            self.citysetnum=1  
            self.closecitysetnum=1  
            self.closeval=9999999999  
            self.temp={}  
            self.temp[self.city[apiad]]=self.city  
        else:  
            self.closecitysetnum=self.citysetnum+1  
            self.closeval=9999999999  
            self.temp={}  
            for self.key in self.citysetdict:  
                for self.key2 in self.citysetdict[self.key]:  
                    self.secondcity= self.citysetdict[self.key][self.key2]  
                    self.compare=cityCompare(self.city,self.secondcity)  
                    self.compare.distance()  
                    if self.compare.dist<=distancethreshold:  
                        self.closecitysetnum=self.key  
                        self.temp = self.citysetdict[self.key]  
                        self.temp[self.city[apiad]]=self.city  

citysets={}  
for currentcity in citylist:  
    d=citySets(currentcity,citysets,citysetnum)  
    d.findsetlists()  
    citysetnum=d.closecitysetnum  
    citysets[citysetnum]=d.temp  
Foi útil?

Solução

            ...
            for self.key2 in self.citysetdict[self.key]:
                 ....
                 if self.compare.dist<=distancethreshold: 
                    ...
                    self.temp = self.citysetdict[self.key]
                    self.temp[self.city[apiad]]=self.city

This looks like your problem. You're iterating over the dictionary self.citysetdict[self.key]. Then you assign self.citysetdict[self.key] to self.temp, and then assign an item of self.temp (which will change its size unless the key already existed).

As an aside, when Python reported that error about "dictionary size changed during iteration", it would have told you exactly which line was the problem. That clue could have saved your confusion about how you thought you weren't changing size until after the for loops were finished, because it would clearly have pointed to a line within the for loops (which also greatly narrows down which dictionary is the problem). But even if you don't yet know how to read the stack traces printed in the error message to do this kind of problem identification (which is fine, everyone has to learn sometime), when you're asking others for help please include the error message, so that the people helping you can make use of this clue!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top