在长度不等的列表上使用Python的map

1 投票
1 回答
1271 浏览
提问于 2025-04-18 12:46

在Lisp语言中,我以前常常这样做,因为我知道这样不会出错:

 [3]> (mapcar #'+ '(1 2 3) '(1 2))
(2 4)

在Python中,做同样的事情似乎会出错:

>>> map(lambda x,y : x + y, [1,2,3], [1,2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

在Python中有没有一个函数,能像Lisp那样处理长度不一样的列表?或者,有没有办法改变map的行为?

1 个回答

5

这个问题适合用 Python 2.x 来解决(感谢 @user2357112)。在 Python 3.x 的文档中,关于 map 的说明是:

当最短的输入可迭代对象用完时,迭代器就会停止。

所以,在 Python 3.x 中,你可以直接使用 map

In [1]: list(map(lambda a, b: a + b, [1, 2, 3], [1, 2]))
Out[1]: [2, 4]

但是在 Python 2.x 的文档中,关于 map 的说明是:

如果一个可迭代对象比另一个短,它会被假设用 None 项目来扩展。

所以,你应该先用 zip 把这些列表组合起来:

In [2]: map(sum, zip([1, 2, 3], [1, 2]))
Out[2]: [2, 4]

因为 zip 会把返回的列表截断到最短的参数序列的长度(正如文档中所说的那样)。

你也可以定义自己的函数 zip_with这个答案中的例子):

import itertools

def zip_with(f, *coll):
    return itertools.starmap(f, itertools.izip(*coll))

使用示例:

In [3]: list(zip_with(operator.add, [1, 2, 3], [1, 2]))
Out[3]: [2, 4]

撰写回答