When you run the for loop, it takes the id of the provided object and iterates over it.
In the first code snippet, you are changing an element of the original object, so when the iterator reaches the second element it takes the updated value.
However, in the second case you are creating a new object with different values, but the object that you provided to the loop stays the same.
A way of checking this behaviour is to get the id of the variable before and after the modifications, and see how it does not change in the first case but it changes in the second case:
my_list = [1, 2, 3]
original_id = id(my_list)
# Check if the object identification changes after modifying one element
my_list[2] = 4
new_id = id(my_list)
if original_id == new_id:
print("1st case: The ID stays the same")
else:
print("1st case: The ID has changed")
# Check now what happens if you create a new list
my_list = [3, 2, 1]
new_id = id(my_list)
if original_id == new_id:
print("2nd case: The ID stays the same")
else:
print("2nd case: The ID has changed")
The obtained result is the following:
1st case: The ID stays the same
2nd case: The ID has changed
forloop gets an iterator once ofnumat the beginning of the loop, which then looks at each value in the list one by one.num = ...replaces the variablenumwith a different list, but that's of no interest to theforloop, because it doesn't look atnumagain after it has already gotten its iterator.numwhile you continue to iterate over the original list.