使用Python映射和其他function工具

这是相当不错的,但我正在学习/理解Python中的函数式编程。 以下代码:

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo, bar): print foo, bar map(maptest, foos, bars) 

生产:

 1.0 1 2.0 2 3.0 3 4.0 None 5.0 None 

问:有没有办法使用地图或任何其他function的工具在Python中产生以下没有循环等

 1.0 [1,2,3] 2.0 [1,2,3] 3.0 [1,2,3] 4.0 [1,2,3] 5.0 [1,2,3] 

正如旁注所示,如果在foo和bar之间存在依赖关系,实现将如何更改。 例如

 foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3,4,5] 

并打印:

 1.0 [2,3,4,5] 2.0 [1,3,4,5] 3.0 [1,2,4,5] ... 

PS:我知道如何天真地使用if,loops和/或generator,但我想学习如何使用function工具来实现相同的function。 是否只是添加一个if语句来maptesttesting或在maptest内部应用另一个filter贴图的情况?

最简单的方法是不通过不同的function,而是直接从maptest访问:

 foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo): print foo, bars map(maptest, foos) 

使用您的原始maptest函数,您也可以在map使用lambda函数:

 map((lambda foo: maptest(foo, bars)), foos) 

你熟悉其他function语言吗? 即你想学习如何python做function编程,或者你想了解function编程和使用python作为车辆?

另外,你是否理解列表parsing?

 map(f, sequence) 

与(*)直接等同于:

 [f(x) for x in sequence] 

事实上,我认为map()曾经被定义为从Python 3.0中删除,因为它是多余的(这没有发生)。

 map(f, sequence1, sequence2) 

大部分相当于:

 [f(x1, x2) for x1, x2 in zip(sequence1, sequence2)] 

(在序列长度不同的情况下,它的处理方式有所不同)正如你所看到的,当一个序列用完时map()填充None,而当最短序列停止时, zip()停止)

所以,为了解决你的具体问题,你试图产生结果:

 foos[0], bars foos[1], bars foos[2], bars # etc. 

你可以通过编写一个只有一个参数的函数来打印它,接下来是条形:

 def maptest(x): print x, bars map(maptest, foos) 

或者,您可以创build一个如下所示的列表:

 [bars, bars, bars, ] # etc. 

并使用您的原始maptest:

 def maptest(x, y): print x, y 

一种方法是预先明确地build立列表:

 barses = [bars] * len(foos) map(maptest, foos, barses) 

或者,你可以拉动itertools模块。 itertools包含许多巧妙的function,可以帮助你在python中进行函数式的懒惰评估编程。 在这种情况下,我们需要itertools.repeat ,在迭代它时将无限期地输出它的参数。 这最后一个事实意味着如果你这样做:

 map(maptest, foos, itertools.repeat(bars)) 

你将得到无尽的输出,因为只要其中一个参数仍然产生输出, map()一直持续下去。 但是, itertools.imap就像map() ,但是一旦最短迭代停止,就停止。

 itertools.imap(maptest, foos, itertools.repeat(bars)) 

希望这可以帮助 :-)

(*)在Python 3.0中有点不同。 在那里,map()基本上返回一个生成器expression式。

这是您正在寻找的解决scheme:

 >>> foos = [1.0, 2.0, 3.0, 4.0, 5.0] >>> bars = [1, 2, 3] >>> [(x, bars) for x in foos] [(1.0, [1, 2, 3]), (2.0, [1, 2, 3]), (3.0, [1, 2, 3]), (4.0, [1, 2, 3]), (5.0, [ 1, 2, 3])] 

我build议在使用map的时候使用list comprehension( [(x, bars) for x in foos][(x, bars) for x in foos]部分),因为它避免了每次迭代(这可能是非常重要的)函数调用的开销。 如果你只是在for循环中使用它,你可以通过使用generator生成器来获得更好的速度:

 >>> y = ((x, bars) for x in foos) >>> for z in y: ... print z ... (1.0, [1, 2, 3]) (2.0, [1, 2, 3]) (3.0, [1, 2, 3]) (4.0, [1, 2, 3]) (5.0, [1, 2, 3]) 

不同之处在于生成器的理解是延迟加载的 。

更新为了回应这个评论:

当然,你知道,你不复制栏,所有条目都是同样的栏列表。 所以如果你修改它们中的任何一个(包括原始的条),你修改它们。

我想这是一个有效的观点。 有两个解决scheme,我可以想到。 效率最高的可能是这样的:

 tbars = tuple(bars) [(x, tbars) for x in foos] 

因为元组是不可变的,所以这将防止通过这个列表理解的结果(或者如果你去那个路由发生器理解的话)修改它们。 如果你真的需要修改每一个结果,你可以这样做:

 from copy import copy [(x, copy(bars)) for x in foos] 

然而,这在内存使用和速度方面都可能有点贵,所以我build议不要这样做,除非你真的需要添加到其中每一个。

函数式编程是关于创build无副作用的代码。

map是一个function列表转换抽象。 你用它来取一些东西,把它变成一系列别的东西。

你正试图用它作为迭代器。 不要这样做。 🙂

下面是一个如何使用map来构build你想要的列表的例子。 有更短的解决scheme(我只是使用理解),但这将帮助您了解什么地图做得更好一点:

 def my_transform_function(input): return [input, [1, 2, 3]] new_list = map(my_transform, input_list) 

注意在这一点上,你只做了一个数据操作。 现在你可以打印它:

 for n,l in new_list: print n, ll 

– 我不确定你的意思是“没有循环”。 fp不是关于避免循环(你不能检查列表中的每个项目,而不访问每个项目)。 这是为了避免副作用,从而写出更less的错误。

 >>> from itertools import repeat >>> for foo, bars in zip(foos, repeat(bars)): ... print foo, bars ... 1.0 [1, 2, 3] 2.0 [1, 2, 3] 3.0 [1, 2, 3] 4.0 [1, 2, 3] 5.0 [1, 2, 3] 
 import itertools foos=[1.0, 2.0, 3.0, 4.0, 5.0] bars=[1, 2, 3] print zip(foos, itertools.cycle([bars])) 

下面是map(function, *sequences)函数的参数概述:

  • function是你的函数的名字。
  • sequences是任何数量的序列,通常是列表或元组。 map同时迭代它们并给出当前值的function 。 这就是为什么序列的数量应该等于你的函数的参数数量。

这听起来像你试图迭代一些function的参数,但保持其他人不变,不幸的是map不支持。 我发现了一个旧的build议 ,将这样的function添加到Python,但是地图结构非常干净和完善,我怀疑这样的function是否会被实现。

像其他人所build议的那样,使用像全局variables或列表parsing这样的解决方法。

这会做吗?

 foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest2(bar): print bar def maptest(foo): print foo map(maptest2, bars) map(maptest, foos) 

这个怎么样:

 foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo, bar): print foo, bar map(maptest, foos, [bars]*len(foos))