如何做多个参数来映射函数在python中保持不变?


155

可以说我们有一个函数添加如下

def add(x, y):
    return x + y

我们要对数组应用map函数

map(add, [1, 2, 3], 2)

语义是我想将2添加到数组的每个元素。但是该map函数也需要第三个参数中的列表。

注意:为了简单起见,我将添加示例。我原来的功能要复杂得多。当然,设置yin add函数默认值的选项是毫无疑问的,因为每次调用都会更改它。


20
这与Lisp中的完全相同:map(add,[1,2,3],[2]*3) 通常,map将一个函数作为其第一个参数,如果该函数接受K个参数,则必须跟进K可迭代:addTriple(a,b,c) -> map(addTriple,[...],[...],[...])
watashiSHUN 2015年

Answers:


188

一种选择是列表理解:

[add(x, 2) for x in [1, 2, 3]]

更多的选择:

a = [1, 2, 3]

import functools
map(functools.partial(add, y=2), a)

import itertools
map(add, a, itertools.repeat(2, len(a)))

1
是的,但是与map功能相比有多快?
2012年

@山:非常相似,特别是如果add()是一个非平凡的功能
斯文·马纳赫

2
@Shan:在这种情况下,请看一下NumPy。如果这确实对您来说是一个问题,则列表理解之间的速度差异map()将无济于事。
Sven Marnach

3
@Shan:就像我之前说的,看看NumPy。如果可以对循环进行矢量化处理,则可能有助于加快循环速度。
Sven Marnach

1
@abarnert:尚不清楚OP是使用Python 2还是3。为确保示例在Python 2中有效,我添加了参数。(请注意,map()其行为类似于zip_longest()Python 2,而其行为却类似于zip()
Python3

60

文档明确建议这是以下用途的主要用途itertools.repeat

制作一个迭代器,一次又一次返回对象。除非指定了times参数,否则将无限期运行。用作map()被调用函数的不变参数的参数。还用于zip()创建元组记录的不变部分。

而且没有理由将通过len([1,2,3])作为times论点。map第一个可迭代项被消耗后立即停止,因此无限可迭代性就很好了:

>>> from operator import add
>>> from itertools import repeat
>>> list(map(add, [1,2,3], repeat(4)))
[5, 6, 7]

实际上,这等效repeat于docs中的示例:

>>> list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

这提供了一个不错的惰性函数式语言y解决方案,该解决方案也可以用Python迭代器术语完美地读取。


2
+1这应该是公认的答案。当然,它扩展到任意数量的参数,并带有一些常数和其他列表或生成器。例如:def f(x,y,z): \\ return '.'.join([x,y,z])然后:list(map(f, list('abc'), repeat('foo'), list('defgh')))返回['a.foo.d', 'b.foo.e', 'c.foo.f']
皮埃尔·D

5
在Python 2中,必须提供to的length参数repeat(),因为map()它将一直运行到该版本的Python中最长的迭代器用完为止,并填充None所有缺失的值。说“没有理由”传递参数是错误的。
Sven Marnach '16

@SvenMarnach的评论并不小:Python 3Python 2的行为大不相同!
奥古斯丁

36

使用列表理解。

[x + 2 for x in [1, 2, 3]]

如果你真的真的真的想用map,给它一个匿名函数作为第一个参数:

map(lambda x: x + 2, [1,2,3])

16

Map可以包含多个参数,标准方式是

map(add, a, b)

您的问题应该是

map(add, a, [2]*len(a))

不知道他的问题意味着什么,但是我认为添加接受2的值,而那些2不是固定的,应该像arg1一样来自用户。所以在这种情况下,我们应该如何在map下调用add(x,y)?
Bimlesh Sharma

15

正确的答案比您想像的要简单。只需做:

map(add, [(x, 2) for x in [1,2,3]])

并改变添加实现的元组即

def add(t):
   x, y = t
   return x+y

这可以处理两个添加参数都是动态的任何复杂用例。


14

有时我使用闭包解决了类似的情况(例如使用pandas.apply方法)

为了使用它们,您需要定义一个函数,该函数可以动态定义并返回该函数的包装器,从而有效地使参数之一成为常数。

像这样:

def add(x, y):
   return x + y

def add_constant(y):
    def f(x):
        return add(x, y)
    return f

然后,add_constant(y)返回一个可用于添加y到任何给定值的函数:

>>> add_constant(2)(3)
5

这样,您就可以在一次给定一个参数的任何情况下使用它:

>>> map(add_constant(2), [1,2,3])
[3, 4, 5]

编辑

如果您不想在其他地方编写闭包函数,则始终可以使用lambda函数即时构建它:

>>> map(lambda x: add(x, 2), [1, 2, 3])
[3, 4, 5]

13

如果可用,我将考虑使用numpy。这些类型的操作非常快:

>>> import numpy
>>> numpy.array([1,2,3]) + 2
array([3, 4, 5])

这是假设您的实际应用程序正在做数学运算(可以向量化)。


10

如果确实需要使用map函数(例如此处的类分配...),则可以使用具有1个参数的包装器函数,将其余函数传递给其主体中的原始函数;即:

extraArguments = value
def myFunc(arg):
    # call the target function
    return Func(arg, extraArguments)


map(myFunc, itterable)

肮脏和丑陋,仍然可以解决问题


1
闭包,我认为这增加了一些东西,再加上一个。类似于部分功能,如已接受的答案。
亚伦·霍尔

1
myFunc需要return Func(arg, extraArguments)
PM 2Ring

我站在正确的@ PM2Ring上,这是真的。更新了代码。
Todor Minakov

Func在哪里定义?因为我收到了Func的名称错误
Nikhil Mishra,

Func是你的原函数的名称- OP紧将add例如
托多尔Minakov

6

我相信星图是您所需要的:

from itertools import starmap


def test(x, y, z):
    return x + y + z

list(starmap(test, [(1, 2, 3), (4, 5, 6)]))

您的示例中的错字:list(starmap(test,[(1,2,3),(4,5,6)]))
Teebu

哦是的 谢谢:)
Shqi.Yang

1

将多个参数传递给一个map函数。

def q(x,y):
    return x*y

print map (q,range(0,10),range(10,20))

这里q是一个多说法,函数映射()的调用。确保两个范围的长度,即

len (range(a,a')) and len (range(b,b')) are equal.



1
def func(a, b, c, d):
 return a + b * c % d
map(lambda x: func(*x), [[1,2,3,4], [5,6,7,8]])

通过使用lambda包装函数调用并使用星号拆包,您可以使用任意数量的参数进行映射。


lambda非常慢,请改用functools
Wang

0

另一个选择是:

results = []
for x in [1,2,3]:
    z = add(x,2)
    ...
    results += [f(z,x,y)]

调用多个函数时,此格式非常有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.