[实用库/轮子] 让 Python 的高阶函数支持链式调用

2018-05-22 20:31:47 +08:00
 Thoxvi

项目地址

希望大佬们不吝啬 Star 鼓励一下 ;-)

为了解决什么问题?

举个例子,当你在原生 Python 里使用函数式编程的时候,不免会写出如下代码:

  # 先给所有元素 +1,
  # 再筛选大于 4 的元素,
  # 打印,
  # 再让所有元素 +1,
  # 最后让 l 变成 List,方便后续的操作
  
  l = [1, 2, 3, 4, 5]
  l = filter(lambda x: x > 4, map(lambda x: x + 1, l))
  l = list(l)
  print(l)
  # [5, 6]
  
  l = list(map(lambda x: x + 1, l))
  assert l==[6, 7]

这里有几个让人不舒服的地方

  1. 类似于 filtermap 之类的操作,只能是嵌套的,而不能是链式调用
  2. list 化要也需要嵌套使用
  3. 打印需要中断操作、保存现场、打印、恢复现场等一系列的操作
  4. Python 对高阶函数库的支持不如像 Kotlin 之类的那么精细(虽然自己可以实现,但是颇为麻烦)

如何使用?

fc 库能够优雅地解决以上问题,而你只需要在环境终端里输入

$ pip install fc

然后上述的代码就可以改成:

from fc import Fc

# 建议用括号 () 把链式的 Fc 包起来,就可以实现多行链式调用了(虽然有点丑,但是是无可奈何的。。。

l = (
  Fc([1, 2, 3, 4, 5])
    .map(lambda x: x + 1)
    .filter(lambda x: x > 4)
    .print()  # [5, 6]
    .map(lambda x: x + 1)
    .done()
)
assert l == [6, 7]

并且当你不需要 print 的时候,只需要简单在前面加上一个 # 即可轻松注释。

注:Fc 不会改变传入的 Iterable,即以只读的形式对待传入的参数,每次链式都会创建一个新的 Fc(时间复杂度为 O(1),可以忽略不计),满足函数式无副作用的思想。

性能问题?不用担心

fc 考虑了性能上的优化策略,所有的支持链式的 Fc 的类成员函数基本上都是使用生成器的方式返回(yield),即实现了惰性求值,优化了时间和空间效率,只有个别函数由于实现原因(需要从后向前计数等)会转换成数组,并且这种函数都会被标注在文档上,方便进行性能排查。

当然,如果你有任何建议(不限于性能优化等)都可以提 issue 或者发邮件到 A@Thoxvi.com 联系我。

; )

函数名命名规范问题

本项目默认使用的是驼峰命名,但由于 Python 一贯是使用下划线命名,所以 fc 提供了一个 Fc_ 的类,除了把驼峰式例如 getAfter 变成了 get_after 以外,功能上没有任何差别,可以放心使用。(不过因为是动态生成的,所以 IDE 可能不会提供自动补全,所以如果不是刚需的话,不是特别建议手撸下划线式(当然不用太在意这个,功能、性能又不会有影响,就是怕手误打错而已))。

2357 次点击
所在节点    分享创造
10 条回复
silhouette
2018-05-22 20:38:31 +08:00
6666
Arnie97
2018-05-22 20:44:32 +08:00
之前有一个 Shell 管道画风的库,和这个库功能较为类似: https://github.com/0101/pipetools
Thoxvi
2018-05-22 20:48:56 +08:00
@Arnie97 卧槽我去瞅瞅代码,看看能引进啥
hourann
2018-05-22 21:09:28 +08:00
链式调用确实是个痛点…
Thoxvi
2018-05-22 21:12:16 +08:00
@hourann 是的,痛了好久终于忍不住想治治了。。。
msg7086
2018-05-22 23:17:18 +08:00
这是把 Python 写出了 Ruby 的风格吗……
Thoxvi
2018-05-22 23:30:44 +08:00
@msg7086 设计思路是偏向于混合 Js 和 Kotlin 的,Python 完全不支持代码块啊。。。
inflationaaron
2018-05-22 23:45:45 +08:00
对于函数式来说 point free style 会更好一点
msg7086
2018-05-23 00:26:53 +08:00
@Thoxvi 有半残废的 Lambda 嘛。
Thoxvi
2018-05-23 07:44:20 +08:00
@msg7086 没错…的确是半残废…

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/456945

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX