如何创建链管道?

时间:2017-11-24 13:50:42

标签: python python-3.x

我想创建一个简单的链管道,我找到了this简单的例子:

"""
From https://stackoverflow.com/questions/33658355/piping-output-from-one-function-to-another-using-python-infix-syntax
"""
import collections

def pipe(original):
    """
    """

    class PipeInto(object):
        data = {'function': original}

        def __init__(self, *args, **kwargs):
            self.data['args'] = args
            self.data['kwargs'] = kwargs

        def __rrshift__(self, other):
            return self.data['function'](
                other,
                *self.data['args'],
                **self.data['kwargs']
            )
        def __call__(self):
            return self.data['function'](
                *self.data['args'],
                **self.data['kwargs']
            )

    return PipeInto

@pipe
def select(df, *args):
    cols = [x for x in args]
    return df[cols]

df >> select('one')工作正常,pipe= select(df, 'one')返回需要调用的对象。 select(df, 'one')如何作为一个返回过滤后的DataFrame的简单函数调用?

1 个答案:

答案 0 :(得分:3)

好吧,我可以想到一个解决方案,但有一个警告:你的原始函数不能采用第二个位置参数,这是一个pandas数据帧(关键字参数没问题)。让我们放弃__call__并在装饰器内的__new__类中添加PipeInto方法。这个新的构造函数测试第一个参数是否是一个数据帧,如果是,那么我们只用参数调用原始函数:

def __new__(cls, *args, **kwargs):
    if args and isinstance(args[0], pd.DataFrame):
        return cls.data['function'](*args, **kwargs)
    return super().__new__(cls)

它似乎有用,如果你发现任何不足,请告诉我。

>>> df = pd.DataFrame({'one' : [1., 2., 3., 4., 4.],
                       'two' : [4., 3., 2., 1., 3.]})

>>> select(df, 'one')
   one
0  1.0
1  2.0
2  3.0
3  4.0
4  4.0

>>> df >> select('one')
   one
0  1.0
1  2.0
2  3.0
3  4.0
4  4.0