This is one of the mistakes! Python that can avoid newbies.
words[:] is a magical sauce here.
Note:
>>> words = ['cat', 'window', 'defenestrate'] >>> words2 = words[:] >>> words2.insert(0, 'hello') >>> words2 ['hello', 'cat', 'window', 'defenestrate'] >>> words ['cat', 'window', 'defenestrate']
And now without [:] :
>>> words = ['cat', 'window', 'defenestrate'] >>> words2 = words >>> words2.insert(0, 'hello') >>> words2 ['hello', 'cat', 'window', 'defenestrate'] >>> words ['hello', 'cat', 'window', 'defenestrate']
The main thing to note here is that words[:] returns copy existing list, so you iterate over a copy that doesn't change.
You can check if you are referencing the same lists using id() :
In the first case:
>>> words2 = words[:] >>> id(words2) 4360026736 >>> id(words) 4360188992 >>> words2 is words False
In the second case:
>>> id(words2) 4360188992 >>> id(words) 4360188992 >>> words2 is words True
It is worth noting that [i:j] is called the slice operator, and it returns a fresh copy of the list, starting from index i to (but not including) index j .
So words[0:2] give you
>>> words[0:2] ['hello', 'cat']
Skipping the initial index means that it defaults to 0 , and skipping the last index means that it defaults to len(words) , and as a result you get a copy of the whole list.
If you want to make your code a little more readable, I recommend the copy module.
from copy import copy words = ['cat', 'window', 'defenestrate'] for w in copy(words): if len(w) > 6: words.insert(0, w) print(words)
This is basically the same as your first code snippet, and much more readable.
Alternatively (as mentioned by DSM in the comments) and in python> = 3, you can also use words.copy() which does the same.