12

Getting the error mentioned in the title. The below mentioned functioned is called by another function that is called through a POST api.

Error is on the line below the print statement. Don't know what the error means and why its coming. The same code used to run a week back.

def remove_individual_stops(ordered_parkstop_dict, relevant_data):
    new_ordered_parkstop_dict = ordered_parkstop_dict
    for key, value in ordered_parkstop_dict.items():
        if len(value) == 0:
            for k,v in ordered_parkstop_dict.items():
                if key in v:
                    new_ordered_parkstop_dict.pop(key)
        print (type(ordered_parkstop_dict), ordered_parkstop_dict)
        for k,v in ordered_parkstop_dict.items():
            klist = []
            keylist = []
            if value and v:
                if len(v)==1 and len(value)==1:
                    klist.append(k), keylist.append(key)
                if (keylist == v) and (klist == value and len(value) == 1):
                    new_ordered_parkstop_dict.pop(key)
    return new_ordered_parkstop_dict
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
SUP
  • 349
  • 1
  • 2
  • 11
  • 3
    you walk through the object and modify it at the same time. – Brown Bear Sep 28 '18 at 06:39
  • [How to delete items from a dictionary while iterating over it?](https://stackoverflow.com/questions/5384914/how-to-delete-items-from-a-dictionary-while-iterating-over-it) I think this is a very relevant answer, besides making a copy of the dictionary, as in the answer. – aspiring1 May 24 '19 at 06:34

2 Answers2

19

You assigned new_ordered_parkstop_dict with a reference of the ordered_parkstop_dict dict, so when you iterate over ordered_parkstop_dict.items() and mutate new_ordered_parkstop_dict by popping it, you mutate ordered_parkstop_dict too, which can't be done since your loop is iterating over ordered_parkstop_dict.

You should assign a copy of ordered_parkstop_dict to new_ordered_parkstop_dict instead. Change:

new_ordered_parkstop_dict = ordered_parkstop_dict

to:

new_ordered_parkstop_dict = ordered_parkstop_dict.copy()
blhsing
  • 91,368
  • 6
  • 71
  • 106
  • 1
    Thanks a lot. The issue is fixed but can you explain why did the error pop up now while the same code was working last week – SUP Sep 28 '18 at 06:56
  • The error does not necessarily occur because you're putting `new_ordered_parkstop_dict.pop(key)` in a conditional block, so with a different input it may or may not trigger the error by satisfying or not satisfying the condition. – blhsing Sep 28 '18 at 06:59
  • Ok thats obvious, but what if i tell you that there is no change with the input as well. The same code is deployed in another server and it runs perfectly for the same input. – SUP Sep 28 '18 at 07:11
  • 3
    That's most likely because the other server is running Python 2.7 or earlier versions, where mutating a dict while iterating over it is allowed. – blhsing Sep 28 '18 at 07:21
  • I had my doubt but didn't check what version of python was runnning. Sir, Thanks a lot for helping out. – SUP Sep 28 '18 at 07:41
  • You don't need any reputation to accept an answer. Try clicking on the grey check mark next to an answer to accept it. :-) – blhsing Sep 28 '18 at 08:06
  • cool, there are very interesting comments above. I migrated my code from python 2.7 to python 3.7. I get the same error with an OrderedDict. Shouldn't I do `deepcopy` instead of `copy`? – alwbtc May 01 '19 at 19:45
0

You should assign the copy object of ordered_parkstop_dict to new_ordered_parkstop_dict with dict() or copy() as shown below:

new_ordered_parkstop_dict = dict(ordered_parkstop_dict)
new_ordered_parkstop_dict = ordered_parkstop_dict.copy()

In addition, you can check if the objects are the same with is operator as shown below:

person1 = {"name": "John", "age": 36}
person2 = person1
print(person1 is person2) # True
person1 = {"name": "John", "age": 36}
person2 = dict(person1)
print(person1 is person2) # False
person1 = {"name": "John", "age": 36}
person2 = person1.copy()
print(person1 is person2) # False
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129