0

I have a question on the remove method of lists in python when using for loop. When I am not using the remove method, the loop works as expected.

a_copy = a = [1, 2, 3, 4, 5]
print(a_copy)
b = ["a", "b", "c"]
for item in a:
    if item not in b:
        print(item)

Output:

[1, 2, 3, 4, 5]
1
2
3
4
5

However, when trying to remove elements using the same if statement in the for loop, the output was weird:

a_copy = a = [1, 2, 3, 4, 5]
print(a_copy)
b = ["a", "b", "c"]
for item in a:
    if item not in b:
        print(item)
        a_copy.remove(item)

Output:

[1, 2, 3, 4, 5]
1
3
5

Anyone has an opinion on what's wrong here, please?

Lei Lei
  • 11
  • 1

3 Answers3

1

You are removing from the list items but then again you are iterating over it. Use a_copy = copy.deepcopy(a) would give you the same result. In your code your pointing to the same object. When you are deep copying it, you have separate opject with same content as your initial list.

import copy
a = [1, 2, 3, 4, 5]
a_copy = copy.copy(a)
print(a_copy)
b = ["a", "b", "c"]
for item in a:
    if item not in b:
        print(item)
        a_copy.remove(item)

Originally used copy.deepcopy() but as mentioned in the comment, if there is no mutable objects you can get away with copy.copy() or simply list.copy() (in this case a.copy()). Deep Copy is much more slow and memory demanding. So better to not use here.

(Also note that, just adding from the comment itself, we can copy list via slicing - a_copy = a[:] is also another to make a copy of the list just like copy.copy()).

user2736738
  • 30,591
  • 5
  • 42
  • 56
0

a_copy is not a copy of a. they point to the same object because you use a simple assignment statement. When you remove an element from a_copy, the element in a also changes:

>>> for item in a:
...     if item not in b:
...         print(item)
...         a_copy.remove(item)
...         print(a_copy, a)
...
1
[2, 3, 4, 5] [2, 3, 4, 5]
3
[2, 4, 5] [2, 4, 5]
5
[2, 4] [2, 4]
Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31
0

You are mutating the list as you iterate over it (and a and a_copy are references to the same list)

I think initially the first item in a is 1, which you remove. Next time round the loop, the second item in the list is 3 (the list is now 2, 3, 4, 5). Same thing happens again - 2 is removed and third item in 3, 4, 5 is 5

Someone will have a fuller explanation with a better understanding of iterators in Python (or they will look at the source code) but essentially mutating collections during iteration generally causes unexpected behaviour and is best avoided.

Chris
  • 1,644
  • 1
  • 11
  • 15