Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Collections (Retired) Slices Deleting Or Replacing Slices

Trying to get the whole "dont loop a list copy it" thing

I saw someone do this:

for item in copied_list: 
    if item in alphabet:
        while True:
            try:
                my_list.remove(item)
            except:
                break

to me this looks like:

  • looping over a copy of the list
  • but then taking action on the list itself
  • have I got that right?
  • is that the way to loop a list
  • without the list going nuclear?

Thanks Jason, I feel like that cemented it for me.

2 Answers

Hi John,

Your explanation of the code is correct. You're looping over a copy of the list, that remains unchanged, while you modify the original list.

You don't always have to loop over a copy of the list though. If you're not planning to modify the list then it's ok to loop over it.

The main thing with this is that you don't want to loop over a list while you're modifying it. It can lead to unintended consequences.

Suppose that you have a list of numbers and the goal is to remove all the odd numbers.

Here's some output from the python shell:

>>> my_list = [9, 7, 4, 1, 8, 5]
>>> for num in my_list:
...     if num % 2 == 1:
...             my_list.remove(num)
...
>>> print(my_list)
[7, 4, 8]
>>>

Notice that it removed all the odd numbers except for 7.

What happens is that the for loop keeps its own internal index of which item it's looking at. The first time through the loop the index is 0 and it's looking at the 9. This is removed since it's odd and then every number after it moves down one index to occupy that empty space. The 7 was at index 1 but now it's at index 0 and the 4 is at index 1 now.

It loops again and the internal index is 1 now. It's looking at the 4 now because that is what's currently at index 1. It ends up skipping over the 7 and it never gets examined.

This is why you want to loop over a copy of the list if you intend to modify that list.

Here's the same code, except looping over a copy. It correctly removes all the odd numbers.

>>> my_list = [9, 7, 4, 1, 8, 5]
>>> for num in my_list[:]:
...     if num % 2 == 1:
...             my_list.remove(num)
...
>>> print(my_list)
[4, 8]
>>>

I used slice notation here to get a copy of the list.

Idan Melamed
Idan Melamed
16,285 Points

Yeah that's one way of changing a list by looping a copy.

Thanks Idan