0

First of all I am trying to update my code from Python 2 to Python 3. I am trying to update a Dictionary, I am updating the name of the keys, and poping out that keys that I don't use. I am getting an error: dictionary changed size during iteration

Code Example:

for k, v in self.v_signals.items():
    for jj in self.On_Signal_Option["levels_run"]:
        new_key = str(k) + str(jj)
        self.v_signals[new_key] = self.v_signals[k]
    self.v_signals.pop(k, None)
Vishal Singh
  • 6,014
  • 2
  • 17
  • 33
Shimron F
  • 221
  • 1
  • 2
  • 7
  • 4
    build a new dictionary instead of modifying the existing one – Chris_Rands Jul 23 '20 at 11:56
  • 2
    You almost never want to mutate the datastructure you're iterating on during the iteration, regardless of the programming language you're using. Take the advice in the first comment - it will save you time & pain! – Nir Alfasi Jul 23 '20 at 11:57
  • @alfasin, I tend to agree with you, but sometimes you don't want to overload with so many duplicated/similar variables. – Shimron F Jul 23 '20 at 12:07
  • 1
    Does this answer your question? [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – SiHa Jul 23 '20 at 12:56

3 Answers3

2

The items method has changed between Python 2 and 3. In Python2, it builds a list while in Python3 it just gives an iterator on the dictionary (what iteritems did in Python2). So the correspondance 2 -> 3, when d is a dict is:

  • d.items() -> list(d.items())
  • d.iteritems() -> d.items()

This explains why the code worked in Python2 and no longer works in Python3.

So to keep Python 2 behaviour, you have to explicitely build an independant list:

for k, v in list(self.v_signals.items()):
    ...                  
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
1

this will create a new dictionary.

self.v_signals = {
    str(k) + str(jj): v
    for k, v in self.v_signals.items()
    for jj in self.On_Signal_Option["levels_run"]
}
Vishal Singh
  • 6,014
  • 2
  • 17
  • 33
0

Copy the items to a list for iteration

for k, v in list(self.v_signals.items()):
  for jj in self.On_Signal_Option["levels_run"]:
      new_key = str(k)+str(jj)
      self.v_signals[new_key] = self.v_signals[k]
  self.v_signals.pop(k, None)
Mike67
  • 11,175
  • 2
  • 7
  • 15