六行代码实现 Python 管道 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
abersheeran
V2EX    Python

六行代码实现 Python 管道

  •  7
     
  •   abersheeran 2021-01-10 17:14:24 +08:00 13769 次点击
    这是一个创建于 1737 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不多说,直接上代码。

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

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

    第 1 条附言    2021-01-12 15:19:15 +08:00

    应某位回复者的要求,已经发布到 PyPi,顺便在 GitHub 建了个库,写了使用说明。https://github.com/abersheeran/only-pipe

    稍微解决了一下好几个人觉得困扰的 tuple 判断。现在在库里,F 只会传一个参数,如果你想让 tuple 被拆解,应当使用 FF。是否解包,控制权交给程序员,而不是代码本身。

    增加了一个功能,可以把 Freduce 释放到全局,就像 map/filter 一样直接用就行。

    import pipe import functools pipe.set_global(pipe.F, pipe.FF, functools.reduce) assert range(10) | F(filter, lambda x: x % 2) | F(sum) == 25 assert (1, 2, 3) | F(sum) == 6 assert (1, 2) | FF(lambda x, y: x + y) == 3 assert range(10) | F(reduce, lambda x, y: x + y) == 45 
    第 2 条附言    2021-01-12 16:48:57 +08:00

    有回复者提到的 Filter = F(filter) 的类似写法,可通过手动柯里化实现。

    from functools import reduce from pipe import F def fp(func): def _(*args, **kwargs): return F(func, *args, **kwargs) return _ Filter = fp(filter) Map = fp(map) Reduce = fp(reduce) range(100) | Filter(lambda x: x % 2) | Map(lambda x: x * x) | Reduce(lambda x, y: x + y) 

    https://github.com/abersheeran/only-pipe/discussions/1

    122 条回复    2021-02-19 02:25:18 +08:00
    1  2  
    msg7086
        1
    msg7086  
       2021-01-10 17:24:29 +08:00   1
    (虽然我知道这很煞风景,但是我真的忍不住想要吐槽一句,你这不就是把 Python 写成了 Ruby 吗……)
    msg7086
        2
    msg7086  
       2021-01-10 17:27:20 +08:00
    顺带提一句,如果让我来写 Python 的话,我可能还是选择把代码写成 list comprehension (可能需要推倒两次)。
    不写 map reduce 是因为怕被 Python 用户吐槽不够 Pythonic 。
    abersheeran
        3
    abersheeran  
    OP
       2021-01-10 17:37:32 +08:00
    @msg7086 四年 Python 老玩家了,谁敢说我不代码 Pythonic 我就怼死他,我写 C 都 Python 味儿了。

    Ruby 是真没用过,我甚至没有用过任何一门纯粹的函数式编程语言。管道我还是从 Shell 学到的,虽然 Shell 我只是用到 | grep 这种地步。但并不妨碍我真诚的觉得管道很好用。在我几个函数式教徒朋友给我推销的函数式编程概念里,柯里化和管道是我认为唯二可在工业代码里大量使用的。
    msg7086
        4
    msg7086  
       2021-01-10 17:48:52 +08:00
    我之前写任务依赖管理的时候也是把 pipe 拿来用了。
    class Tasks < Array
    def |(op)
    op.call(sources: self)
    end
    end
    类似这么个结构,感觉和你的差不多。
    自己发明 DSL 确实很有成就感。
    Leigg
        5
    Leigg  
       2021-01-10 17:54:14 +08:00 via iPhone
    有半年没有写 py 了,现在都进化到这个程度了吗?
    Leigg
        6
    Leigg  
       2021-01-10 17:55:14 +08:00 via iPhone
    我擦,原来是 magic method 。还以为是 shell 语法呢。
    stdout     7
    stdout  
       2021-01-10 18:06:01 +08:00
    很花哨实用。
    python4
        8
    python4  
       2021-01-10 18:06:18 +08:00   1
    等 python4 发布的时候就作为 feature 吧。
    SjwNo1
        9
    SjwNo1  
       2021-01-10 18:20:54 +08:00
    是很优雅,但不够语义化 - . -
    whileFalse
        10
    whileFalse  
       2021-01-10 18:41:38 +08:00
    不错 很优雅!
    abersheeran
        11
    abersheeran  
    OP
       2021-01-10 19:08:27 +08:00 via Android
    @python4 Guido:I don't like it.
    ferock
        12
    ferock  
    PRO
       2021-01-10 19:09:25 +08:00 via iPhone
    学习
    Jirajine
        13
    Jirajine  
       2021-01-10 19:22:37 +08:00 via Android
    不错,可以发布到 pypi
    abersheeran
        14
    abersheeran  
    OP
       2021-01-10 19:28:57 +08:00 via Android   1
    @Jirajine 请不要把 npm 行为带到 Python 社区。满打满算六行代码,这也需要 PyPi 走一下?复制粘贴它不香吗。我要是真发布了,setup.py 比源码还大。
    abersheeran
        15
    abersheeran  
    OP
       2021-01-10 19:31:43 +08:00 via Android
    @SjwNo1 如果你认为运算符不够语义化,建议开新文,炮轰 Shell 的管道运算符不够语义化。会有人跟你对线。
    如果你认为 F 这个命名不够语义化可以用 Pipe,Python3 里你甚至可以给它一个中文名,管道。够语义化吗?
    Jirajine
        16
    Jirajine  
       2021-01-10 19:51:20 +08:00 via Android
    @abersheeran 复制粘贴是可以,但每个模块都复制粘贴一遍也不合适,还是得自己建一个模块再倒入,这和直接从 pypi 导入也没多大区别吧?
    再者一般情况都从 pypi 找包,即使让人直接从 readme 里复制粘贴。不上的话不利于曝光需要的人也很难找到。
    YUX
        17
    YUX  
    PRO
       2021-01-10 20:07:10 +08:00
    `range(10) | F(filter, lambda x: x % 2) | F(sum)` 是奇数和叭
    dorafmon
        18
    dorafmon  
       2021-01-10 20:54:25 +08:00
    @Jirajine 用这个呗, 不是很接近了? https://pypi.org/project/pipetools/
    abersheeran
        19
    abersheeran  
    OP
       2021-01-10 21:08:25 +08:00 via Android
    @YUX 谢谢指正,写错了哈哈哈。好尴尬,待会就改。
    aijam
        20
    aijam  
       2021-01-10 21:12:58 +08:00
    abersheeran
        21
    abersheeran  
    OP
       2021-01-10 21:15:38 +08:00 via Android
    @Jirajine 有道理。待会就发一个。
    abersheeran
        22
    abersheeran  
    OP
       2021-01-10 21:24:08 +08:00 via Android
    @aijam 各有各的好。我这个一共只有六行代码,工作原理简单,对 Python 原本用法几乎无改变,可以和现在的代码混合使用,使用成本低、收益高。
    你给的那个库,需要从数据源头包一层,返回的也是个它的自定义对象,没办法做到随意的混合使用。当然,它那个只需要在源头和结尾申明一下,可以少输入几个字符,这方面还是有优势的。
    fpure
        23
    fpure  
       2021-01-11 00:18:19 +08:00 via Android
    不错,很优雅的代码
    alan0liang
        24
    alan0liang  
       2021-01-11 08:18:57 +08:00 via Android
    想到了 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
        25
    frostming  
       2021-01-11 08:42:12 +08:00
    我记得很久之前哪里看到过,类似小技巧一类的文章
    不过你这个可以柯里化一下更好:
    range(10) | F(filter)(lambda x: x % 2) | F(sum)
    frostming
        26
    frostming  
       2021-01-11 08:42:44 +08:00
    这样我可以:
    Filter = F(filter)
    Sum = F(sum)
    abersheeran
        27
    abersheeran  
    OP
       2021-01-11 09:13:31 +08:00
    @frostming 嗯? F 从 partial 继承而来,本就可以绑定参数的。
    Ritter
        28
    Ritter  
       2021-01-11 09:37:54 +08:00
    一直以为 partial 是个函数 原来是个类。。。
    zone10
        29
    zone10  
       2021-01-11 10:10:51 +08:00
    我之前看过一个函数式的库, 也很有意思.我现在有个思路是用更高效的语言来实现这个,不知道能不能保证 Python 便利性的同时提高性能
    abersheeran
        30
    abersheeran  
    OP
       2021-01-11 10:13:38 +08:00
    @zone10 partial 本身就是 C 写的,虽然在标准库里也有一个 C 模块不可用时的 Pure Python 降级代替,但编译正常的 CPython 都会用那个 C 版本。所以这里的性能损耗几乎不可能更低了。
    abersheeran
        31
    abersheeran  
    OP
       2021-01-11 10:17:22 +08:00
    @Ritter 一般这种类似于一个函数功能的类,都会以小写命名,而不是死板的遵守 pep8 。
    SjwNo1
        32
    SjwNo1  
       2021-01-11 10:27:15 +08:00
    还有其他类似的实现吗,学习了
    Wincer
        33
    Wincer  
       2021-01-11 10:34:20 +08:00
    不错,不过 python 要是能在所有 function 共同的父类(说法不太准确?)上面定义 __ror__ 就好了,这样应该就可以实现:range(10) | filter(lambda x: x%2) 的写法,更接近于函数式编程语言的管道了。
    dinjufen
        34
    dinjufen  
       2021-01-11 10:58:16 +08:00
    666,花哨的东西学不来
    frostming
        35
    frostming  
       2021-01-11 10:59:29 +08:00
    @Wincer C 实现的类要加额外方法要动用 ctypes
    我很久前写了个黑魔法
    https://github.com/frostming/gorella
    wellsc
        36
    wellsc  
       2021-01-11 11:01:49 +08:00
    666 这个好神奇
    NeezerGu
        37
    NeezerGu  
       2021-01-11 11:09:10 +08:00
    @abersheeran 路过,昨天看这个学习了一阵,partial 是 python 代码实现的吧?
    abersheeran
        38
    abersheeran  
    OP
       2021-01-11 11:18:59 +08:00
    @NeezerGu 自己看标准库源码吧。搜这一行 from _functools import partial
    bruce00
        39
    bruce00  
       2021-01-11 11:34:58 +08:00
    楼主博客好看~
    Wincer
        40
    Wincer  
       2021-01-11 11:37:54 +08:00
    @frostming 沿用了你的代码,成功给 built-in 的 object 加上了 __ror__ 方法,但是还是行不通:range(10) | filter(lambda x: x % 2) 这个表达式被解释器会默认先求两端的值,如果不先求值的话,需要用 partial 包起来,不过这样又和楼主的实现差不多了。
    abersheeran
        41
    abersheeran  
    OP
       2021-01-11 11:41:18 +08:00 via Android
    @bruce00 谢谢~
    abersheeran
        42
    abersheeran  
    OP
       2021-01-11 11:44:28 +08:00 via Android
    @Wincer 要实现你这个,首先要让这些 callable 支持自动柯里化……不是支持一个管道运算符就行了的

    自动柯里化的工作量就太大了,因为 Py 里存在 *args 和 **kwargs 。我是想不到有什么好办法能实现的。所以我选择让程序员自己柯里化一次(也就是使用 F 包裹一次)。
    Wincer
        43
    Wincer  
       2021-01-11 11:46:59 +08:00
    @abersheeran 嗯是的,这确实是目前比较合适的方法了
    iqxd
        44
    iqxd  
       2021-01-11 11:48:01 +08:00
    请问下楼主 if isinstance(other, tuple): return self(*other) 是为了处理哪种情况呢?
    abersheeran
        45
    abersheeran  
    OP
       2021-01-11 11:53:13 +08:00 via Android
    @frostming
    @Wincer

    就比如说明希想要的那个,可以用
    def fp(func):
    def _(*args, **kwargs):
    return F(func, *args, **kwargs)
    return _

    折中实现一下,强制 double call 才能实际调用。

    而你要做的这个,既要支持 direct call 又要支持
    double call……那就得第一次调用之后延迟计算,判断如果是走管道,调第二次,判断直接赋值的话再去计算。CPython 应该做不到,可以考虑做个超集语言,在编译期做。
    NeezerGu
        46
    NeezerGu  
       2021-01-11 12:03:31 +08:00
    @abersheeran
    不是这个吗? https://github.com/python/cpython/blob/master/Lib/functools.py
    哦,这是说, 同时提供了 python 版本和 c 版本? 如果 c 版本的导入失败就用 python 的?
    frostming
        47
    frostming  
       2021-01-11 12:38:10 +08:00
    @Wincer 如果只是 patch function 大可直接把 builtin 的 map, filter 换掉,我说的那种可以用来给 list 加 chaining call:

    [1, 2, 3].map(lambda x: x**2)
    mckelvin
        48
    mckelvin  
       2021-01-11 13:01:55 +08:00
    `sum(i for i in range(10) if i % 2)` 比 `range(10) | F(filter, lambda x: x % 2) | F(sum)` 更难读吗?
    yuruizhe
        49
    yuruizhe  
       2021-01-11 13:04:14 +08:00 via iPhone
    @Leigg 同+1,我还纳闷 shell 咋能调用 python 函数呢…老实说,我还真没把 python shell 当成过主力 shell,都是 bash…
    muzuiget
        50
    muzuiget  
       2021-01-11 13:10:53 +08:00
    这种用法容易走火入魔。
    Merlini
        51
    Merlini  
       2021-01-11 13:14:02 +08:00
    之前做文本处理的时候看到网上一个 pipeline 写法感觉也挺不错。
    ```python
    def pipeline(
    value: T,
    function_pipeline: Sequence[Callable[[T], T]],
    ) -> T:
    """A generic Unix-like pipeline
    :param value: the value you want to pass through a pipeline
    :param function_pipeline: an ordered list of functions that
    comprise your pipeline
    """
    return reduce(lambda v, f: f(v), function_pipeline, value)
    ```
    zouzou0208
        52
    zouzou0208  
       2021-01-11 13:25:22 +08:00
    好玩,原来是 index.py 的作者。好棒。
    chaleaoch
        53
    chaleaoch  
       2021-01-11 13:29:09 +08:00
    在这么玩, 会被玩坏的喂~~~~~
    shyling
        54
    shyling  
       2021-01-11 13:43:09 +08:00
    f#自带语法
    Wincer
        55
    Wincer  
       2021-01-11 14:23:56 +08:00
    @frostming 是的,这样也可以,但是适用性会窄一些,需要预先针对某一种类型 patch
    shyrock
        56
    shyrock  
       2021-01-11 14:42:38 +08:00
    赞!学习了。
    aldslvda
        57
    aldslvda  
       2021-01-11 14:52:48 +08:00
    学习了
    iintothewind
        58
    iintothewind  
       2021-01-11 16:07:57 +08:00
    你这个管道实现是不是可以再优化一下,
    毕竟每次都得带 F() 包住后面的操作符, 这个看起来有点多余。
    admirez
        59
    admirez  
       2021-01-11 16:11:52 +08:00
    pandas 也可以这样搞么?
    sapocaly
        60
    sapocaly  
       2021-01-11 16:50:00 +08:00
    个人觉得 chain funciton call 可能更符合 python 一些至少更接近 django 一些。比如 range(10).filter(lambda x: x % 2).sum()。毕竟每次加个 F 还是有点难受。当然,去掉 F 容易,我是没想到怎么实现 range(10) | filter, lambada x:x |sum 这样的 syntax
    frostming
        61
    frostming  
       2021-01-11 17:19:37 +08:00
    @sapocaly 只能魔改 builtins 了,参考我上面的回答
    sapocaly
        62
    sapocaly  
       2021-01-11 17:46:39 +08:00
    @frostming 不 我发现我之前的纠结没有意义, 如果只是要实现 range(10) | (filter, lambada x:x) |sum 或 range(10).filter(lambda x: x % 2).sum()这样的话,你只需开头用一个自己定一个 class,前者(pipe)照规矩 override ror 就行了,后者 chaining 的话我想用 metaclass 应该不难,不知道有没有更简单的。我觉得这种已经很 hack 了,改 buildin 就太过分了,没必要也不合适。当然如果你非要实现 range(10) | filter(lambada x:x) |sum 这样的,确实可能只能 patch 了,当然我会建议 patch a limited scope 而不是 explicitly override
    sapocaly
        63
    sapocaly  
       2021-01-11 17:52:14 +08:00
    补充一下,比较容易实现的 chain 的用法会是 Chain.range(10).filter(lambda x:x % 2).sum().end(),稍微难一点的是 Chain.range(10).filter(lambda x:x % 2).sum(),我猜这里我得想下类似 lazy eval 的实现。如果想直接 range(10).filter(lambda x:x % 2).sum(),我可能会用 with patched_buildin(): range(10).filter(lambda x:x % 2).sum()这样的 syntax 当然讨厌 indentation 的话自然也有别的办法
    sapocaly
        64
    sapocaly  
       2021-01-11 17:54:13 +08:00
    想了想似乎 metaclass 都不需要
    abersheeran
        65
    abersheeran  
    OP
       2021-01-11 18:03:21 +08:00 via Android
    @NeezerGu 对的。

    @admirez 可以,此管道可以用在任何 Python 代码里。我就是在处理数据的时候想到的这个。

    @sapocaly 你说的这个不就是楼上推荐的那个库吗?你喜欢的话可以去试试,上面有链接。我个人喜欢 | F(...) 这么用。没有黑魔法,工作原理简单,对 debug 友好,最重要的优点是每一次管道运算都是真实的运算出了结果,我可以在任何一次运算之后拿去用,而不需要特意标识一个 END 或者其他什么的。
    xuboying
        66
    xuboying  
       2021-01-11 18:04:45 +08:00
    楼主不去写 perl6 可惜了,python 的名人名言是只能有一种写法,不遵守人的可以去开发其他语言(逃)
    Tumblr
        67
    Tumblr  
       2021-01-11 18:07:05 +08:00
    啊!这很 PowerShell !很 pwsh !
    abersheeran
        68
    abersheeran  
    OP
       2021-01-11 18:10:13 +08:00 via Android
    @mckelvin 我文章里解释过了。管道的数据处理顺序跟阅读顺序是一样的。利于阅读代码。
    你说的这个嵌套用法当然可以,可是阅读顺序和实际的执行顺序是相反的,它先执行的内部函数再执行的外部函数。
    NeezerGu
        69
    NeezerGu  
       2021-01-11 18:12:21 +08:00
    @abersheeran 原来如此,感谢哈。
    sapocaly
        70
    sapocaly  
       2021-01-11 18:15:46 +08:00
    @abersheeran 额其实我很久没写 python 了,倒不是真要用到,不过觉得你提出的这个问题挺有意思所以想想有啥别的实现。我看了那个库介绍,和我理想中的比较接近,我觉得 END 是可以去掉的,但当然这又要加很多 hack 。 至于哪种 syntax 我比较喜欢,我觉得都还行,不过我觉得我现实中不会去用。简单的逻辑没必要,复杂的逻辑 chain 或者 pipe 的可读性并不会增加,也大概率效率不是最好的。当然,我也很久没用 python 了,效率这个还得具体问题具体分析。
    xuboying
        71
    xuboying  
       2021-01-11 18:31:51 +08:00
    为何要特殊处理 tuple,没有 get 到 OP 的意图,有什么特殊情况可以简便写法么?
    >>> (1, 2 , 3) | F(filter, lambda x: x % 2) | F(list)
    TypeError: filter expected 2 arguments, got 4

    >>> [1, 2 , 3] | F(filter, lambda x: x % 2) | F(list)
    [1, 3]

    >>> list(filter( lambda x: x % 2,(1,2,3)))
    [1, 3]
    abersheeran
        72
    abersheeran  
    OP
       2021-01-11 19:20:39 +08:00
    @sapocaly 嗯,关于此的讨论你可以看看楼上我、 @frostming 和 @Wincer 发的。更好、更简单的实现方法目前来看,在 CPython 里是没有的。如果自己实现一个 Python 超集的编译器,那就可以做到了。

    @iqxd @xuboying 因为我希望能传递多个参数给被 F 包裹的函数。一般来说,函数返回多值是 return x, y, z 这样,它的实际类型是一个 tuple 。

    比如

    def fa(...): return a, b, c
    def fb(a, b, c, d, e): return y

    就可以直接 data | F(fa) | F(fb), 而不是 data | F(fa) | F(lambda args: F(fb(*args))) 这样写。
    maddevil
        73
    maddevil  
       2021-01-11 19:24:49 +08:00
    from functools import partial

    F = type("F", (partial,), {"__ror__": lambda self, other: self(other)})
    range(10) | F(filter, lambda x: x & 1) | F(sum) | F(print)
    geebos
        74
    geebos  
    PRO
       2021-01-11 19:44:23 +08:00
    个人觉得可以写成装饰器

    ```python
    from functools import partial

    class F(partial):
    def __init__(self, func):
    self.__func = func

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

    def __call__(self, *args, **kwargs):
    return self.__func(*args, **kwargs)

    def pipefy(func):
    return F(func)

    ```
    zyb201314
        75
    zyb201314  
       2021-01-11 21:07:19 +08:00 via Android
    这就是牛人技术探讨吗?作为小白的我完全参入不进讨论, 只能给你们鼓掌.
    crclz
        76
    crclz  
       2021-01-11 21:09:30 +08:00
    可以可以,脚本语言就应该有脚本的样子
    24bit
        77
    24bit  
       2021-01-11 23:35:01 +08:00
    赞一个
    lithbitren
        78
    lithbitren  
       2021-01-12 01:29:41 +08:00
    非常有意思
    AlexChing
        79
    AlexChing  
       2021-01-12 09:59:30 +08:00
    这个在 python 的数据预处理阶段确实是很实用的。数据预处理需要按照特定的流程来走,自己一个个的写流程确实很难受。
    Reficul
        80
    Reficul  
       2021-01-12 10:12:33 +08:00
    差点真被唬住了, 原来是覆盖了位运算的或。。。

    秒啊~
    xuboying
        81
    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
        82
    xuboying  
       2021-01-12 11:05:00 +08:00
    @xuboying #81 草率了。。ror 和 rrshift 有优先级关系,一起用不方便。。。
    abersheeran
        83
    abersheeran  
    OP
       2021-01-12 11:37:40 +08:00
    @xuboying 哈哈,如果你想要拆分成两个字符,不妨考虑 `|` 和 `^` 这两没有优先级问题。
    Leviathann
        84
    Leviathann  
       2021-01-12 12:51:52 +08:00 via iPhone
    @alan0liang 这个 sharp 让我想到了 Mathematica
    no1xsyzy
        85
    no1xsyzy  
       2021-01-12 13:25:00 +08:00
    @abersheeran | ^ 这两个也有优先级问题, ^ 优先级高
    似乎 | 没有同优先级的……

    @geebos 你的 __init__ 和 __call__ 的功能已经被 partial 实现了……
    abersheeran
        86
    abersheeran  
    OP
       2021-01-12 13:34:53 +08:00
    no1xsyzy
        87
    no1xsyzy  
       2021-01-12 13:48:22 +08:00
    最长的管道实现:发 PEP 要求增加 |> 和 ||> 操作符
    no1xsyzy
        88
    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
        89
    abersheeran  
    OP
       2021-01-12 15:06:55 +08:00
    @no1xsyzy 提这个 PEP,Guido 会回复:I don't like it. Closed. 哈哈哈
    woostundy
        90
    woostundy  
       2021-01-12 15:30:06 +08:00
    或运算有时候还挺常用的。
    要是能自己增加运算符以及定义就好了。
    no1xsyzy
        91
    no1xsyzy  
       2021-01-12 15:32:04 +08:00
    @abersheeran 大人,时代变了
    Guido 不是也不喜欢 := 么……
    abersheeran
        92
    abersheeran  
    OP
       2021-01-12 15:36:34 +08:00
    @no1xsyzy 但是能和他对着干的,也就那么几个大佬吧。红姐提交模式匹配的 PR 不还是 Guido 直接 Closed 嘛。
    xuboying
        93
    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
        94
    abersheeran  
    OP
       2021-01-12 16:35:30 +08:00
    @xuboying https://github.com/abersheeran/only-pipe/discussions 方便的话可以发到这,留作记录。

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

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


    我已经 抛弃 python 了


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

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

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


    什么是好语言:

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

    python 一样都没占上

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


    所以, 自己玩玩可以
    abersheeran
        98
    abersheeran  
    OP
       2021-01-12 18:55:32 +08:00
    @yueyoum 喔。你是 Golang 的粉丝吧。
    lizytalk
        99
    lizytalk  
       2021-01-12 19:10:46 +08:00
    @aijam #20 我觉得这里面的 pipe 的设计比楼主的好
    xuboying
        100
    xuboying  
       2021-01-12 19:52:20 +08:00 via Android
    @yueyoum 从语法的角度 op 的代码并不符合社区规范,但可能很多人(包括我)是把 op 的设计当成一个最终产品来用的,比如数据分析。op 更像是一个优秀的产品经理而不是单纯的 coder 。
    1  2  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2773 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 15:06 PVG 23:06 LAX 08:06 JFK 11:06
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86