Reputation: 389
I have to reverse every word in a list which length is greater that 4. So I tried:
for word in words:
if len(word) >= 5:
word = word[::-1]
and it didn't work. But this:
for i in range(len(words)):
if len(words[i]) >= 5:
words[i] = words[i][::-1]
works fine. What's the diference?
Upvotes: 5
Views: 229
Reputation: 3
The reason why is because when you do the first one, you are only modifying the word
variable, you aren't modifying the words
list. But when you are using the second example, you are modifying it because you are using words[i] = words[i][::-1]
. In this example, you are modifying the words list because the words[i]
is the modifier; you are setting the element of the list into something.
Upvotes: 0
Reputation: 6927
To understand what's going on here, compare what happens in a similar example, where I want to set any numbers bigger than 20 to -1:
numbers = [1, 10, 30, 40, 50]
for number in numbers:
if number > 20:
number = -1
print(numbers) # same as before!
Why does this not set the last three numbers to -1? Because number
here is a value—it's location in memory is totally unrelated to the contents of the numbers
array. word
in your example is exactly the same.
Inside your loop, word
is bound to a new piece of memory whose contents happen to be the same as the current entry of the words
array. By the time word
is defined in your first snippet, you have lost any way to manipulate the array location it came from. By iterating over the indexes like in your second snippet, you keep a back door into the array.
These two references,
might help understand the following tricky business: instead of a list of strings, what happens if we have a list of lists?
listOfLists = [[1], [2, 3], [9, 10, 11], [40, 50, 60, 70]]
for l in listOfLists:
if len(l) >= 3:
l[:] = l[::-1] # note that `[:]`!!!
print(listOfLists)
This actually will reverse any sub-list that has more than 2 elements. Can you understand why? If so, take this gold star: 🌟!
Upvotes: 0
Reputation: 18916
When you iterate through a list Python creates references (with same ID) to your variable. However these are not editable in place. Check this for instance: Can't modify list elements in a loop Python
Consider this example which hopefully can help you out:
words = ['abcdef','abc']
for ind,i in enumerate(words):
print('Loop {}'.format(ind))
i = i[::-1]
print('words equal {}'.format(words))
words[ind] = words[ind][::-1]
print('words equal {}'.format(words))
print()
Returns:
Loop 0
words equal ['abcdef', 'abc'] # <--- after changing i (nothing changed)
words equal ['fedcba', 'abc'] # <--- after changing words[ind]
Loop 1
words equal ['fedcba', 'abc'] # <--- after changing i (nothing changed)
words equal ['fedcba', 'cba'] # <--- after changing words[ind]
in your case
The most simple solution would be to use a list comprehension. Consider this:
rWords = [word[::-1] if len(word) >=5 else word for word in words]
Upvotes: 1
Reputation: 313
word = word[::-1]
word is not referenced to the words[i]. You can do this with functional programming.
new_words = list(word[::-1] if len(word) >= 5 else word for word in words)
Upvotes: 0