为什么`for`可以迭代对,但`lambda i,x:`不能`map`对?

时间:2015-06-30 05:53:34

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

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

使用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)

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

有没有(好)理由不这样做?

2 个答案:

答案 0 :(得分:4)

这不是$this->db->trans_off()的问题,而是问lambdadocumentation说:

  

如果传递了其他可迭代参数,则函数必须使用那么多参数,并且并行地应用于所有迭代中的项。

换句话说,函数必须使用与您传递的可迭代次数相同数量的参数。迭代中每个单独元素的大小无关紧要。

如果要将单个 iterable的每个元素作为多个参数传递,可以使用map和参数解包来转置序列:

zip

正如Ashwini所说,您也可以使用itertools.starmap代替>>> map(lambda i, x: x**i, *zip(*enumerate([5,10,15]))) [1, 10, 225]

答案 1 :(得分:1)

这是因为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]))

return的{​​{1}}值传递给enumerate()。因此,当您指定两个参数时,它只获得一个值。 如果您尝试:

lambda

你得到预期的输出

相关问题