如何使用toolz制作总是返回列表的咖喱版地图

时间:2017-11-16 06:36:05

标签: python toolz

如果我使用

导入toolz
from toolz.curried import *

然后map将自动变为curry形式,所以

map(func,[[1,2],[3,4]])

可以写成

map(func)([[1,2],[3,4]])

但curried map总是返回一个可迭代的。我的方法是定义一个总是返回列表的curry lmap。但是简单的尝试

lmap=compose(list,map)

不起作用,例如

lmap(len)([[1,2],[3,4]])

将给出

  

----------------------------------------------- ----------------------------
TypeError Traceback(最近一次调用   最后)in()   ----> 1 lmap(len)([[1,2],[3,4]])

     

C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ toolz \ functoolz.py in
  致电(自我,* args,** kwargs)
      466 ret = self.first(* args,** kwargs)
      467 for f in self.funcs:
   - > 468 ret = f(ret)
      469返回       470

     

TypeError:'咖喱'对象不可迭代

那么如何定义一个有条理的lmap

2 个答案:

答案 0 :(得分:2)

你的方式是错误的。被传递给撰写的map是咖喱,但不是一个完整的表达。当你把它称为

lmap(len)([[1,2],[3,4]])

它将len传递给lmap,它返回toolz.functoolz.curry等效于

map(len)

然后尝试在其上调用list

list(map(len))
显然无法正常工作。如果没有失败,则完整表达式将等同于:

list(map(len))([[1,2],[3,4]])

而您正在寻找的电话是:

list(map(len), [[1,2],[3,4]])

所以实际上currying在这里没有多大意义。

你可能想要这些内容:

def lmap(g): return compose(list, map(g)) 

可根据需要调用:

>>> lmap(len)([[1,2],[3,4]])
[2, 2]

但说实话,问题看起来有点人为 - toolz在统一懒惰中的最大优势。转换为list会抛弃大部分内容。

答案 1 :(得分:0)

此问题目前在Google搜索结果中排在第一位,原因是Toolz错误'curry' object is not iterable。触发此处未提及的错误消息的另一种方法是尝试将toolz.curried.pipe与咖喱迭代器一起使用,就像pipe本身是咖喱一样:

>>> transform = pipe(
    map(lambda x: x + 1),
    map(lambda x: x + x)
    )
>>> list(transform([3,4,5]))
TypeError: 'curry' object is not iterable

这里,第一个咖喱图作为最终参数传递给第二个; 尽管管道是从curried命名空间中重新导出的,但管道却不是curried的。解决方案是升级到尚未使用的toolz版本0.10.0(如果尚未使用的话),而改用toolz.curried.compose_left,它实际上是咖喱pipe

>>> transform = compose_left(
    map(lambda x: x + 1),
    map(lambda x: x + x)
    )
>>> list(transform([3,4,5]))
[8, 10, 12]