1

I am writing a program in which I need to iterate through many long dictionaries, so I thought I could remove unneeded values from it, to save on some runtime. Here is a minimal working example with lacking context:

years = {0: 2019, 1: 2020, 2: 2021}


def iterate_years():
    for i in years:
        temp_years = years
        print("years:", years)
        print("temp_years:", temp_years)
        temp_years.pop(i)
        minimum = min(temp_years)
        maximum = max(temp_years)
        print("temp_years:", years)
        print("years:", years)


iterate_years()

When I run this it returns a runtime error because the size f the dictionary changed while iteration. As you can see through the example the line temp_years.pop(i) seems to pop the key-value pair i in temp_years, as specified but also in years.
Why does this happen? I am not very experienced but years is never assigned to temp_years after the pop() so the value for years should stay like they were specified in the first line.

2 Answers2

1

The problem here is that temp_years and years are pointing to the same object in memory (reference), you can check it comparing the id of both variables:

>>> id(temp_years) == id(years)
>>> True

If you want a copy, you have to create a new dict with temp_years = years.copy(). But if you have nested objects in the dictionary, you will have to do a deep copy, because dict.copy() only does a shallow copy.

>>> import copy
>>> temp_years = copy.deepcopy(years)
>>> id(temp_years)
140641196228824
>>> id(years)
140641197662072
scmanjarrez
  • 407
  • 4
  • 8
0

You need to make a copy when you create the dict temp_years otherwise it will just function as a pointer to the original object (years). That's why the changes you're making to temp_years also change years. So all you need is to change that assignment line:

temp_years = years.copy()

You could also make it a deepcopy if it's a nested dict (otherwise you'll only get the top level keys):

import copy
temp_years = copy.deepcopy(years)

Check out this answer for more details: How to copy a dictionary and only edit the copy

rer
  • 1,198
  • 2
  • 13
  • 24