六行代码实现 Python 管道

2021-01-10 17:14:24 +08:00
 abersheeran

不多说,直接上代码。

from functools import partial

class F(partial):
    def __ror__(self, other):
        if isinstance(other, tuple):
            return self(*other)
        return self(other)

使用样例。

range(10) | F(filter, lambda x: x % 2) | F(sum)

更详细的前因后果介绍,可以看 https://aber.sh/articles/Python-Pipe/ ,实在是懒得复制到 V2EX 调样式了。有兴趣的就看看,没兴趣的就复制代码去用就完事。

小小的得瑟一下,这是最近几天写的最满意、最有用的代码。妙手偶得之~

12393 次点击
所在节点    Python
122 条回复
abersheeran
2021-01-10 21:15:38 +08:00
@Jirajine 有道理。待会就发一个。
abersheeran
2021-01-10 21:24:08 +08:00
@aijam 各有各的好。我这个一共只有六行代码,工作原理简单,对 Python 原本用法几乎无改变,可以和现在的代码混合使用,使用成本低、收益高。
你给的那个库,需要从数据源头包一层,返回的也是个它的自定义对象,没办法做到随意的混合使用。当然,它那个只需要在源头和结尾申明一下,可以少输入几个字符,这方面还是有优势的。
fpure
2021-01-11 00:18:19 +08:00
不错,很优雅的代码
alan0liang
2021-01-11 08:18:57 +08:00
想到了 ECMAScript 的 proposal pipeline op: https://github.com/tc39/proposal-pipeline-operator
大概长这样:
64 |> Math.sqrt |> (x => x + 1) |> console.log
或者:
64 |> Math.sqrt |> # + 1 |> console.log
frostming
2021-01-11 08:42:12 +08:00
我记得很久之前哪里看到过,类似小技巧一类的文章
不过你这个可以柯里化一下更好:
range(10) | F(filter)(lambda x: x % 2) | F(sum)
frostming
2021-01-11 08:42:44 +08:00
这样我可以:
Filter = F(filter)
Sum = F(sum)
abersheeran
2021-01-11 09:13:31 +08:00
@frostming 嗯? F 从 partial 继承而来,本就可以绑定参数的。😀
Ritter
2021-01-11 09:37:54 +08:00
一直以为 partial 是个函数 原来是个类。。。
zone10
2021-01-11 10:10:51 +08:00
我之前看过一个函数式的库, 也很有意思.我现在有个思路是用更高效的语言来实现这个,不知道能不能保证 Python 便利性的同时提高性能
abersheeran
2021-01-11 10:13:38 +08:00
@zone10 partial 本身就是 C 写的,虽然在标准库里也有一个 C 模块不可用时的 Pure Python 降级代替,但编译正常的 CPython 都会用那个 C 版本。所以这里的性能损耗几乎不可能更低了。
abersheeran
2021-01-11 10:17:22 +08:00
@Ritter 一般这种类似于一个函数功能的类,都会以小写命名,而不是死板的遵守 pep8 。
SjwNo1
2021-01-11 10:27:15 +08:00
还有其他类似的实现吗,学习了
Wincer
2021-01-11 10:34:20 +08:00
不错👍,不过 python 要是能在所有 function 共同的父类(说法不太准确?)上面定义 __ror__ 就好了,这样应该就可以实现:range(10) | filter(lambda x: x%2) 的写法,更接近于函数式编程语言的管道了。
dinjufen
2021-01-11 10:58:16 +08:00
666,花哨的东西学不来
frostming
2021-01-11 10:59:29 +08:00
@Wincer C 实现的类要加额外方法要动用 ctypes
我很久前写了个黑魔法
https://github.com/frostming/gorella
wellsc
2021-01-11 11:01:49 +08:00
666 这个好神奇
NeezerGu
2021-01-11 11:09:10 +08:00
@abersheeran 路过,昨天看这个学习了一阵,partial 是 python 代码实现的吧?
abersheeran
2021-01-11 11:18:59 +08:00
@NeezerGu 自己看标准库源码吧。搜这一行 from _functools import partial
bruce00
2021-01-11 11:34:58 +08:00
楼主博客好看~
Wincer
2021-01-11 11:37:54 +08:00
@frostming 沿用了你的代码,成功给 built-in 的 object 加上了 __ror__ 方法,但是还是行不通:range(10) | filter(lambda x: x % 2) 这个表达式被解释器会默认先求两端的值,如果不先求值的话,需要用 partial 包起来,不过这样又和楼主的实现差不多了。

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

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

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

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

© 2021 V2EX