【问题标题】:Why `for` can iterate pairs, but `lambda i,x:` cannot `map` pairs?为什么`for`可以迭代对,但`lambda i,x:`不能`map`对?
【发布时间】:2015-09-16 19:05:05
【问题描述】:

我在存档中找不到这样的问题。

使用for 可以解包迭代对:

>>> for i, x in enumerate([5,10,15]): print('x[%d]=%d' % (i, x))
x[0]=5
x[1]=10
x[2]=15

或者也可以 解压它们:

>>> for x in enumerate([5,10,15]): print(x)
(0, 5)
(1, 10)
(2, 15)

然而,当使用map()时,这个解包是不可能的:

>>> list(map(lambda i, x: x**i, enumerate([5,10,15])))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'x'

这是为什么?设计选择?为什么?

我想有人可以实现这样的包装器:

def map1(func, *iterables):
    from inspect import signature
    params = signature(func).parameters
    if len(params) == 1:
        yield from map(func, *iterables)
    else:
        yield from map(lambda x: func(*x), *iterables)

(适用于任何情况)

或另一个盲目地解包参数:

def map2(func, *iterables):
    yield from map(lambda x: func(*x), *iterables)

(我猜后者会造成一些麻烦)

是否有(好的)理由不这样做?

【问题讨论】:

  • 您正在寻找itertools.starmap
  • enumerate的情况可以使用list(map(lambda i, x: x**i, itertools.count(), [5,10,15]))

标签: python python-3.x lambda iterable enumerate


【解决方案1】:

这不是lambda 的问题,而是map 的问题。 documentation 说:

如果传递了额外的可迭代参数,则函数必须接受那么多参数并并行应用于所有可迭代的项目。

换句话说,该函数必须采用与您传递的可迭代数量相同数量的参数。可迭代对象中每个单独元素的大小不相关。

如果您想将 single 可迭代的每个 元素 作为多个参数传递,可以使用 zip 和参数解包来转置序列:

>>> map(lambda i, x: x**i, *zip(*enumerate([5,10,15])))
[1, 10, 225]

正如 Ashwini 所说,您也可以使用 itertools.starmap 而不是 map

【讨论】:

  • 转置序列序列(+1)的好技巧。但我想对于枚举的特殊情况,可以只做map(f, range(len(lst)), lst),不是吗?
  • @mescalinum:是的,你可以在这种情况下这样做。
【解决方案2】:

这是因为enumerate() 返回一个枚举对象,该对象在多个枚举对象中保存一对值。如果你尝试:

>>> enumerate([5,10,15])
>>> <enumerate at 0x39152d8>
>>>e = enumerate([5,10,15])

>>> for i in e:
    print e

<enumerate object at 0x03915080>
<enumerate object at 0x03915080>
<enumerate object at 0x03915080>

你在他的声明中做了什么:

map(lambda i, x: x**i, enumerate([5,10,15]))

returnenumerate() 值传递给lambda。因此,当您指定两个参数时,它只会获得一个值。 如果你尝试:

>>>map(lambda i: i[0] * i[1], enumerate([5,10,15]))
>>> [0,10,30]

你得到预期的输出

【讨论】:

    猜你喜欢
    • 2017-02-09
    • 1970-01-01
    • 2020-10-22
    • 2021-03-01
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 2020-04-09
    相关资源
    最近更新 更多