0

As I was debugging a small bit of code, I noticed something unexpected:

The for loop that cycles through the filename to remove the numbers, by looking at each character of the string and replacing it, seems to take a print of the filename as it exists in the first pass of the loop and cycles through those letters, so that if, as I do in the code, make changes to the string passed to the loop, python still looks for those letters that were in the string to begin with.

Have I just uncovered (for myself) a fundamental feature of the for loop, or is this just something weird that resulted from my code?

short_list = ['1787cairo.jpg', '237398rochester.jpg']
print short_list
for entry in short_list:
    entry_pos = short_list.index(entry)
    for char in entry:
        print entry, char, ord(char)
        if ord(char) in range (48,58):
            entry = entry.replace(char,'')
        print entry
    short_list[entry_pos] = entry              
print short_list
2
  • "... just something weird that resulted from my code" should be way, way down the list of the things that you consider in any given situation. Commented Feb 11, 2016 at 16:49
  • If an answer helped you, you should accept it as a solution. Commented Feb 18, 2016 at 2:42

2 Answers 2

7

The point here is that Python variables are really just names that point at objects. When you do for char in entry the for loop is iterating over whatever entry happens to point to; if you then reassign entry to point to something else, the iterator won't know that.

Note that if entry happened to be a mutable object, like a list, and you mutated the items in that object, the values seen by the iterator would change; again, this is because the iterator is pointing to the object itself.

Really though your code is over-complicated; rather than keeping indexes and replacing items in the list, you should be building up new lists with the changed items:

new_list = []
for entry in short_list:
    new_entry = ''
    for char in entry:
        if ord(char) not in range (48,58):
            new_entry += char
    new_list.append(new_entry)

and this can be shortened further to a nested list comprehension:

[''.join(char for char in entry if ord(char) not in range (48,58)) for entry in short_list]

(and, as a further improvement, your check of ord(char) can be replaced by char.isdigit().)

Sign up to request clarification or add additional context in comments.

2 Comments

I think I see what you mean, but let me try to re-phrase through my understanding: The for loop looks at whatever the variable "entry" points to, at that point in time of the code execution, and because it is a string, and this is immutable, the reassignment of "entry" that comes later is not recognized by the iterator, which is still looking at the object pointed to by "entry" originally? -However, if loop had been executed against a list, i.e. if "entry" was a list, which is mutable, rather than a string, which is not, the iterator would recognize the mutated list it was executing against?
Hmm, almost. The distinction is not really between mutable and immutable objects, but between mutating and reassigning. If entry was a list, but you reassigned it inside the for loop just as you are doing with the string, it would have the same result; but lists also have the ability to be mutated without reassigning, and if you did that, then the loop would see the new items. Hope that's a bit clearer.
0

Try instead

from string import digits

def remove_chars(s, bad_chars):
    """
    Return `s` with any chars in `bad_chars` removed
    """
    bad_chars = set(bad_chars)
    return "".join(ch for ch in s if ch not in bad_chars)

short_list = ['1787cairo.jpg', '237398rochester.jpg']
short_list = [remove_chars(entry, digits) for entry in short_list]

which gives

['cairo.jpg', 'rochester.jpg']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.