Reputation: 2794
I'm aware that this is an example of code you should never write, and I'm not asking for the right approach. My concern is that I don't understand its behaviour, so I was hoping someone could shed light on it:
def foo(list_of_chars):
'''Returns the set of words that can be obtained by removing one character from list_of_chars.'''
result = set()
my_copy = list(list_of_chars)
for elem in my_copy:
my_copy.remove(elem)
result.add(''.join(my_copy))
my_copy = list(list_of_chars)
return result
I would have expected either behaviour from this function (let's say list_of_chars
is ['h', 'e', 'l', 'l', 'o']
):
my_copy
at the end of each iteration, so when the for
loop assigns the next element to elem it is the same as if we had never touched the list (so we do iterate over 'h', 'e', 'l', 'l', 'o');What actually happens is stranger: we iterate over 'h', 'l', 'l', 'o', so 'e' is skipped, but it's the only character that is skipped. Other examples behave in the same way: only the second element of list_of_chars
is overlooked. Can someone explain this? (Python 2 and 3 yield the same result).
Upvotes: 0
Views: 43
Reputation: 522109
The for
loop does not "read" my_copy
again on every iteration, but my_copy.remove
does.
for elem in my_copy:
my_copy.remove(elem)
On the first iteration, my_copy
in both lines refers to the same object. You're actually modifying the object for
iterates over. However, at the end of the iteration, you replace my_copy
with something else. The for
loop retains its original object reference, but my_copy.remove
refers to the current version of my_copy
. So now the object the for
loop iterates over and the object that you remove
an element from are two different objects.
Hence remove
interferes with the loop only on the first iteration.
Upvotes: 4