[python] R의 magritrr의 %> %와 같은 파이썬의 기능성 파이프

R에서 (덕분에 magritrr) 이제를 통해 더 기능적인 파이핑 구문으로 작업을 수행 할 수 있습니다 %>%. 이것은 이것을 코딩하는 대신에 의미합니다 :

> as.Date("2014-01-01")
> as.character((sqrt(12)^2)

다음과 같이 할 수도 있습니다.

> "2014-01-01" %>% as.Date
> 12 %>% sqrt %>% .^2 %>% as.character

나에게 이것은 더 읽기 쉽고 이것은 데이터 프레임을 넘어서는 사용 사례로 확장됩니다. 파이썬 언어가 비슷한 것을 지원합니까?



답변

이를 수행하는 한 가지 가능한 방법은라는 모듈을 사용하는 것 macropy입니다. Macropy를 사용하면 작성한 코드에 변환을 적용 할 수 있습니다. 따라서 a | b로 변환 될 수있다 b(a). 여기에는 많은 장점과 단점이 있습니다.

Sylvain Leroux가 언급 한 솔루션과 비교할 때 가장 큰 장점은 사용하려는 함수에 대해 중위 객체를 만들 필요가 없다는 것입니다. 변환을 사용하려는 코드 영역을 표시하기 만하면됩니다. 둘째, 변환이 런타임이 아닌 컴파일 타임에 적용되기 때문에 변환 된 코드는 런타임 중에 오버 헤드가 발생하지 않습니다. 모든 작업은 소스 코드에서 바이트 코드가 처음 생성 될 때 수행됩니다.

가장 큰 단점은 macropy가 작동하려면 특정 방법을 활성화해야한다는 것입니다 (나중에 언급). 더 빠른 런타임과 달리 소스 코드의 구문 분석은 계산적으로 더 복잡하므로 프로그램을 시작하는 데 더 오래 걸립니다. 마지막으로, 매크로 피에 익숙하지 않은 프로그래머가 코드를 이해하기 더 어려울 수 있음을 의미하는 구문 스타일을 추가합니다.

예제 코드 :

run.py

import macropy.activate
# Activates macropy, modules using macropy cannot be imported before this statement
# in the program.
import target
# import the module using macropy

target.py

from fpipe import macros, fpipe
from macropy.quick_lambda import macros, f
# The `from module import macros, ...` must be used for macropy to know which 
# macros it should apply to your code.
# Here two macros have been imported `fpipe`, which does what you want
# and `f` which provides a quicker way to write lambdas.

from math import sqrt

# Using the fpipe macro in a single expression.
# The code between the square braces is interpreted as - str(sqrt(12))
print fpipe[12 | sqrt | str] # prints 3.46410161514

# using a decorator
# All code within the function is examined for `x | y` constructs.
x = 1 # global variable
@fpipe
def sum_range_then_square():
    "expected value (1 + 2 + 3)**2 -> 36"
    y = 4 # local variable
    return range(x, y) | sum | f[_**2]
    # `f[_**2]` is macropy syntax for -- `lambda x: x**2`, which would also work here

print sum_range_then_square() # prints 36

# using a with block.
# same as a decorator, but for limited blocks.
with fpipe:
    print range(4) | sum # prints 6
    print 'a b c' | f[_.split()] # prints ['a', 'b', 'c']

그리고 마지막으로 열심히 일하는 모듈입니다. 한 프로세스에서 다른 프로세스로 출력을 전달하기위한 에뮬레이션 쉘 구문으로 기능 파이프에 대해 fpipe라고 불렀습니다.

fpipe.py

from macropy.core.macros import *
from macropy.core.quotes import macros, q, ast

macros = Macros()

@macros.decorator
@macros.block
@macros.expr
def fpipe(tree, **kw):

    @Walker
    def pipe_search(tree, stop, **kw):
        """Search code for bitwise or operators and transform `a | b` to `b(a)`."""
        if isinstance(tree, BinOp) and isinstance(tree.op, BitOr):
            operand = tree.left
            function = tree.right
            newtree = q[ast[function](ast[operand])]
            return newtree

    return pipe_search.recurse(tree)


답변

파이프는 Pandas 0.16.2 의 새로운 기능입니다. .

예:

import pandas as pd
from sklearn.datasets import load_iris

x = load_iris()
x = pd.DataFrame(x.data, columns=x.feature_names)

def remove_units(df):
    df.columns = pd.Index(map(lambda x: x.replace(" (cm)", ""), df.columns))
    return df

def length_times_width(df):
    df['sepal length*width'] = df['sepal length'] * df['sepal width']
    df['petal length*width'] = df['petal length'] * df['petal width']

x.pipe(remove_units).pipe(length_times_width)
x

참고 : Pandas 버전은 Python의 참조 의미를 유지합니다. 그렇기 때문에 length_times_width반환 값이 필요하지 않습니다. x제자리에서 수정 됩니다.


답변

PyToolz [doc] 는 파이프 연산자 구문으로 정의되지 않은 파이프를 임의로 구성 할 수 있습니다.

빠른 시작은 위의 링크를 따르십시오. 다음은 비디오 자습서입니다.
http://pyvideo.org/video/2858/functional-programming-in-python-with-pytoolz

In [1]: from toolz import pipe

In [2]: from math import sqrt

In [3]: pipe(12, sqrt, str)
Out[3]: '3.4641016151377544'


답변

파이썬 언어가 비슷한 것을 지원합니까?

“더 기능적인 파이핑 구문” 이 실제로 더 “기능적인”구문입니까? 대신 R에 “infix”구문을 추가합니다.

즉, Python의 문법 은 표준 연산자 이상의 중위 표기법을 직접 지원하지 않습니다.


정말로 그런 것이 필요하다면 Tomer Filiba의 코드를 시작점 으로 가져 와서 자신 만의 중위 표기법을 구현해야합니다.

Tomer Filiba의 코드 샘플 및 주석 ( http://tomerfiliba.com/blog/Infix-Operators/ ) :

from functools import partial

class Infix(object):
    def __init__(self, func):
        self.func = func
    def __or__(self, other):
        return self.func(other)
    def __ror__(self, other):
        return Infix(partial(self.func, other))
    def __call__(self, v1, v2):
        return self.func(v1, v2)

이 독특한 클래스의 인스턴스를 사용하여 이제 함수를 중위 연산자로 호출하는 데 새로운 “구문”을 사용할 수 있습니다.

>>> @Infix
... def add(x, y):
...     return x + y
...
>>> 5 |add| 6


답변

개인 스크립팅을 위해 이것을 원한다면 Python 대신 Coconut을 사용하는 것이 좋습니다.

Coconut은 Python의 상위 집합입니다. 따라서 Coconut의 파이프 연산자를 사용할 수 |>있으며 나머지 Coconut 언어는 완전히 무시할 수 있습니다.

예를 들면 :

def addone(x):
    x + 1

3 |> addone

컴파일

# lots of auto-generated header junk

# Compiled Coconut: -----------------------------------------------------------

def addone(x):
    return x + 1

(addone)(3)


답변

dfply모듈은. 자세한 정보는

https://github.com/kieferk/dfply

몇 가지 예는 다음과 같습니다.

from dfply import *
diamonds >> group_by('cut') >> row_slice(5)
diamonds >> distinct(X.color)
diamonds >> filter_by(X.cut == 'Ideal', X.color == 'E', X.table < 55, X.price < 500)
diamonds >> mutate(x_plus_y=X.x + X.y, y_div_z=(X.y / X.z)) >> select(columns_from('x')) >> head(3)


답변

|>Elixir 의 파이프 연산자를 놓 쳤기 때문에 >>ast 라이브러리와 컴파일 / 실행을 사용하여 컴파일 타임에 Python 오른쪽 시프트 연산자를 매우 Elixir와 유사한 파이프로 재 해석하는 간단한 함수 데코레이터 (~ 50 줄의 코드)를 만들었습니다 .

from pipeop import pipes

def add3(a, b, c):
    return a + b + c

def times(a, b):
    return a * b

@pipes
def calc()
    print 1 >> add3(2, 3) >> times(4)  # prints 24

하는 일은 다음 a >> b(...)과 같이 다시 작성 하는 것입니다.b(a, ...) .

https://pypi.org/project/pipeop/

https://github.com/robinhilliard/pipes