wrightboy
wrightboy

Reputation: 39

Is there a difference between traversing a list in python with range keyword and by use of other variable?

I am trying to make a program where I add a '*' in front of every line of my string.

This is what I did:

text = "Lists of animals, Lists of aquarium life"

lines = text.split(',')

for l in lines:
    l = '* ' + l
print(lines)

This gives the output:

['Lists of animals', 'Lists of aquarium life']

But if I make a simple change where I use:

for i in range(len(lines)):
    lines[i] = '* ' + lines[i]
print(lines)

This gives me the desired output that is:

['* Lists of animals', '* Lists of aquarium life']

Why is this happening? Can I make in-place changes to a list only when I traverse it through the range method?

Thanks for the help.

Upvotes: 0

Views: 126

Answers (4)

sahasrara62
sahasrara62

Reputation: 11228

This is happening because in code 1

text = "Lists of animals, Lists of aquarium life"
lines = text.split(',')
for l in lines:
    l = '* ' + l
print(lines)

a new string object l is being created ie l = '* ' + l, and that's all. it is created only and is not saved anywhere, not in the lines list. Because of this lines list is not updated and you are getting the same result.

To verify this, you can check the id of each element in the list.

text = "Lists of animals, Lists of aquarium life"
lines = text.split(',')

text = "Lists of animals, Lists of aquarium life"
lines = text.split(',')

print("checking id before modifictaion in the list")
for i in lines:
    print("text >  {},  id -> {}".format(i, id(i)))
    
for l in lines:
    print("line/text -> {}".format(i))
    print("before  modification id  - > {}".format(id(l)))
    l = '* ' + l
    print("after modification id -> {}".format(id(l)))
    
print("checking id after modifictaion in the list")
for i in lines:
    print("line/text -> {},  id -> {}".format(i, id(i)))

list object ids

checking id before modifictaion in the list
text >  Lists of animals,  id -> 140630273648640
text >   Lists of aquarium life,  id -> 140630273650240
line/text ->  Lists of aquarium life
before  modification id  - > 140630273648640
after modification id -> 140630273561344
line/text ->  Lists of aquarium life
before  modification id  - > 140630273650240
after modification id -> 140630273561344
checking id after modifictaion in the list
line/text -> Lists of animals,  id -> 140630273648640
line/text ->  Lists of aquarium life,  id -> 140630273650240

while in code2, the updated list object is saved back in the list itself, thus making the change that you desire.

Upvotes: 1

Kien Nguyen
Kien Nguyen

Reputation: 2691

Because the way for l in lines: l = '* ' + l works is something like this:

for i in range(len(lines)):
    l = lines[i]
    l = '* ' + l

So if you assign anything to l, it won't affect lines[i].

If you don't want to use the range method, use List comprehension instead:

lines = ['* ' + l for l in lines]

Upvotes: 1

Ashish M J
Ashish M J

Reputation: 700

In first case you are affecting only the variable l.

for l in lines:
    l = '* ' + l
print(l)

In the second case you are changing the list.

for i in range(len(lines)):
    lines[i] = '* ' + lines[i]
print(lines)

Now the output would be similar

Upvotes: 0

Timinator
Timinator

Reputation: 52

Your "l" is in the loop just a normal variable. If you wanna make changes directly in the list, you have to call it:

for l in lines:
    lines[l] = '* ' + l
    print(lines)

Otherwise the changes are just made to the variable "l".

Upvotes: 0

Related Questions