Python 中的条件函数链接

Ata*_*ias 6 python function chaining

g想象一下,我想通过链接子函数来实现一个函数。这可以通过以下方式轻松完成:

def f1(a):
    return a+1

def f2(a):
    return a*2

def f3(a):
    return a**3

g = lambda x: f1(f2(f3(x)))
Run Code Online (Sandbox Code Playgroud)

然而,现在考虑一下,哪些子功能将链接在一起,取决于条件:具体来说,是预先已知的用户指定的选项。人们当然可以这样做:

def g(a, cond1, cond2, cond3):

    res = a
    if cond1:
        res = f3(res)
    if cond2:
        res = f2(res)
    if cond3:
        res = f1(res)
    return res
Run Code Online (Sandbox Code Playgroud)

然而,我认为最好g提前根据函数的组成函数来定义函数,而不是在每次调用函数时动态检查这些静态条件。不幸的是,以下给出了RuntimeError: maximum recursion depth exceeded

g = lambda x: x
if cond1:
    g = lambda x: f3(g(x))
if cond2:
    g = lambda x: f2(g(x))
if cond3:
    g = lambda x: f1(g(x))
Run Code Online (Sandbox Code Playgroud)

有没有一种好的方法可以在 Python 中实现这种条件链?请注意,要链接的函数可以是 N 个,因此不能单独定义所有 2^N 个函数组合(本例中为 8 个)。

san*_*ash 4

我找到了一种使用装饰器的解决方案。看一看:

def f1(x):
    return x + 1

def f2(x):
    return x + 2

def f3(x):
    return x ** 2


conditions = [True, False, True]
functions = [f1, f2, f3]


def apply_one(func, function):
    def wrapped(x):
        return func(function(x))
    return wrapped


def apply_conditions_and_functions(conditions, functions):
    def initial(x):
        return x

    function = initial

    for cond, func in zip(conditions, reversed(functions)):
        if cond:
            function = apply_one(func, function)
    return function


g = apply_conditions_and_functions(conditions, functions)

print(g(10)) # 101, because f1(f3(10)) = (10 ** 2) + 1 = 101
Run Code Online (Sandbox Code Playgroud)

定义函数时仅检查一次条件g,调用函数时不会检查条件。