2016-08-24 15 views
7

Tôi có một giá trị đầu vào val và một danh sách các hàm được áp dụng theo thứ tự:Áp dụng một danh sách các hàm Python để thanh lịch

funcs = [f1, f2, f3, ..., fn] 

Làm thế nào để áp dụng thanh lịch và không viết

fn(... (f3(f2(f1(val))) ...) 

và cũng không sử dụng cho vòng lặp:

tmp = val 
for f in funcs: 
    tmp = f(tmp) 

Cảm ơn Martijn vì câu trả lời tuyệt vời. Có một số đọc tôi tìm thấy: https://mathieularose.com/function-composition-in-python/.

Trả lời

17

Sử dụng reduce() function:

# forward-compatible import 
from functools import reduce 

result = reduce(lambda res, f: f(res), funcs, val) 

reduce() áp dụng đối số đầu tiên, một callable, để mỗi phần tử lấy từ số thứ hai, cộng với kết quả tích lũy cho đến nay (như (result, element)). Đối số thứ ba là giá trị bắt đầu (phần tử đầu tiên từ funcs sẽ được sử dụng khác).

Trong Python 3, hàm dựng sẵn được di chuyển đến functools.reduce() location; cho khả năng tương thích về phía trước mà cùng một tham chiếu có sẵn trong Python 2.6 trở lên.

Các ngôn ngữ khác có thể gọi số này folding.

Nếu bạn cần trung kết quả cho từng chức năng quá, sử dụng itertools.accumulate() (chỉ từ Python 3.3 trở đi cho một phiên bản mà phải mất một tham số chức năng):

from itertools import accumulate, chain 
running_results = accumulate(chain(val, funcs), lambda res, f: f(res)) 
+0

Perfect câu trả lời! Tôi yêu 'List.fold_left' của OCaml và bằng Python, chúng ta có' functools.reduce() ':) – Viet

+2

@Viet: xem [danh sách Wikipedia * gấp * trong các ngôn ngữ lập trình khác nhau] (https://en.wikipedia.org/wiki/Fold_ (thứ tự cao hơn_function) #Folds_in_various_languages). –

1

MartijnPieters trả lời là tuyệt vời. Điều duy nhất tôi sẽ thêm được rằng điều này được gọi là function composition

Đặt tên cho những Generics có nghĩa là bạn có thể sử dụng chúng bất cứ khi nào có nhu cầu

from functools import reduce 

def id(x): 
    return x 

def comp(f,g): 
    return lambda x: f(g(x)) 

def compose(*fs): 
    return reduce(comp, fs, id) 

# usage 
# compose(f1, f2, f3, ..., fn) (val) 

print(compose (lambda x: x + 1, lambda x: x * 3, lambda x: x - 1) (10)) 
# = ((10 - 1) * 3) + 1 
# = 28 
+0

Cảm ơn bạn đã thêm, @naomik: D – Viet

Các vấn đề liên quan