함수형 프로그래밍의 'fold'함수에 해당하는 'pythonic'은 무엇입니까?
Haskell에서 다음과 같은 것을 달성하는 가장 관용적 인 방법은 무엇입니까?
foldl (+) 0 [1,2,3,4,5]
--> 15
또는 Ruby에서 이에 상응하는 것 :
[1,2,3,4,5].inject(0) {|m,x| m + x}
#> 15
분명히 파이썬은 reduce
위와 같이 fold의 구현 인 함수를 제공 하지만, 프로그래밍의 'pythonic'방식은 가능한 경우 lambda
목록 이해를 선호하는 용어와 고차 함수 를 피하는 것이라고 들었습니다 . 따라서 reduce
함수 가 아닌 Python에서 목록 또는 목록과 유사한 구조를 접는 선호하는 방법 reduce
이 있습니까? 아니면 이것을 달성하는 관용적 방법입니까?
배열을 합하는 Pythonic 방법은 sum
. 다른 목적을 위해 때때로 reduce
( functools
모듈에서)와 모듈의 조합을 사용할 수 있습니다 operator
. 예 :
def product(xs):
return reduce(operator.mul, xs, 1)
그주의 reduce
사실이다 foldl
하스켈 측면에서. 폴드를 수행하는 특별한 구문도없고 내장도 없으며 foldr
실제로 reduce
비 연관 연산자와 함께 사용 하는 것은 잘못된 스타일로 간주됩니다.
고차 함수를 사용하는 것은 매우 비단뱀 적입니다. 함수와 클래스를 포함하여 모든 것이 객체라는 파이썬의 원칙을 잘 활용합니다. 람다가 일부 Pythonistas에 의해 눈살을 찌푸리는 것은 맞지만 대부분 복잡해지면 읽기가 쉽지 않기 때문입니다.
Haskell
foldl (+) 0 [1,2,3,4,5]
파이썬
reduce(lambda a,b: a+b, [1,2,3,4,5], 0)
분명히 그것은 요점을 설명하는 사소한 예입니다. 파이썬에서는 그냥 할 sum([1,2,3,4,5])
것이고 심지어 Haskell 순수 주의자들도 일반적으로 선호 할 것 sum [1,2,3,4,5]
입니다.
명백한 편의 기능이없는 사소하지 않은 시나리오의 경우 관용적 파이썬 접근 방식은 for 루프를 명시 적으로 작성하고 reduce
또는 을 사용 하는 대신 가변 변수 할당을 사용 하는 것 fold
입니다.
그것은 전혀 기능적인 스타일은 아니지만 "파이썬"방식입니다. Python은 기능적 순수 주의자를 위해 설계되지 않았습니다. 파이썬이 어떻게 작동하지 않는 관용적 파이썬이 있는지 확인하려면 흐름 제어에 대한 예외를 선호하는 방법을 참조하십시오.
Python 3에서는 reduce
이 제거되었습니다. 릴리스 정보 . 그럼에도 불구하고 functools 모듈을 사용할 수 있습니다.
import operator, functools
def product(xs):
return functools.reduce(operator.mul, xs, 1)
반면에 문서는 for
대신 -loop에 대한 선호를 표현 reduce
하므로 다음과 같습니다.
def product(xs):
result = 1
for i in xs:
result *= i
return result
휠을 재발 명 할 수도 있습니다.
def fold(f, l, a):
"""
f: the function to apply
l: the list to fold
a: the accumulator, who is also the 'zero' on the first call
"""
return a if(len(l) == 0) else fold(f, l[1:], f(a, l[0]))
print "Sum:", fold(lambda x, y : x+y, [1,2,3,4,5], 0)
print "Any:", fold(lambda x, y : x or y, [False, True, False], False)
print "All:", fold(lambda x, y : x and y, [False, True, False], True)
# Prove that result can be of a different type of the list's elements
print "Count(x==True):",
print fold(lambda x, y : x+1 if(y) else x, [False, True, True], 0)
질문에 대한 답은 아니지만 foldl 및 foldr에 대한 한 줄 :
a = [8,3,4]
## Foldl
reduce(lambda x,y: x**y, a)
#68719476736
## Foldr
reduce(lambda x,y: y**x, a[::-1])
#14134776518227074636666380005943348126619871175004951664972849610340958208L
이 (줄이기) 문제에 대한 실제 대답은 : 그냥 루프를 사용하십시오!
initial_value = 0
for x in the_list:
initial_value += x #or any function.
이것은 감소보다 빠르며 PyPy와 같은 것들은 이와 같은 루프를 최적화 할 수 있습니다.
BTW, 합계 케이스는 sum
함수 로 해결해야 합니다.
시작 Python 3.8
및 할당 표현식 (PEP 572) ( :=
연산자) 의 도입으로 표현식 결과의 이름을 지정할 수 있습니다. 목록 이해를 사용하여 다른 언어에서 fold / foldleft / reduce 작업을 호출하는 것을 복제 할 수 있습니다.
목록, 축소 함수 및 누산기가 제공됩니다.
items = [1, 2, 3, 4, 5]
f = lambda acc, x: acc * x
accumulator = 1
we can fold items
with f
in order to obtain the resulting accumulation
:
[accumulator := f(accumulator, x) for x in items]
# accumulator = 120
or in a condensed formed:
acc = 1; [acc := acc * x for x in [1, 2, 3, 4, 5]]
# acc = 120
Note that this is actually also a "scanleft" operation as the result of the list comprehension represents the state of the accumulation at each step:
acc = 1
scanned = [acc := acc * x for x in [1, 2, 3, 4, 5]]
# scanned = [1, 2, 6, 24, 120]
# acc = 120
I may be quite late to the party, but we can create custom foldr
using simple lambda calculus and curried function. Here is my implementation of foldr in python.
def foldr(func):
def accumulator(acc):
def listFunc(l):
if l:
x = l[0]
xs = l[1:]
return func(x)(foldr(func)(acc)(xs))
else:
return acc
return listFunc
return accumulator
def curried_add(x):
def inner(y):
return x + y
return inner
def curried_mult(x):
def inner(y):
return x * y
return inner
print foldr(curried_add)(0)(range(1, 6))
print foldr(curried_mult)(1)(range(1, 6))
Even though the implementation is recursive (might be slow), it will print the values 15
and 120
respectively
I believe some of the respondents of this question have missed the broader implication of the fold
function as an abstract tool. Yes, sum
can do the same thing for a list of integers, but this is a trivial case. fold
is more generic. It is useful when you have a sequence of data structures of varying shape and want to cleanly express an aggregation. So instead of having to build up a for
loop with an aggregate variable and manually recompute it each time, a fold
function (or the Python version, which reduce
appears to correspond to) allows the programmer to express the intent of the aggregation much more plainly by simply providing two things:
- A default starting or "seed" value for the aggregation.
- A function that takes the current value of the aggregation (starting with the "seed") and the next element in the list, and returns the next aggregation value.
'program story' 카테고리의 다른 글
JSF 대 Facelets 대 JSP (0) | 2020.08.12 |
---|---|
$ (document) .ready 필요합니까? (0) | 2020.08.12 |
create-react-app webpack 구성 및 파일은 어디에 있습니까? (0) | 2020.08.12 |
CSS에서 @import와 링크의 차이점 (0) | 2020.08.12 |
Excel 2007에서 줄 바꿈이있는 CSV 가져 오기 (0) | 2020.08.12 |