RuntimeError: dictionary changed size during iteration

avatar
Borislav Hadzhiev

Last updated: Feb 17, 2023
5 min

banner

# Table of Contents

  1. RuntimeError: dictionary changed size during iteration
  2. RuntimeError: Set changed size during iteration in Python

# RuntimeError: dictionary changed size during iteration

The Python "RuntimeError: dictionary changed size during iteration" occurs when we change the size of a dictionary when iterating over it.

To solve the error, use the copy() method to create a shallow copy of the dictionary that you can iterate over, e.g. my_dict.copy().

runtimeerror dictionary changed size during iteration

Here is an example of how the error occurs.

main.py
my_dict = {'a': 1, 'b': 2, 'c': 3} # โ›”๏ธ RuntimeError: dictionary changed size during iteration for key in my_dict: print(key) if key == 'b': del my_dict[key]

dictionary changed size during iteration

It is not allowed to change the size of a dictionary while iterating over it.

Changing the size of a dictionary (e.g. removing items from it or adding items to it) while iterating over it is confusing for the Python interpreter.

# Using the dict.copy() method to solve the error

One way to solve the error is to use the dict.copy method to create a shallow copy of the dictionary and iterate over the copy.

main.py
my_dict = {'a': 1, 'b': 2, 'c': 3} for key in my_dict.copy(): print(key) if key == 'b': del my_dict[key] print(my_dict) # ๐Ÿ‘‰๏ธ {'a': 1, 'c': 3}

using dict copy method to solve the error

The dict.copy method returns a shallow copy of the object on which the method was called.

Iterating over a dictionary and changing its size messes up with the iterator, so creating a shallow copy and iterating over the copy solves the issue.

We are not allowed to iterate over the dictionary and change its size, however, iterating over a copy of the dictionary and changing the size of the original dictionary is permitted.

# Converting the keys of the dictionary to a list to solve the error

You can also convert the keys of the dictionary to a list and iterate over the list of keys.

main.py
my_dict = {'a': 1, 'b': 2, 'c': 3} for key in list(my_dict.keys()): print(key) if key == 'b': del my_dict[key] print(my_dict) # ๐Ÿ‘‰๏ธ {'a': 1, 'c': 3}

converting keys of dictionary to list

The dict.keys method returns a new view of the dictionary's keys.

main.py
my_dict = {'id': 1, 'name': 'Bobby Hadz'} print(my_dict.keys()) # ๐Ÿ‘‰๏ธ dict_keys(['id', 'name'])

We used the list() class to create a copy of the keys in the example.

The list class takes an iterable and returns a list object.

You can also use the dict.items() method in a similar way.

# Converting the items of the dictionary to a list to solve the error

However, notice that when using dict.items(), we have access to the key and value of the current iteration.

main.py
my_dict = {'a': 1, 'b': 2, 'c': 3} for key, value in list(my_dict.items()): print(key, value) # ๐Ÿ‘‰๏ธ a 1, b 2, c 3 if key == 'b': del my_dict[key] print(my_dict) # ๐Ÿ‘‰๏ธ {'a': 1, 'c': 3}

converting items of dictionary to list

We used the list() class to create a copy of the dictionary's items.

The dict.items method returns a new view of the dictionary's items ((key, value) pairs).

main.py
my_dict = {'id': 1, 'name': 'Alice'} print(my_dict.items()) # ๐Ÿ‘‰๏ธ dict_items([('id', 1), ('name', 'Alice')])

# Using a dict comprehension to get around the error

You can also use a dict comprehension to solve the error.

main.py
my_dict = {'a': 1, 'b': 2, 'c': 3} keys_to_remove = ['a', 'b'] my_dict = {key: value for key, value in my_dict.items() if key not in keys_to_remove} print(my_dict) # ๐Ÿ‘‰๏ธ {'c': 3}

We stored the keys we want to remove in a keys_to_remove list and used a dict comprehension to iterate over the key-value pairs of the dictionary.

Dict comprehensions are very similar to list comprehensions.

They perform some operation for every key-value pair in the dictionary or select a subset of key-value pairs that meet a condition.

On each iteration, we check if the current key is not present in the keys_to_remove list.

If the condition is met, the current key-value pair is returned.

All of the keys from the keys_to_remove list get removed from the dictionary.

# Using two separate for loops to solve the error

You can also use two separate for loops to solve the error.

main.py
my_dict = {'a': 0, 'b': 1, 'c': 0} keys_to_remove = [] for key, value in my_dict.items(): if not value: keys_to_remove.append(key) print(keys_to_remove) # ๐Ÿ‘‰๏ธ ['a', 'c'] for key in keys_to_remove: del my_dict[key] print(my_dict) # ๐Ÿ‘‰๏ธ {'b': 1}

The first for loop iterates over the dictionary and adds the keys that should be removed to a list.

The second for loop iterates over the list of keys and uses the del statement to remove them.

We never actually change the dictionary's size while iterating over it, so the error isn't raised.

Which approach you pick is a matter of personal preference. I'd go with using the dict.copy() method.

The method returns a shallow copy of the dictionary, so it's quite easy to read and solves the issue of not being able to iterate over a dictionary and change its size.

# RuntimeError: Set changed size during iteration in Python

The Python "RuntimeError: Set changed size during iteration in Python" occurs when we change the size of a set object when iterating over it.

To solve the error, use the copy() method to create a shallow copy of the set that you can iterate over, e.g. my_set.copy().

runtimeerror set changed size during iteration

Here is an example of how the error occurs.

main.py
my_set = {'Alice', 'Bob', 'Carl'} for i in my_set: print(i) if i == 'Bob': # โ›”๏ธ RuntimeError: Set changed size during iteration my_set.remove(i)

It is not allowed to change the size of a set while iterating over it.

# Using the set.copy() method to solve the error

One way to solve the error is to use the set.copy() method to create a shallow copy of the set object and iterate over the copy.

main.py
my_set = {'Alice', 'Bob', 'Carl'} for i in my_set.copy(): print(i) if i == 'Bob': my_set.remove(i) print(my_set) # ๐Ÿ‘‰๏ธ {'Alice', 'Carl'}
Iterating over a set and changing its size messes up with the iterator, so creating a shallow copy and iterating over the copy solves the issue.

# Using a list comprehension to filter the set object

We could have also used a list comprehension to filter out elements from the set.

main.py
my_set = {'Alice', 'Bob', 'Carl'} my_new_set = set([i for i in my_set if i != 'Bob']) print(my_new_set) # ๐Ÿ‘‰๏ธ {'Carl', 'Alice'}
List comprehensions are used to perform some operation for every element, or select a subset of elements that meet a condition.

Make sure to pass the list to the set() class to convert the result to a set object.

Here is another example of using a list comprehension to filter out elements from a set.

main.py
my_set = {1, 2, 3, 4, 5, 6} my_new_set = set([i for i in my_set if i % 2 == 0]) print(my_new_set) # ๐Ÿ‘‰๏ธ {2, 4, 6}

The final set contains only elements that are divisible by 2.

Set objects are an unordered collection of unique elements.

# Using two for loops to solve the error

You can also use 2 for loops to solve the error.

main.py
my_set = {'Alice', 'Bob', 'Carl', 'Bobby'} elements_to_remove = [] for element in my_set: if 'Bob' in element: elements_to_remove.append(element) print(elements_to_remove) # ๐Ÿ‘‰๏ธ ['Bob', 'Bobby'] for element in elements_to_remove: my_set.remove(element) print(my_set) # ๐Ÿ‘‰๏ธ {'Carl', 'Alice'}

The first for loop iterates over the set and adds the elements that should be removed to a new list.

The second for loop iterates over the list and removes each element from the set.

We never remove items from the set while iterating over it, so the error isn't raised.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev