【问题标题】:Programmatically define a new function from a list of other functions以编程方式从其他函数列表中定义一个新函数
【发布时间】:2016-08-05 12:43:15
【问题描述】:

我有:

def f(x, y): return x**2 + y**2
def g(x, y): return x**3 + y**3
def h(x, y): return x**4 + y**4

我想做一个新功能:

def J(x, y):
    return f(x,y)*g(x,y)*h(x,y)

但是,我无法找到以编程方式执行此操作的方法。 也就是说,采取如下方式:

myFunctions = [f,g,h]

并返回一个新函数J,它返回fgh的乘积。

另一个问题是,虽然 fgh 将始终具有相同数量的参数,但该数量可能会改变。也就是说,他们都可以有五个参数而不是两个。

期望的行为:

print(J(2, 2)) # 4096

编辑

myFunctions 中的函数数量也是任意的。 我认为这是在我的问题中暗示的,但是在重读它时,我发现我根本没有说清楚。我很抱歉。

【问题讨论】:

  • 您有什么理由不将J 定义为def J(*args, **kwargs)?您是否出于任何其他原因需要这些参数?
  • 您是否创建函数列表?如果是这样,您可以使用 *args 将可选数量的位置参数传递给您的函数。
  • 您可以在 Python 中使用functools.reduceoperator.mulfunctools.partial 和其他功能工具来执行此操作。正如其他 cmets 所指出的,您可以轻松定义任意位置和关键字参数。
  • @VincentSavard 不是名字本身,不。

标签: python python-3.x functional-programming


【解决方案1】:

一个函数可以像这样使用* 接受任意多个参数:

def J(*args):

这会将J 的所有参数存储在args 列表中。然后可以将该列表转换回多个参数以调用其他函数,如下所示:

def J(*args):
  return f(*args) * g(*args)

这解决了参数数量变化的问题。所以现在让我们处理可以有任意多个函数的事实。首先,我们需要调用列表中的函数。我们可以通过迭代它们并使用()来做到这一点:

def J(*args):
  return [func(*args) for func in myFunctions]

这将返回函数返回值的列表。所以我们现在需要的就是得到一个集合的产品:

from functools import reduce
from operator import mul

def product(numbers):
  return reduce(mul, list, 1)

def J(*args):
  return product(func(*args) for func in myFunctions)

【讨论】:

    【解决方案2】:

    您可以允许J 接受尽可能多的参数,然后将 f、g 和 h 给出的最终列表相乘:

    def f(x, y): return x**2 + y**2
    
    def g(x, y): return x**3 + y**3
    
    def h(x, y): return x**4 + y**4
    
    def multiply(mylist):
        return reduce(lambda a, b: a*b, mylist)
    
    myfuncs = [f,g,h]
    def J(*args):
        return multiply([myfunc(*args) for myfunc in myfuncs])
    

    由于 f、g 和 h 将具有相同数量的参数,因此这应该适用于所有情况。

    【讨论】:

    • 问题被标记为 Python 3,因此您必须从 itertools 导入 reduce。还不如导入 operator.mul 而不是构建自己的 multiply 函数。
    【解决方案3】:

    另一种选择:

    from functools import reduce, partial
    from operator import mul
    
    def f(x, y): return x**2 + y**2
    def g(x, y): return x**3 + y**3
    def h(x, y): return x**4 + y**4
    
    myFunctions = [f,g,h]
    
    J = partial(lambda funcs, *args: reduce(mul, (func(*args) for func in funcs), 1), myFunctions)
    print J(2, 2)
    

    J 具有与函数 f、g 和 h 相同数量的参数而不是 *args 的优点。

    【讨论】:

    • 这并不使用myFunctions - 它只是硬编码fgh
    • 同意,我已经改进了答案(受您的启发),谢谢
    【解决方案4】:

    参数数量可变的问题可以这样解决:

    def f(*args): return sum(map(lambda x: x**2, args))
    
    def g(*args): return sum(map(lambda x: x**3, args))
    
    def h(*args): return sum(map(lambda x: x**4, args))
    

    然后你可以简单地定义J函数

    def J(*args):
        return f(*args)*g(*args)*h(*args)
    

    如果你想支持可变数量的函数,那么你可以定义 J 如下,并将函数列表作为列表的第一项传入,参数作为以下项传入。

    def J(*args):
        funcs = args[0]            
        args = args[1:]           
        temp = map(lambda x: x(*args), funcs)
        return reduce(lambda x,y: x*y, temp, 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 2019-03-11
      • 2023-03-16
      • 2014-12-18
      相关资源
      最近更新 更多