Skip to main content

一个支持类似于使用 Unix 管道的函数组合的库。

项目描述

测试徽章 覆盖徽章 pypi 徽章

完整的文档

pipetools启用类似于使用 Unix 管道的功能组合。

它允许任意函数的前向组合和管道 - 无需装饰它们或做任何额外的事情。

它还打包了一堆实用程序,使常用操作更加方便和可读。

来源在github 上

为什么?

管道和功能组合是用于大量编程任务的一些最自然的操作。然而 Python 并没有内置的方式来执行它们。这迫使您要么对函数调用进行深度嵌套,要么添加额外的胶水代码

例子

假设您想在给定目录中创建一个 python 文件列表,按文件名长度排序,作为一个字符串,每个文件在一行上,还带有行号:

>>> print(pyfiles_by_length('../pipetools'))
1. ds_builder.py
2. __init__.py
3. compat.py
4. utils.py
5. main.py

所有的原料都已经在那里了,你只需要把它们粘在一起。你可以这样写:

def pyfiles_by_length(directory):
    all_files = os.listdir(directory)
    py_files = [f for f in all_files if f.endswith('.py')]
    sorted_files = sorted(py_files, key=len, reverse=True)
    numbered = enumerate(py_files, 1)
    rows = ("{0}. {1}".format(i, f) for i, f in numbered)
    return '\n'.join(rows)

或者可能是这样的:

def pyfiles_by_length(directory):
    return '\n'.join('{0}. {1}'.format(*x) for x in enumerate(reversed(sorted(
        [f for f in os.listdir(directory) if f.endswith('.py')], key=len)), 1))

或者,如果你是一个疯狂的科学家,你可能会这样做:

pyfiles_by_length = lambda d: (reduce('{0}\n{1}'.format,
    map(lambda x: '%d. %s' % x, enumerate(reversed(sorted(
        filter(lambda f: f.endswith('.py'), os.listdir(d)), key=len))))))

应该有一种——最好只有一种——明显的方法来做到这一点

那么是哪一个呢?好吧,为了挽回局面,pipetools给了你另一种可能!

pyfiles_by_length = (pipe
    | os.listdir
    | where(X.endswith('.py'))
    | sort_by(len).descending
    | (enumerate, X, 1)
    | foreach("{0}. {1}")
    | '\n'.join)

你问我为什么要这样做?与原生Python 代码相比,它是

  • 更容易阅读——最小的额外混乱

  • 更容易理解——从一个步骤到下一个步骤的单向数据流,没有其他需要跟踪的

  • 更容易改变——想要更多的处理?只需在管道中添加一个步骤

  • 消除了一些错误机会——您在第一个示例中发现错误了吗?

当然它不会解决你所有的问题,但是大量的代码可以 表示为一个管道,给你上面的好处。继续阅读以了解它是如何工作的!

安装

$ pip install pipetools

呃,那是什么?

用法

管道

管道对象可用于将函数连接在一起以形成新函数,它的工作方式如下:

from pipetools import pipe

f = pipe | a | b | c

# is the same as:
def f(x):
    return c(b(a(x)))

一个真实的例子,从 0 到x的奇数之和:

from functools import partial
from pipetools import pipe

odd_sum = pipe | range | partial(filter, lambda x: x % 2) | sum

odd_sum(10)  # -> 25

请注意,直到总和的链是惰性的。

管道中的自动局部应用

由于部分应用在管道在一起时通常很有用,当管道遇到元组时它会自动完成,因此这会产生与前面的示例相同的结果:

odd_sum = pipe | range | (filter, lambda x: x % 2) | sum

0.1.9开始,这更加强大,请参阅X-partial

内置工具

Pipetools 包含一组解决一些常见任务的管道工具。例如,我们的示例中有一个过滤器类的快捷方式,称为 where()

from pipetools import pipe, where

odd_sum = pipe | range | where(lambda x: x % 2) | sum

好吧,这可能更具可读性,但并不是真正的巨大改进,但等等!

如果pipe-util用作管道中的第一项或第二项(这种情况经常发生),则可以省略开头的管道:

odd_sum = range | where(lambda x: x % 2) | sum

请参阅pipe-utils 的文档

好的,但是丑陋的 lambda 呢?

where(),还有foreach()sort_by()和其他管道工具都非常有用,但需要一个函数作为参数,它可以是一个命名函数——如果它做一些复杂的事情就可以——但通常这很简单,所以使用lambda是合适的。除了 Python 的 lambdas 对于简单的任务来说非常冗长而且代码变得混乱......

X对象来救援!

from pipetools import where, X

odd_sum = range | where(X % 2) | sum

那怎么办。

阅读有关 X 对象及其限制的更多信息。

自动字符串格式化

由于用字符串组合函数没有意义,因此当管道(或 pipe-util)遇到字符串时,它会尝试将其用于 (高级)格式化

>>> countdown = pipe | (range, 1) | reversed | foreach('{}...') | ' '.join | '{} boom'
>>> countdown(5)
'4... 3... 2... 1... boom'

给水管

有时创建一次性管道并立即通过它运行一些输入很有用。而且由于这有点尴尬(并且不是很可读,尤其是当管道跨越多行时):

result = (pipe | foo | bar | boo)(some_input)

也可以使用>运算符来完成:

result = some_input > pipe | foo | bar | boo

但是等等,还有更多

查看完整文档的 Maybe 管道类固醇的部分应用自动数据结构创建

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

pipetools-1.1.0.tar.gz (16.0 kB 查看哈希)

已上传 source