Reputation: 305
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
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,..]
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
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
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
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
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
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
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