【发布时间】:2017-01-18 21:17:23
【问题描述】:
我看到下面的代码将一个列表过滤成两个类:
reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49, 58, 76, 82, 88, 90],([],[]))
它是如何工作的? ([], []) 看起来在 lambda 中初始化 (a, b),但它是如何一步一步工作的呢?
这似乎也不适用于 Python 3。这是为什么呢?
【问题讨论】:
我看到下面的代码将一个列表过滤成两个类:
reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49, 58, 76, 82, 88, 90],([],[]))
它是如何工作的? ([], []) 看起来在 lambda 中初始化 (a, b),但它是如何一步一步工作的呢?
这似乎也不适用于 Python 3。这是为什么呢?
【问题讨论】:
它是如何工作的?
([], [])看起来在 lambda 中初始化(a, b),但它是如何一步一步工作的呢?
在每一点,reduce 都会看到一个左侧操作数 (a, b),它是一对列表(最初是两个空列表)和一个元素 c。它将列表[c] 添加到a 或b,具体取决于它是否大于60,并返回新的列表对。因此,它最终会分别返回大于 60 和小于 60 的元素对。
这似乎也不适用于 Python 3。这是为什么呢?
在 Python3 中,您不能再定义一个显式采用元组的函数 - tuple unpacking has been removed。所以
def foo((a, b)):
...
在 Python3 中是非法的。这也是这里的问题(除了 lambda 形式)。
【讨论】:
reduce(lambda a,c: (a[0]+[c],a[1]) if c > 60 else (a[0],a[1]+[c]), [49, 58, 76, 82, 88, 90],([],[]))
要回答您的第一个查询,等效于使用 for 循环:
>>> c = [49, 58, 76, 82, 88, 90]
>>> final = ([], [])
>>> for val in c:
... if val > 60:
... final[0].append(val)
... else:
... final[1].append(val)
...
>>> final
([76, 82, 88, 90], [49, 58])
在python3中等价的是:
In [8]: import functools
In [9]: functools.reduce(lambda x,c: (x[0]+[c],x[1]) if c > 60 else (x[0],x[1] + [c]), [49, 58, 76, 82, 88, 90],([],[]))
Out[9]: ([76, 82, 88, 90], [49, 58])
【讨论】:
看看下面的实验:
>>> reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49],([],[]))
([], [49])
>>> reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49,58],([],[]))
([], [49, 58])
>>> reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49,58,76],([],[]))
([76], [49, 58])
>>> reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49,58,76,82],([],[]))
([76, 82], [49, 58])
>>> reduce(lambda(a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49,58,76,82,88,90],([],[]))
([76, 82, 88, 90], [49, 58])
函数reduce描述如下:
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
在我们的示例中,function 是一个 lambda 函数,第一个参数是一个二元素元组 (a,b),第二个参数是一个整数 c,从列表中挑选出来进行处理。由于函数产生一个 2 元素的列表元组,它被初始化为 ([], [])。处理开始时,如果元素>60,则将其添加到元组的第一个列表中;否则它被添加到元组的第二个列表中。
a+[c] 的语法实际上是列表的extend 语法。我们不能做a+c,因为a 是一个列表,而c 是一个整数。同样,对于b+[c]
【讨论】: