thực hiện đệ quy
Dưới đây là một việc thực hiện đệ quy, mà tôi đã chưa nhìn thấy:
def compose(*funcs):
def inner(data, funcs=funcs):
return inner(funcs[-1](data), funcs[:-1]) if funcs else data
return inner
Tôi không mong đợi nó sẽ rất performant, tuy nhiên, vì nó làm cho một tuple mới đối số mỗi cuộc gọi đệ quy.
So sánh tất cả các gợi ý:
Hãy kiểm tra một số trong những triển khai và xác định đó là performant nhất, lần đầu tiên một số chức năng đối số duy nhất (Cảm ơn bạn poke):
def square (x):
return x ** 2
def increment (x):
return x + 1
def half (x):
return x/2
Đây là triển khai của chúng tôi, tôi nghi ngờ phiên bản lặp lại là phiên bản thứ hai hiệu quả nhất (soạn thảo thủ công sẽ tự nhiên là nhanh nhất).
from functools import reduce
def recursive_compose(*funcs):
def inner(data, funcs=funcs):
return inner(funcs[-1](data), funcs[:-1]) if funcs else data
return inner
def iterative_compose(*functions):
def inner(arg):
for f in reversed(functions):
arg = f(arg)
return arg
return inner
def _compose2(f, g):
return lambda *a, **kw: f(g(*a, **kw))
def reduce_compose1(*fs):
return reduce(_compose2, fs)
def reduce_compose2(*funcs):
"""bug fixed - added reversed()"""
return lambda x: reduce(lambda acc, f: f(acc), reversed(funcs), x)
Và để kiểm tra sau đây:
import timeit
composes = (recursive_compose, iterative_compose,
reduce_compose1, reduce_compose2)
def manual():
return square(increment(half(5)))
print('manual compose', min(timeit.repeat(manual)), manual())
for compose in composes:
fn = lambda: compose(square, increment, half)(5)
result = min(timeit.repeat(fn))
print(compose.__name__, result, fn())
Kết quả
Và chúng tôi nhận được kết quả như sau (cùng độ lớn và tỷ lệ bằng Python 2 và 3):
manual compose 0.607658714056015 12.25
recursive_compose 1.929560380987823 12.25
iterative_compose 1.3319460819475353 12.25
reduce_compose1 2.0850532418116927 12.25
reduce_compose2 1.5899418010376394 12.25
Và kỳ vọng của tôi đã được xác nhận: nhanh nhất là tất nhiên, thành phần chức năng thủ công theo sau là việc thực hiện lặp lại. Phiên bản đệ quy chậm hơn nhiều - có khả năng vì khung ngăn xếp mới được tạo bởi mỗi cuộc gọi hàm và một bộ hàm mới được tạo cho mỗi hàm.
Cảm ơn câu trả lời, nó thực sự làm việc cho tôi. Tôi đã sử dụng phương pháp thứ hai. Bạn có thể giải thích những gì bạn có nghĩa là "đóng cửa cuối cùng tham khảo cùng một tế bào f", và cũng có thể bạn hãy giải thích phương pháp đầu tiên. – Starless
@Không sao tôi đã cập nhật câu trả lời với lời giải thích dài hơn. – user4815162342