Python의 함수 체인
Codewars.com 에서 다음 작업을 수행했습니다.
생성하기
add
연속적으로 호출될 때 숫자를 함께 추가합니다.그렇게add(1)
해야 합니다.1
,add(1)(2)
해야 합니다.1+2
, ...
파이썬의 기본은 익히 알고 있지만, 이렇게 연속적으로 호출할 수 있는 함수, 즉 함수를 접해본 적이 없습니다.f(x)
은 고라할 할 수 .f(x)(y)(z)...
지금까지, 저는 이 표기법을 어떻게 해석해야 할지조차 잘 모르겠습니다.
수학자로서, 저는 의심합니다.f(x)(y)
는 모든 에하는함다에 입니다.x
수함g_{x}
리고돌아니다옵그다니▁and옵▁then돌을 반환합니다.g_{x}(y)
로 리고마찬로지가그로▁for.f(x)(y)(z)
.
만약 이 해석이 맞다면, 파이썬은 제가 매우 흥미롭게 보이는 기능들을 동적으로 만들 수 있게 해줄 것입니다.저는 지난 한 시간 동안 웹을 검색했지만 올바른 방향으로 단서를 찾지 못했습니다.하지만 이 프로그래밍 개념이 어떻게 불리는지 모르기 때문에, 이것은 그리 놀라운 일이 아닐 수도 있습니다.
이 개념을 어떻게 부르고 어디서 더 자세히 읽을 수 있습니까?
이것이 호출 가능한 체인만큼 함수 체인인지는 모르겠지만, 함수는 호출 가능하기 때문에 해를 끼치지 않을 것 같습니다.어느 쪽이든, 제가 생각할 수 있는 두 가지 방법이 있습니다.
위류분int
그리고 정의합니다.__call__
:
첫 번째 방법은 관습을 따르는 것입니다.int
업데이트된 값으로 자신의 새 인스턴스를 반환하는 하위 클래스:
class CustomInt(int):
def __call__(self, v):
return CustomInt(self + v)
기.add
이를반도정수있의다니습할을 할 수 .CustomInt
인스턴스는 자체의 업데이트된 값을 반환하는 호출 가능으로 연속적으로 호출될 수 있습니다.
>>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44) # and so on..
50
게가로 으서, 로다.int
은 하클래스, 반된값다유지다니합을을 유지합니다.__repr__
그리고.__str__
의 int
그러나 보다 복잡한 작업의 경우 다른 실수를 적절하게 정의해야 합니다.
@Caridorc가 논평에서 언급했듯이,add
간단히 다음과 같이 쓸 수도 있습니다.
add = CustomInt
을 " 스이다변경로음으을름클래add
에 CustomInt
또한 유사하게 작동합니다.
마감을 정의합니다. 가치를 창출하기 위해 추가 통화가 필요합니다.
제가 생각할 수 있는 유일한 방법은 결과를 반환하기 위해 빈 인수 호출이 추가로 필요한 중첩 함수입니다.사용하지 않습니다.nonlocal
그리고 Pythons 간에 이동할 수 있도록 함수 객체에 속성을 연결하는 것을 선택합니다.
def add(v):
def _inner_adder(val=None):
"""
if val is None we return _inner_adder.v
else we increment and return ourselves
"""
if val is None:
return _inner_adder.v
_inner_adder.v += val
return _inner_adder
_inner_adder.v = v # save value
return _inner_adder
반환합니다._inner_adder
) 만약 그렇다면,val
급공, 증가)_inner_adder += val
및 않은 반환합니다 및 그렇지 않은 경우 값을 그대로 반환합니다.제가 말씀드린 것처럼, 그것은 추가적으로 필요합니다.()
증분 값을 반환하려면 다음을 호출합니다.
>>> add(1)(2)()
3
>>> add(1)(2)(3)() # and so on..
6
당신은 나를 미워할 수 있지만, 여기 원라이너가 있습니다 :)
add = lambda v: type("", (int,), {"__call__": lambda self, v: self.__class__(self + v)})(v)
편집: 자, 어떻게 작동합니까?코드는 @Jim의 답변과 동일하지만, 모든 것은 한 줄에서 발생합니다.
type
유형을 하는 데 할 수 .type(name, bases, dict) -> a new type
.위해서name
이 경우 이름이 필요하지 않으므로 빈 문자열을 제공합니다.위해서bases
우리는 제공합니다.(int,)
것과 .int
.dict
으로, 우스는여첨부기다니합에며를 .__call__
람다의self.__class__(self + v)
는 와동합다니와 동일합니다.return CustomInt(self + v)
- 새 유형이 생성되어 외부 람다 내에서 반환됩니다.
번 하려면 먼저 함수를 매번 . 그렇지 를▁a▁if▁by▁▁object▁your▁own▁each▁you▁to매)다합▁otherwise▁function▁have▁create니▁a▁to)를 정의하여 자신의 개체를 만들어야 합니다. 그렇지 않으면 다음을 정의하여 자체 개체를 생성해야 합니다.__call__
호출 가능한 속성입니다.
다음은 모든 인수를 보존해야 한다는 것입니다. 이 경우 코루틴 또는 재귀 함수를 사용할 수 있습니다.그러나 코루틴은 특히 이러한 작업에 대해 재귀 함수보다 훨씬 더 최적화/유연합니다.
다음은 최신 상태를 보존하는 코루틴을 사용한 샘플 함수입니다.반환 값이 다음과 같으므로 여러 번 호출할 수 없습니다.integer
호출할 수는 없지만, 이것을 예상 개체로 바꾸는 것을 생각할 수 있습니다 ;-).).
def add():
current = yield
while True:
value = yield current
current = value + current
it = add()
next(it)
print(it.send(10))
print(it.send(2))
print(it.send(4))
10
12
16
단순:
class add(int):
def __call__(self, n):
return add(self + n)
이 추가로 할 의사가 ,()
결과를 검색하기 위해 사용할 수 있습니다.
from functools import partial
def add(*args, result=0):
return partial(add, result=sum(args)+result) if args else result
예:
>>> add(1)
functools.partial(<function add at 0x7ffbcf3ff430>, result=1)
>>> add(1)(2)
functools.partial(<function add at 0x7ffbcf3ff430>, result=3)
>>> add(1)(2)()
3
이를 통해 한 번에 여러 개의 숫자를 지정할 수도 마찬가지입니다.
>>> add(1, 2, 3)(4, 5)(6)()
21
단일 숫자로 제한하려는 경우 다음을 수행할 수:
def add(x=None, *, result=0):
return partial(add, result=x+result) if x is not None else result
네가 원한다면add(x)(y)(z)
결과를 즉시 반환하고 하위 분류보다 추가로 호출할 수 있습니다.int
가는 길입니다.
이를 위한 파이썬적 방법은 동적 인수를 사용하는 것입니다.
def add(*args):
return sum(args)
이것은 여러분이 찾고 있는 답이 아닙니다. 여러분도 아실지도 모르지만, 저는 어쨌든 누군가가 호기심 때문이 아니라 일을 위해 이것을 하는 것에 대해 궁금해한다면 그것을 줄 것이라고 생각했습니다.그들은 아마도 "올바른 일"이라는 답을 가져야 할 것입니다.
언급URL : https://stackoverflow.com/questions/39038358/function-chaining-in-python
'programing' 카테고리의 다른 글
WPF 컨트롤의 여백 속성의 일부만 바인딩 (0) | 2023.05.15 |
---|---|
다른 테이블의 필드에서 한 테이블의 SQL 업데이트 필드 (0) | 2023.05.15 |
특정 화이트리스트를 제외한 모든 HTML 태그를 필터링하려면 어떻게 해야 합니까? (0) | 2023.05.15 |
Xcode에서 기호 파일 처리 (0) | 2023.05.10 |
상황에 맞는 메뉴의 메뉴 항목에서 요소 이름 바인딩 (0) | 2023.05.10 |