我们在使用Python
完成日常任务时,经常会遇到一些很小的辅助性的需求,又不想花费时间去搜索是否已有现成的库实现了这些功能,往往则需要自己临时编写一些逻辑或函数。
而事实上已经有勤劳伟大的开发者编写了集成众多小功能于一身的第三方库,本文要给大家介绍的funcy
就是其中非常实用的一个,它汇集了数量惊人的实用函数及装饰器,帮助我们使用Python
更好的践行「函数式编程」理念。
图 1
funcy
的设计宗旨就是汇集一系列花哨的实用函数,其在不断地迭代过程中,已经积累下相当多的功能,下面我们就来学习其中代表性的一些。
使用pip install funcy
完成安装后,推荐大家按照如下方式进行导入:
import funcy as fc
funcy
中的count()
可以生成一个可指定起点和步长的无限迭代器,默认参数start=0
,step=1
,我们可以用它来替代常规的<while
循环+自增变量的逻辑:
for i in fc.count():
print(i, end='\r')
# 当i大于等于1000时停止迭代,否则继续
if i >= 1000:
break
funcy
中的flatten()
可以用来展平任意的嵌套数组:
图 2
funcy
中的interpose()
可以用来将指定元素插入到对应数组的两两元素之间:
图 3
在funcy
中有两种从原始列表中删除指定元素的方法,方式1是使用remove()
来传入条件判断函数来删除满足条件的元素,类似filter()
的方式:
图 4
第二种方式是利用funcy
中的without()
,它可以帮我们从原始数组中排除指定的1个或多个元素,譬如下面我们把2、5、7、9排除掉:
图 5
funcy
中提供了group_by()
函数,帮助我们传入函数,作用于指定数组的每个元素上,并自动按照返回的结果进行分组输出,就像下面的例子那样:
图 6
funcy
中的partition()
帮助我们对输入的数组做指定长度的切片划分,譬如下面的例子,我们对列表[0, 1, ..., 10]进行长度为3的切片拆分,剩余不足长度3的部分就会被丢弃:
图 7
与partition()
功能相似,funcy
中的chunks()
会在等长度拆分数组的同时,保留末尾长度不足的部分单独输出:
图 8
利用funcy
中的pairwise()
,我们可以对输入数组从头开始,将相邻的成对元素以二元组的形式输出:
图 9
利用merge()
,我们可以将传入的多个同类型数据结构拼成一个完整的,这在合并集合或字典时尤其受用:
图 10
有些情况下我们执行某些函数时,由于某些原因导致报错,但如果我们并不希望遇到错误就中断的话,就需要自己写额外的try...except...
逻辑,而funcy
中的silent()
则可以让这个过程变得很省事:
图 11
上面介绍的silent()
会帮助传入函数遇到任意错误时返回None,而funcy
中的ignore()
则赋予我们指定错误类型,以及报错时设定返回值的能力:
图 12
下面要介绍的方法非常的实用,想象一下这样的场景:你书写的某个函数接受输入,然后经过一段耗时不菲的计算过程输出结果,但在函数实际调用过程中经常遇到重复的传入参数。
这种时候你肯定希望自己的函数可以“记忆”下执行过的参数与输出结果,省得大量重复计算,而funcy
中的memoize
装饰器就可以帮助我们快速改造自己的函数:
图 13
而函数的缓存记录可查询,可自定义添加,也可以手动清空:
图 14
很多情况下,print()
循环过程变量变化情况的debug
方式虽然很粗糙,但有些时候下却很方便,但在一些诸如「列表推导」等情况下却不太方便注入print()
代码。
而利用funcy
中的tap()
函数,我们可以将迭代变量传入,并填写对应说明标签,即可快速查看运行过程,tap()
的逻辑其实很简单,相当于把输入值打印一下再原封不动地返回,但既然有现成的API,何乐而不为~
图 15
有些情况下,我们希望程序中的某个函数在整个程序的生命周期中只执行一次,譬如创建数据库连接等操作时,而funcy
中提供的装饰器once
就可以帮助我们快速实现这个功能,并且保证了线程安全:
图 16
除了以上介绍的这些功能之外,funcy
还拥有其他众多的实用 API,你可以进入其官方文档进行查看( https://funcy.readthedocs.io/en/stable/ )。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8