2

I'm new to Python, and i'm struggling to understand the output of this simple program:

list = os.listdir(os.getcwd())
print(list)
print()
for element in list:
    print(element)
    if 'txt' not in element: list.remove(element)

Which gives me this output :

['examples_list.txt', 'generate_patterns.py', 'lehoczky_example_3.txt', 'patterns', 'test.py', 'test2.py']

examples_list.txt
generate_patterns.py
patterns
test2.py

why are certain elements (such as 'lehoczky_example_3.txt'), ignored by the "for" loop?

Juan M Rivas
  • 127
  • 1
  • 8

2 Answers2

10

You cannot remove elements from the list while looping through it. Try and loop over a copy of the list, or create a new one with only the elements you want to keep.

See also Python strange behavior in for loop or lists

Community
  • 1
  • 1
Marco Mariani
  • 13,556
  • 6
  • 39
  • 55
  • 1
    Technically you _can_ remove elements from a list while looping, you just won't get the result you may have expected. – WildCrustacean Oct 26 '10 at 12:53
  • @bde - right. In some other programming languages, where you have `for (i = 10; i >= 0; i--)` loops, this reversed iteration is used to remove individual elements safely. – eumiro Oct 26 '10 at 12:55
  • @eumiro - reverse traversal of a list while removing elements is also valid in Python. But the real Pythonic solution is to create a new list from the old, as you posted in your answer. – PaulMcG Oct 26 '10 at 13:28
  • 1
    sure, I meant cannot in the "you cannot cross the beams" sense :-) – Marco Mariani Oct 26 '10 at 13:38
  • thanks Marco! I feel a little bit silly now that I know what the problem was – Juan M Rivas Oct 26 '10 at 14:23
  • Nothing silly, it's a quite common mistake, coming from other environments. By the way, if you make a habit of treating objects as immutable, functional languages will appear less weird -- where most of the times, the _only_ way to manipulate an object is to build a new one :-) – Marco Mariani Oct 26 '10 at 14:56
5

Try list comprehension. This will keep your list of files and create a new list noTxtFiles without touching the files.

files = os.listdir(os.getcwd())
noTxtFiles = [ element for element in files if 'txt' not in element ]

And don't use the reserved word list for a variable name.

eumiro
  • 207,213
  • 34
  • 299
  • 261