Hello Jochen, nice chat, I made this summarization to understand the problems, and I will drop it here in case it can help anyone, greeting!!
1. Dictionaries Store References, Not Copies
When you assign a list to a dictionary key:
high_priority_tasks = ["task1", "task2"]
prioritized_tasks = {"high_priority": high_priority_tasks}
The dictionary doesn’t create a new copy of the list. Instead, it stores a reference to the same list object in memory.
- Implication: Any changes made to the list (mutations) will reflect in the dictionary.
2. Mutability of Lists
Lists are mutable, meaning you can change their contents without creating a new object.
Example:
high_priority_tasks.append("task3")
print(prioritized_tasks["high_priority"]) # ["task1", "task2", "task3"]
The change to high_priority_tasks
is visible in the dictionary because the dictionary points to the same list object.
3. Reassignment Does Not Affect the Dictionary
If you reassign the list variable to a new list:
high_priority_tasks = ["new_task1", "new_task2"]
print(prioritized_tasks["high_priority"]) # ["task1", "task2", "task3"]
The dictionary still references the original list, not the new one. Reassignment only changes what the variable high_priority_tasks
points to, not what the dictionary references.
4. Modifying the Dictionary Directly
To update the dictionary with a new list:
prioritized_tasks["high_priority"] = ["new_task1", "new_task2"]
print(prioritized_tasks["high_priority"]) # ["new_task1", "new_task2"]
This replaces the reference in the dictionary with a reference to the new list.
5. Shallow Copy vs. Deep Copy
Dictionaries store shallow references to objects. This distinction matters when dealing with nested structures.
- Shallow Copy: Only the top-level references are copied.
import copy
shallow_copy = prioritized_tasks.copy()
- Deep Copy: Creates a completely independent copy of all objects.
deep_copy = copy.deepcopy(prioritized_tasks)
Example with Nested Lists:
high_priority_tasks = [["subtask1", "subtask2"]]
prioritized_tasks = {"high_priority": high_priority_tasks}
# Modifying a nested element affects the dictionary
high_priority_tasks[0][1] = "changed"
print(prioritized_tasks["high_priority"]) # [["subtask1", "changed"]]
To prevent this, use a deep copy.
6. Immutable Types in Dictionaries
Immutable types (like integers, strings, and tuples) behave differently:
- Dictionaries store copies of immutable types.
- Changing a variable holding an immutable value has no effect on the dictionary.
Example:
count = 5
prioritized_tasks = {"task_count": count}
count = 10
print(prioritized_tasks["task_count"]) # 5
Practical Examples
Use Case: Syncing Data
If you need synchronized updates between a list and a dictionary, use references:
tasks = ["task1", "task2"]
task_dict = {"tasks": tasks}
tasks.append("task3")
print(task_dict["tasks"]) # ["task1", "task2", "task3"]
Avoiding Unintended Changes
To avoid changes propagating unintentionally, create a copy:
task_dict["tasks"] = tasks.copy()