2010-02-17 2 views
18

몇 시간 전 하스켈 문서를 살펴본 결과 기능 구성 연산자가 정말 멋지다는 것을 알았습니다.파이썬에서 구문을 기능하도록 설탕을 넣는 것이 좋은 생각입니까?

from functools import partial 

class _compfunc(partial): 
    def __lshift__(self, y): 
     f = lambda *args, **kwargs: self.func(y(*args, **kwargs)) 
     return _compfunc(f) 

    def __rshift__(self, y): 
     f = lambda *args, **kwargs: y(self.func(*args, **kwargs)) 
     return _compfunc(f) 

def composable(f): 
    return _compfunc(f) 

@composable  
def f1(x): 
    return x * 2 

@composable 
def f2(x): 
    return x + 3 

@composable 
def f3(x): 
    return (-1) * x 

@composable 
def f4(a): 
    return a + [0] 

print (f1 >> f2 >> f3)(3) #-9 
print (f4 >> f1)([1, 2]) #[1, 2, 0, 1, 2, 0] 
print (f4 << f1)([1, 2]) #[1, 2, 1, 2, 0] 

문제는 : 우리는이 같은 내장 기능 또는 람다에이 구문을 사용할 수 없습니다 언어 지원없이 가 :

((lambda x: x + 3) >> abs)(2) 

질문 : 입니다 그래서 나는이 작은 장식을 구현했습니다 유용할까요? 파이썬 메일 목록에서 논의 할 가치가 있습니까?

+0

...하지만 다음과 같이 쓸 수도 있습니다. print (composable (lambda x : x + 3) >> composable (abs)) (- 4) – si14

답변

8

IMHO : 아니에요. 하스켈을 좋아하지만 이것은 파이썬에 들어 맞지 않는 것 같습니다. (f1 >> f2 >> f3) 대신 compose(f1, f2, f3)을 사용하면 문제를 해결할 수 있습니다. 과부하, 장식 또는 코어 (IIRC 누군가 이미 제안한 누군가 functools.compose)를 변경하지 않고도 호출 가능 코드와 함께 사용할 수 있습니다. 지금 당장은 찾을 수 없습니다.

게다가 언어 정의가 현재 고정되어 있으므로 어쨌든 이러한 종류의 변경을 거부 할 수 있습니다. PEP 3003을 참조하십시오.

+0

compose()가 너무 명확하지 않습니다. 작곡의 방향은 무엇입니까? 이 질문에 대답하려면 문서를 봐야합니다. – si14

+2

@ si14 : 하스켈을 알지 못한다. >>와 <<를 찾지 못한다. (다른 함수를 삽입하거나 감싸는 것을 의미 하는가?). – nikow

+1

@Nikow : 나도 몰라. >> 및 <<는 "계산 흐름"을 명확하게 정의합니다. f1 >> f2 >> f3은 "결과를 f1에서 f2로, 그 다음 f2에서 f3으로"를 의미합니다. 대안은 f1 (f2 (f3 (x)))입니다. 많은 지저분한 괄호가 있습니다. – si14

6

함수 합성은 Python에서 매우 일반적인 연산이 아니며, 특히 합성 연산자가 분명히 필요하지는 않습니다. 뭔가 추가 되었다면 나는 파이썬을 위해 <<>>을 선택하는 것을 좋아하지 않는다고 확신하지는 않는다.

나는 많은 사람들이 문제가되지 않습니다 위해있는 기능 compose, 더 편안 할 것입니다 의심 : compose(f, g)(x)f(g(x)), 수학 o와 하스켈 .와 같은 순서로 의미 할 것입니다. 파이썬은 특히 특수 문자가 널리 알려지지 않은 경우 영어 단어를 사용할 때 구두점을 사용하지 않습니다. (장식자 (@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@)와 같은 @을 무시하고 너무 유용하게 보이지 않는 것들은 예외입니다.

이것을 python-ideas, 기능 구성이 코드를보다 명확하고, 작성하기 쉽고, 유지 보수가 가능하거나, 효율적으로 만들 수있는 stdlib 또는 대중적인 Python 라이브러리에서 일부 인스턴스를 찾을 수 있다면 더 많은 사람들을 확보 할 수있을 것입니다. 호출의 순서가 오른쪽에서 왼쪽으로 만되어 있지만

+0

'>>'과'<<'가 명확하지 않은 이유를 분명히 해줄 수 있습니까? 나는 동의하지 않는다. 나는 단지 프로그래머들 사이에 합의가 이루어 졌는지 알아보기 위해 노력하고있다. – max

+0

@max, 나는 왜 무언가가 명백하지 않은지를 어떻게 설명 할 수 있을지 전혀 모른다. "<<' and '>"을보고 "아, 이걸 사용해야합니다!"라고 말할 이유가 없습니다. –

+0

@max 시도 : * 사용법에 대한 전통이 없으므로 덜 명백합니다. 또 다른 의미로 *'''는 확장 된 print 문 ('print chevron')에서 사용되기 때문에 덜 명백합니다. [특수 기능] (https://docs.python.org/)의 [이동 작업] (https://docs.python.org/2/reference/expressions.html#shifting-operations) 2/reference/datamodel.html # 에뮬 레이팅 - 숫자 유형) * all * [callables] (https://docs.python.org/2/reference/datamodel.html#emulating-callable-objects)에 대한 구성 : * 이것이 어떤 종류의 물체가 실격이되는지 분명하지 않습니다. – n611x007

6

당신은 reduce와 함께 할 수 있습니다 : 나는 여부 언어 변화 전망을 파이썬과 충분한 경험이없는

def f1(a): 
    return a+1 

def f2(a): 
    return a+10 

def f3(a): 
    return a+100 

def call(a,f): 
    return f(a) 


reduce(call, (f1, f2, f3), 5) 
# 5 -> f1 -> f2 -> f3 -> 116 
reduce(call, ((lambda x: x+3), abs), 2) 
# 5 
1

것 가치가있다. 하지만 현재 언어로 제공되는 옵션을 설명하고 싶었습니다. 예기치 않은 동작을 생성 방지하기 위해

는 기능성 성분이 이상적으로 즉, f ∘ g ∘ h 다음 다음 h, g, f 적용을 의미한다, 작업 (또는 하스켈) 위해 표준 수학을 따라야합니다.

람다와 내장 함수에 문제가 있다고 언급 한대로 기존 연산자 인 Python을 사용하려면 <<을 사용하십시오. __lshift__ 외에도 반사 된 버전 __rlshift__을 정의하면 훨씬 쉽게 생활 할 수 있습니다. 그것으로 λ/built-ins에 인접한 composable 객체가 처리됩니다.두 개의 인접한 람다/내장 함수가있을 때는 @ si14가 제안한대로 composable으로 명시 적으로 변환해야합니다. 사실 __rlshift__이 아니라 __rshift__을 의미합니다. 사실 __rshift__을 사용하지 말 것을 권합니다. 왜냐하면 주문 변경은 운영자의 모양에 의해 제공된 방향 힌트에도 불구하고 혼란 스럽기 때문입니다.

하지만 다른 방법을 고려해 볼 수 있습니다. Ferdinand Jamitzky는 내장 함수에서도 작동하는 Python의 의사 삽입 연산자를 정의하기 위해 great recipe을 가지고 있습니다. 이것으로 함수 합성을 위해 f |o| g을 쓸 수 있습니다. 실제로는 매우 합리적입니다.

관련 문제