如何将列表中的每个元素乘以一个数字?

136

我有一个列表:

my_list = [1, 2, 3, 4, 5]

如何将my_list中的每个元素乘以5?输出应为:

[5, 10, 15, 20, 25]

2
使用map比使用for-loop更好。 - Tony
10
列表推导式(几乎总是)比 map 更好(如果使用 lambda,则始终如此)。 - ShadowRanger
10个回答

192

你可以使用一个列表推导式

my_list = [1, 2, 3, 4, 5]
my_new_list = [i * 5 for i in my_list]

>>> print(my_new_list)
[5, 10, 15, 20, 25]

请注意,列表推导通常比使用for循环更高效:

my_new_list = []
for i in my_list:
    my_new_list.append(i * 5)

>>> print(my_new_list)
[5, 10, 15, 20, 25]

作为另一种选择,这里提供了一个使用流行的Pandas包的解决方案:

import pandas as pd

s = pd.Series(my_list)

>>> s * 5
0     5
1    10
2    15
3    20
4    25
dtype: int64

或者,如果您只想要列表:

>>> (s * 5).tolist()
[5, 10, 15, 20, 25]

最后,可以使用map,尽管这通常不被赞同。

my_new_list = map(lambda x: x * 5, my_list)

然而,使用map通常效率较低。根据此问题已删除的回答中ShadowRanger的评论:

之所以“没有人”使用它是因为一般来说,这是一种性能劣化。在CPython中考虑使用map的唯一情况是当您使用内置函数作为映射函数时实现C;否则,map将与更具Python风格的列表推导式或genexpr(它们也更明确地说明了它们是惰性生成器还是急切的list创建器;在Py3上,如果不将map调用包装在list中,则您的代码将无法工作)。如果您正在使用lambda函数和map,请停止,您正在错误地使用它。

他在此答复中发表的另一条评论如下:

请不要教人们使用带有lambdamap;一旦您需要一个lambda,您最好使用列表推导式或生成器表达式。如果您聪明,可以使map在很多情况下工作,例如在这种情况下,map((5).__mul__,my_list),尽管在这种特定情况下,由于字节码解释器对简单的int数学进行了一些优化,[x * 5 for x in my_list]更快,而且更符合Pythonic和更简单。


以大写字母开头的变量名不符合 Python 的规范。而且它们是列表,不是数字。因此,我建议使用 l1l2 作为变量名。 - Remi Guan
5
禁止使用"l"作为变量,因为字母"l"和数字1很容易混淆。我在原作者的问题中使用了变量,我认为你对问题的编辑弊大于利。 - Alexander
1
如果你觉得我的编辑不好,你可以编辑问题来改进它。此外,我们可以选择其他变量而不是 l1,比如 l_1list_1 等等。这些都比 Num_1 更好。 - Remi Guan

36

一个更快的方法是以向量化的方式进行乘法,而不是循环遍历列表。Numpy已经提供了一种非常简单和方便的方法,您可以使用它。

>>> import numpy as np
>>> 
>>> my_list = np.array([1, 2, 3, 4, 5])
>>> 
>>> my_list * 5
array([ 5, 10, 15, 20, 25])

请注意,这不适用于Python的原生列表。如果你将一个数字与列表相乘,它会将该数字作为大小重复该列表的项。

In [15]: my_list *= 1000

In [16]: len(my_list)
Out[16]: 5000
如果你想要一个纯Python的方法,使用列表推导式基本上是最Pythonic的方式。
In [6]: my_list = [1, 2, 3, 4, 5]

In [7]: [5 * i for i in my_list]
Out[7]: [5, 10, 15, 20, 25]

除了列表推导式这种纯函数式的方法,你也可以使用内置的map()函数来实现如下:

In [10]: list(map((5).__mul__, my_list))
Out[10]: [5, 10, 15, 20, 25]

该代码将列表my_list中的所有项传递到数字5__mul__方法中,并返回类似迭代器的对象(在Python-3.x中)。然后,您可以使用内置函数list()将迭代器转换为列表(在Python-2.x中,您不需要这样做,因为map默认返回一个列表)。

基准测试:

In [18]: %timeit [5 * i for i in my_list]
463 ns ± 10.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [19]: %timeit list(map((5).__mul__, my_list))
784 ns ± 10.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [20]: %timeit [5 * i for i in my_list * 100000]
20.8 ms ± 115 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: %timeit list(map((5).__mul__, my_list * 100000))
30.6 ms ± 169 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [24]: arr = np.array(my_list * 100000)

In [25]: %timeit arr * 5
899 µs ± 4.98 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我对numpy方法为什么“极快”很感兴趣?您能否详细说明或指向一些资源?我不确定什么是矢量化。 - Aerinmund Fagelson
1
@AerinmundFagelson 在这里 -> https://dev59.com/ClsW5IYBdhLWcg3wVWHj - Mazdak
@Kasramvd 那个链接是不正确的。该链接讨论了 向量化 的另一种含义,即单指令多数据(一次性对多个数据应用操作,就像 GPU 所做的那样)。在 NumPy 的上下文中,向量化 指的是使用快速预编译的 C 循环来操作一个数据序列,而不是使用纯 Python。 - xjcl
这是一个准确的链接:https://www.pythonlikeyoumeanit.com/Module3_IntroducingNumpy/VectorizedOperations.html#Vectorized-Operations - xjcl

21
您可以像这样原地完成操作:
 l = [1, 2, 3, 4, 5]
 l[:] = [x * 5 for x in l]

这不需要额外的导入,并且非常符合Pythonic的风格。


另外:如果您想查找更多信息,该概念被称为“列表推导式”。 - Michael
2
我宁愿使用l = [x * 5 for x in l]而不是l[:] = [x * 5 for x in l]。后者会创建一个新的列表,然后用它来覆盖l的内容,而不是只重新分配引用,这样更便宜。如果你真的担心空间问题,只需使用循环迭代并进行原地变异即可。 - cs95

6

由于我认为您对Python还不熟悉,让我们走捷径,使用for循环遍历您的列表,并将每个元素相乘并附加到新列表中。

使用for循环

lst = [5, 20 ,15]
product = []
for i in lst:
    product.append(i*5)
print product

使用列表推导式,这也与使用for循环相同,但更具有"Python风格"。
lst = [5, 20 ,15]

prod = [i * 5 for i in lst]
print prod

“长路”有什么好处吗?它更长——因此更难阅读——并且并不更易于编写。 - lirtosiast
1
好的,也许你对我的标题有误解,我从未说过它更好,只是想向他展示如何在不使用推导式的情况下完成它。因为根据我的经验,在我刚学Python时,我很难理解推导式的概念。 - ellaRT
哦,好的。我无法直接联系,因为我从函数式语言开始学习编程。 - lirtosiast
我明白了,好的。我编辑了答案,也包括了高效的做法。 - ellaRT

4

使用地图(不是最好的方法,但是解决问题的另一种方法):

list(map(lambda x: x*5,[5, 10, 15, 20, 25]))

此外,如果您正在使用numpy或numpy数组,您可以使用以下方法:
import numpy as np
list(np.array(x) * 5)

为什么不使用lambda而不是定义timesfive函数? - Vimanyu

3
from functools import partial as p
from operator import mul
map(p(mul,5),my_list)

这是一种方法,你可以用它来做... 你的老师可能知道一个简单得多的方法,可能已经在课堂上讲过了。


你可以使用lambda表达式来完成,而不需要导入语句。此外,你的代码片段返回一个map对象,除非将其转换为列表,否则没有用处。list(map(lambda x: 5*x, my_list))。 - castle-bravo
@castle-bravo 它的实用性取决于你需要用它做什么...有许多方法可以实现这个解决方案(正如我所提到的...) - Joran Beasley
4
请不要教导人们使用 maplambda,一旦需要使用 lambda,最好使用列表推导式或生成器表达式。如果您聪明的话,您可以很多时候在不用 lambda 的情况下使用 map,例如在这个例子中,您可以使用 map((5).__mul__, my_list)。尽管在这种特定情况下,由于字节码解释器对简单整数数学运算进行了一些优化,[x * 5 for x in my_list] 更快、更符合 Python 风格和更简单。 - ShadowRanger

2

my_list中的每个元素乘以k:

k = 5
my_list = [1,2,3,4]
result = list(map(lambda x: x * k, my_list))

导致结果为:[5, 10, 15, 20]

1
这可能是最优雅的方式。 - Lawhatre

0
var1 = [2,4,6,8,10,12]

#for Integer multiplier us   int(x).__mull__ with map    
var2 = list( map(int(2).__mul__,var1 ))
#for float multiplier
var2 = list( map(float(2.5).__mul__,var1 ))

0

我发现使用列表推导式或map时只使用一个对象名x很有趣。 请注意,每当x被重新分配时,它的id(x)会改变,即指向不同的对象。

x = [1, 2, 3]
id(x)
2707834975552
x = [1.5 * x for x in x]
id(x)
2707834976576
x
[1.5, 3.0, 4.5]
list(map(lambda x : 2 * x / 3, x))
[1.0, 2.0, 3.0]
id(x) # not reassigned
2707834976576
x = list(map(lambda x : 2 * x / 3, x))
x
[1.0, 2.0, 3.0]
id(x)
2707834980928

-1

最好的方法是使用列表推导式:

def map_to_list(my_list, n):
# multiply every value in my_list by n
# Use list comprehension!
    my_new_list = [i * n for i in my_list]
    return my_new_list
# To test:
print(map_to_list([1,2,3], -1))

返回: [-1,-2,-3]

这只是将被接受的答案转换成一个函数。你可能可以用超过一半的 SO 回答来做到这一点,但它并没有增加任何东西,也不是 OP 所要求的。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接