六行代码实现 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 调样式了。有兴趣的就看看,没兴趣的就复制代码去用就完事。

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

13688 次点击
所在节点    Python
122 条回复
xuboying
2021-01-12 10:56:15 +08:00
@abersheeran #72 感谢 OP 提供了一个非常好的思路,用在 notebook 里做数据分析非常实用,写项目估计会被大多数 team 打死。。。
ror 差点被骗了,以为是循环,看了一下文档以后我想再重载一个运算符,这样就不用粗暴的使用 tuple 来判断处理逻辑了,代码如下:

$ cat foo.py
from functools import partial


class F(partial):
def __ror__(self, rhs):
return self(rhs)

def __rrshift__(self, rhs):
return self(*rhs)


$ python -i foo.py
>>> (1, 2 , 3) | F(filter, lambda x: x % 2) | F(list)
[1, 3]
>>> (14, '#b') >> F(format)
'0b1110'
>>>
xuboying
2021-01-12 11:05:00 +08:00
@xuboying #81 草率了。。ror 和 rrshift 有优先级关系,一起用不方便。。。
abersheeran
2021-01-12 11:37:40 +08:00
@xuboying 哈哈,如果你想要拆分成两个字符,不妨考虑 `|` 和 `^` 这两没有优先级问题。
Leviathann
2021-01-12 12:51:52 +08:00
@alan0liang 这个 sharp 让我想到了 Mathematica
no1xsyzy
2021-01-12 13:25:00 +08:00
@abersheeran | ^ 这两个也有优先级问题, ^ 优先级高
似乎 | 没有同优先级的……

@geebos 你的 __init__ 和 __call__ 的功能已经被 partial 实现了……
abersheeran
2021-01-12 13:34:53 +08:00
no1xsyzy
2021-01-12 13:48:22 +08:00
最长的管道实现:发 PEP 要求增加 |> 和 ||> 操作符
no1xsyzy
2021-01-12 14:01:06 +08:00
@abersheeran 再想了下,可能比较歪
a / F(b) :: b(a)
a // F(b) :: b(*a)
a @ F(b) :: map(b, a)
a % F(b) :: filter(b, a)
a * F(b) :: reduce(b, a)
abersheeran
2021-01-12 15:06:55 +08:00
@no1xsyzy 提这个 PEP,Guido 会回复:I don't like it. Closed. 哈哈哈
woostundy
2021-01-12 15:30:06 +08:00
或运算有时候还挺常用的。
要是能自己增加运算符以及定义就好了。
no1xsyzy
2021-01-12 15:32:04 +08:00
@abersheeran 大人,时代变了
Guido 不是也不喜欢 := 么……
abersheeran
2021-01-12 15:36:34 +08:00
@no1xsyzy 但是能和他对着干的,也就那么几个大佬吧。红姐提交模式匹配的 PR 不还是 Guido 直接 Closed 嘛。
xuboying
2021-01-12 16:10:20 +08:00
@no1xsyzy #85 @abersheeran
花了点摸鱼的时间略微改造了一个符合我个人喜好的版本,以后做数据分析手指就轻松了。

我发现 partial 的类很特殊,不能简单继承,或者前面有人提到了 Filter=F(filter)似乎也是不行的。

希望有高人能帮忙简化一下我的写法。

···
$ cat foo.py
from functools import partial


class P(partial):
"""Pipe."""

def __ror__(self, rhs):
return self(rhs)


class X(partial):
"""Xargs."""

def __ror__(self, rhs):
return self(*rhs)


class Filter(P):

def __new__(cls, *args, **kwargs):
return super(__class__, cls).__new__(cls, filter, *args, **kwargs)


class Map(P):

def __new__(cls, *args, **kwargs):
return super(__class__, cls).__new__(cls, map, *args, **kwargs)


$ python -i foo.py
>>> (1, 2 , 3) | Map(lambda x : x+2 ) | Filter(lambda x: x % 2) | X(divmod) | P (set)
{0, 3}
···
abersheeran
2021-01-12 16:35:30 +08:00
@xuboying https://github.com/abersheeran/only-pipe/discussions 方便的话可以发到这,留作记录。

😀你这个也不错。可以再加一个 Reduce 的,就齐活了哈哈哈。
Macv1994
2021-01-12 17:11:58 +08:00
想问一下题主,怎么样才能像你一样写出这样优雅的代码,可以说一下学习路线吗?
abersheeran
2021-01-12 17:23:05 +08:00
@Macv1994 学习路线?额……你可以看看我博客,按时间顺序倒着看。那个差不多就能展示我的学习路线了。
yueyoum
2021-01-12 18:48:26 +08:00
我为了 回复此贴, 特意登陆了一下

总结: 哗众取宠,毫无意义


我已经 抛弃 python 了


工业应用,各种炫技代码,不是 平铺直述 的代码, 我全部都是 review 不通过的

如果一个 语言 写了 4 年 还能从 语法上玩出花样, 或者 一个语言 写了 4 年 还没掌握全部的语言特性
( c++除外, 特定领域 和 高性能 是别人的卖点)

那么 在这种语言上 浪费时间是 毫无意义的


什么是好语言:

1. 语法 几天 学完
2. 语言特性 几个月 完全掌握
3. 有强力的 IDE 支持
4. 强类型,编译检查错误
5. 如果运行效率高最好
6. 如果容易的支持并行最好

python 一样都没占上

连最基本的 语言特性, 我敢说 这个帖子里 没有一个人 完全掌握了 python 的特性


所以, 自己玩玩可以
abersheeran
2021-01-12 18:55:32 +08:00
@yueyoum 喔。你是 Golang 的粉丝吧。
lizytalk
2021-01-12 19:10:46 +08:00
@aijam #20 我觉得这里面的 pipe 的设计比楼主的好
xuboying
2021-01-12 19:52:20 +08:00
@yueyoum 从语法的角度 op 的代码并不符合社区规范,但可能很多人(包括我)是把 op 的设计当成一个最终产品来用的,比如数据分析。op 更像是一个优秀的产品经理而不是单纯的 coder 。

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

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

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

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

© 2021 V2EX