user285372
user285372

Reputation:

Looping over a slice copy of a list

I am trying to understand the difference between looping over a list and looping over a "slice" copy of a list.

So, for example, in the following list, the element whose length is greater than 6 is appended to the beginning of the list:

words = ['cat', 'window', 'blahblah']

for word in words[:]:
    if len(word) > 6:
        words.insert(0, word)

print(words)

words = ['blahblah', 'cat', 'window', 'blahblah']

I, then, run the following to see why it is not the correct way of doing it, but my interpreter freezes and I have to exit. Why does this happen? I am simply appending something to the start of my list which is allowed since lists are mutable...

for word in words:
    if len(word) > 6:
        words.insert(0, word)

Could someone please help me understand why this last bit stops my program?

Upvotes: 2

Views: 1617

Answers (6)

Mahhos
Mahhos

Reputation: 101

In case you want to see what exactly happens in the background of inserting into the list (words) vs slice copy (words[:]), you can change/tab the print to see the infinite loop, as the infinite loop cannot be seen in its original location in the script:

for w in words:  
if len(w) > 6:
    words.insert(0, w) 
print(words) #prints after each insert, let you see the infinite loop 

Upvotes: 0

Md Mahfuzur Rahman
Md Mahfuzur Rahman

Reputation: 2359

words[:] means a new copy of the words and length is fixed. So you are iterating over a fixed list.

But in the second situation, iterating over and extending the same list which makes it infinity.

words = ['cat', 'window', 'blahblah']
new_words = [_ for _ in words if len(_) > 6]
print(new_words)

Upvotes: 0

Leon
Leon

Reputation: 32464

The following loop

for word in words:
    // do something

is roughly equivalent to the following one (when words is a list and not another kind of iterable):

i = 0
while i != len(words):
    word = words[i]
    // do something (assuming no 'continue' here)
    i += 1

Therefore, when while looping you insert something into your list before the current position, then during the next iteration you end up handling the same element as for the previous iteration. In your case this results in an infinite loop.

Upvotes: 1

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48067

When you are doing words[:], you are iterating over the copy of list, whereas with words, you are iterating over the original copy of list.

In the case II, your interpreter is freezing because when you are at the last index, the condition is satisfied and you insert the item at the beginning of the list. Now, there is one more index which is required to be iterated by the loop. Again, the condition satisfies and it keeps on going like this resulting in an infinite loop.

Where as that is not the case with words[:], as the list in which you are appending and the one on which you are iterating are different.

Upvotes: 1

L3viathan
L3viathan

Reputation: 27273

The list words has three elements. The copy of words also does. You iterate over the copy, insert something in words if the current element is longer than 6 characters, and are done.

Now let's see what happens when you iterate over words directly:

The first two iteration steps are fine, because the condition is False. But since len('blahblah') > 6, you are now inserting 'blahblah' at the beginning of the list. Now the list looks like this:

['blahblah', 'cat', 'window', 'blahblah']

You've just seen the third element, so now the loop continues and looks at the fourth element, but because you inserted something at the beginning of the list the rest of the list shifted and the new fourth element is 'blahblah' again. blahblah is still longer than 6 characters, you insert it again in the beginning and are stuck in an infinite loop:

['cat', 'window', 'blahblah']
   ^
['cat', 'window', 'blahblah']
            ^
['cat', 'window', 'blahblah']
                       ^
['blahblah', 'cat', 'window', 'blahblah']
                                   ^
['blahblah', 'blahblah', 'cat', 'window', 'blahblah']
                                               ^
...

Upvotes: 5

AlvaroP
AlvaroP

Reputation: 400

In your first approach, you are performing a shallow copy of your list words, iterating over it and appending long words to the list words. So you iterate over a fixed list, and extend a different list.

With your last approach, the list words grows with each iteration, so you are in an endless loop as you are looping over it and it keeps growing.

Upvotes: 1

Related Questions