I'm trying to modify item in a list using IN and Indexing. While modifying via indexing, the item was actually changed. However, when I try to change via IN keyword, it seems that the item in the list does not change.
- What's the difference between both method internally?
- When using IN, does it mean that you iterate through the list and assign the value of each item in the variable in for statement?
lines = ['hi', 'hello']
for line in lines:
line = '*'
for i in range(len(lines)):
lines[i] = '#'
print(lines)
Output:
['hi#', 'hello#']
CodePudding user response:
In the first loop, 'line' is merely a placeholder for value received from lines in each iteration.
Whereas, in the second loop, you're directly referring to the individual elements in the list using their index
lines = ['hi', 'hello']
print(f"Outside the loop - id(lines): {id(lines)}\n")
for line in lines:
line = '*'
print(f"id(line): {id(line)}")
print("\n")
for i in range(len(lines)):
lines[i] = '#'
print(f"id(lines[{i}]: {id(lines[i])}")
print(f"\n\nid(lines): {id(lines)},id(lines[0]): {id(lines[0])}, id(lines[1]): {id(lines[1])}\n")
print(lines)
Look at the output. You'll notice that id of 'line' is same throughout the loop and it's different from lines[0] and lines[1]. That means, line and lines[0] are not the same and they're located at different locations in the memory.
OUTPUT:
Outside the loop - id(lines): 2831707232384
id(line): 2831707722928
id(line): 2831707722928
id(lines[0]: 2831707976816
id(lines[1]: 2831707977456
id(lines): 2831707232384,id(lines[0]): 2831707976816, id(lines[1]): 2831707977456
['hi#', 'hello#']
CodePudding user response:
The pythonic way is to create a new list and don't try to change elements of a list
inplace
lines = ['hi', 'hello']
print([f'{line}#' for line in lines])
Output
['hi#', 'hello#']
Both loops can't change a string. They are immutable in python. Your second loop is assigning a new reference to a new string to the given index.
We can verify that by comparing the id
of the strings
lines = ['hi', 'hello']
print(*map(id, lines))
for i in range(len(lines)):
lines[i] = '#'
print(*map(id, lines))
print(lines)
Output
139964185810032 139963627798960
139963551752432 139963317214640
['hi#', 'hello#']
Mutable types (for example a list
) behave differently
lines = ['hi', 'hello']
lines = [[*i] for i in lines] # convert strings to mutable lists
print(*map(id, lines))
for line in lines:
line = ['#']
print(*map(id, lines))
lines = [''.join(i) for i in lines] # convert lists to immutable strings
print(lines)
Output
139963318712752 139963316794224
139963318712752 139963316794224
['hi#', 'hello#']