是否存在将基于范围的分段函数分组为单个函数的pythonic方法?

时间:2013-06-26 15:05:09

标签: python function lambda

我有一系列函数[f(x),g(x),...]
我想要做的是根据x的值所在的范围调用适当的函数。

f = lambda x: x+1
g = lambda x: x-1
h = lambda x: x*x
funcs = [f,g,h]
def superFunction(x):
    if x <= 20:
      return(funcs[0](x))
    if 20 < x <= 40:
      return(funcs[1](x))
    if x > 40:
      return(funcs[2](x))

有没有更好/ pythonic的方法来处理动态数量的函数

计划是沿着数据部分动态生成n个polyfit函数,然后将它们组合成单个可调用函数。

4 个答案:

答案 0 :(得分:3)

您将使用调度序列:

funcs = (
    (20, f),
    (40, g),
    (float('inf'), h),
)

def superFunction(x):
    for limit, f in funcs:
        if x <= limit:
            return f(x)

或者如果功能和限制列表很大,请使用bisect搜索来查找最接近的限制。

答案 1 :(得分:1)

使用NumPy进行超快速选择,以防你有很多选择(否则,为什么不坚持使用“if”语句):

import numpy as np
funcs = np.array([(20,f), (40,g), (np.inf,h)])

def superFunction(x):
    idx = np.argmax(x <= funcs[:,0])
    return funcs[idx,1](x)

这与原始代码类似,但函数选择发生在C而不是Python循环中。

答案 2 :(得分:0)

您可以使用通用功能。例如,PEAK-Rules允许这样做。你的代码看起来像这样:

import peak.rules as pr

def myfunc(x):
    return x * x

@pr.when(myfunc, "x <= 20")
def myfunc_f(x):
    return x + 1

@pr.when(myfunc, "20 < x <= 40")
def myfunc_g(x):
    return x - 1

>>> myfunc(10)
11
>>> myfunc(30)
29
>>> myfunc(50)
2500

通用功能的一个优点是它们不需要在一个地方定义。 myfunc_g可以在myfunc的单独文件中定义。

有一些问题非常适合,例如将自定义JSON编码规则添加到现有类。沿着这条路走下去之前要仔细考虑,我已经看到使用泛型函数使代码变得不必要复杂的例子。您在上面给出的示例我将完全保留您的呈现方式 - 尽管我希望您的实际代码更复杂。

答案 3 :(得分:0)

我会利用lambdas可以用作dict键的事实。从根本上说,你将这些条件与一个函数联系在一起,所以我认为它很合适。您只需修改一个地方即可添加新条件,这也是一种改进。

funcs = {
    lambda x: x <= 20: lambda x: x + 1,
    lambda x: 20 < x <= 40: lambda x: x - 1,
    lambda x: x > 40: lambda x: x * x,
}

def superFunction(x):
    for condition, fn in funcs.iteritems():
        if condition(x):
            return fn(x)