Python 简化函数调用的3种技巧

描述

假设有一个函数,这个函数需要接收4个参数,并返回这4个参数的和:

def sum_four(a, b, c, d):
  return a + b + c + d

如果需要固定最后前三个参数,仅改变最后一个参数的值,这时候可能需要这么调用:

> > > a, b, c = 1, 2, 3

 > > > sum_four(a=a, b=b, c=c, d=1)
7

 > > > sum_four(a=a, b=b, c=c, d=2)
8

 > > > sum_four(a=a, b=b, c=c, d=3)
9

 > > > sum_four(a=a, b=b, c=c, d=4)
10

这样写实在是太丑了,如果用 Map 函数,是否能简化代码?

答案是肯定的,但是Map函数【一般】只能接受单一元素,如果你强行使用的话,它会报这样的错:

> > > list(map(sum_four, [(1, 2, 3, 4)]))
Traceback (most recent call last):
  File "< stdin >", line 1, in < module >
TypeError: sum_four() missing 3 required positional arguments: 'b', 'c', and 'd'

怎么解决?

方案1: itertools.starmap

可以使用 itertools 的函数 starmap 替换Map.

它与Map不同,允许接受一个元组作为传入sum_four的参数。

> > > import itertools
 > > > list(itertools.starmap(sum_four, [(1, 2, 3, 4)]))
[10]

非常棒,这样的话,上述问题就可以使用starmap函数解决:

 > > > import itertools

 > > > ds = [1, 2, 3, 4]

 > > > items = ((a, b, c, d) for d in ds)

 > > > list(items)
 [(1, 2, 3, 1), (1, 2, 3, 2), (1, 2, 3, 3), (1, 2, 3, 4)]

 > > > list(itertools.starmap(sum_four, items))
 [7, 8, 9, 10]

请注意 items 是一个生成器,这是为了避免 items 过大导致内存消耗量过大。平时开发的时候注意这些细节,能够使你和普通的开发者拉开差距。

方案2: functools.partial

第二种解决方案是使用 partial 函数固定前三个参数。

根据文档,partial将“冻结”函数的参数的某些部分,从而生成简化版的函数。

因此上述问题的解决方案就是:

 > > > import functools
 > > > partial_sum_four = functools.partial(sum_four, a, b, c)
 > > > partial_sum_four(3)
9
 > > > # 这样就可以使用map函数了:
 > > > list(map(partial_sum_four, ds))
[7, 8, 9, 10]

方案3: itertools.repeat()

事实上,Map 函数是允许传递可迭代参数的,但是有一个有趣的特点,他会用每个可迭代对象里的项作为传入函数的不同参数。这样说可能太过于抽象了,来看看实际的例子:

> > > list(map(sum_four, [1,1,1,1], [2,2,2,2], [3,3,3,3], [1,2,3,4]))
 [7, 8, 9, 10]

明显,每次都使用了不同数组中对应下标的项传入函数进行计算。

这样,我们可以使用这个特点进行优化。

itertools.repeat() 函数能够根据参数产生一个迭代器,该迭代器一次又一次返回对象。不指定times参数,它将无限期运行。

而 Map 函数会在最短的可迭代对象被迭代完后,就会自动停止运行。

结合这两个特点,上述问题的解决方案就出来了:

> > > import itertools
 > > > list(map(sum_four, itertools.repeat(a), itertools.repeat(b), itertools.repeat(c), ds))
 [7, 8, 9, 10]

这招非常巧妙,缺点是能读懂的人不多。不过没关系,计算机世界中某些东西知道就好,你并不一定需要去使用它。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分