AdR
AdR

Reputation: 305

Multiply every element of a list by a number

I would like to multiply all elements of a list by a number. I know the other ways to do it but I want to know Why isn't this working? I am getting the very same list as an output.

lst = eval(input('enter a list'))
for num in lst:
     num = num * 2
print(lst)

Upvotes: 7

Views: 10589

Answers (7)

Garrett R
Garrett R

Reputation: 2662

As everyone else pointed out, the correct way to do this is by indexing into the list:

myList = range(5)
for i in range(len(myList)):
    myList[i] *= 2
print myList #[0,2,4,..]

A Little Bit About Pass By Assignment

Your loop, which uses the for num in list notation does not modify the list. Because the loop variable num takes a value of type int at each iteration of the loop, since ints are immutable (i.e its value cannot be changed) in python, num gets a copy of the integer value.

This changes when the object in the list is mutable and is passed by reference. Consider the following:

class X: 
    def __init__(self):
         self.val = 1

myList = [X() for i in range(5)]
print [element.val for element in myList] #1,1,1,1,1

for el in myList:
    el.val = 2

print [element.val for element in myList] #2,2,2,2,2 

Now, since myList contains a list of X objects which are mutable, the loop variable el has a reference copied into it. The reference points to the same object in memory that the reference in original myList points to. So when you change the object using the loop variable, the objects referred to in the original myList are also changed.

This Pass By Reference talks about it in greater depth.

Upvotes: 2

Remi Guan
Remi Guan

Reputation: 22282

It isn't working because, you're using for loop on a list and defining/changing the num global variable, not the elements in lst list.

For example:

>>> l = [1, 5, 8]
>>> for num in l:
...     num *= 2
...     
... 
>>> num
16
>>> l
[1, 5, 8]

In this case, in the first loop, num is 1 (the first element in l), and sure 1 * 2 gives 2.

Then, num become 5 since 5 is the second element in the list. After num * 2, num become 10.

In the second for loop, it become 8 * 2, 16. it doesn't change again because the for loop is ended.

However, you didn't change anything of the list during this loop. Because for only gets the elements in the list, and put it into a temporary variable.

And when you change that temporary variable inside the for loop, you didn't change anything of the list.

Upvotes: 6

Anton Protopopov
Anton Protopopov

Reputation: 31672

It's better to use ast.literal_eval then eval due to safety. You could read about it here. You could solve that with list comprehension:

import ast
lst = ast.literal_eval(input('enter a list'))
lst = [num*2 for num in lst]
print(lst)

List comprehensions are faster then map with lambda. Timing:

lst = list(range(1000))

In [56]: %timeit list(map(lambda num:num*2,lst))
10000 loops, best of 3: 169 us per loop

In [57]: %timeit [num*2 for num in lst]
10000 loops, best of 3: 80.5 us per loop

Upvotes: 3

midori
midori

Reputation: 4837

You are not changing the elements of the lst, do it like this:

for num in range(len(lst)):
    lst[num] *= 2

Upvotes: 4

vks
vks

Reputation: 67968

lst=eval(input('enter a list'))
lst=list(map(lambda num:num*2,lst))
print (lst)

You need to update the lst.

Upvotes: 3

hpaulj
hpaulj

Reputation: 231375

Two clean expressions:

In [360]: lst=list(range(10))

to change in-place:

In [361]: for i,v in enumerate(lst):
   .....:     lst[i]=v*2
   .....:     
In [362]: lst
Out[362]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

to produce a new list:

In [363]: [v*2 for v in lst]
Out[363]: [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]

For input I'd prefer explicitly splitting and converting a string:

In [365]: lst = [int(x) for x in input().split()]
10 11 0 1 2 
In [366]: lst
Out[366]: [10, 11, 0, 1, 2]

Upvotes: 3

Selcuk
Selcuk

Reputation: 59184

Well, since you wrote "I know the other ways to do it but I want to know Why isn't this working?", here is your answer: You are only modifying the temporary loop variable num, not the list itself. Try this:

for i, num in enumerate(lst):
     lst[i] = lst[i] * 2

Upvotes: 4

Related Questions