【问题标题】:How do I write a function that returns another function?如何编写返回另一个函数的函数?
【发布时间】:2012-12-25 01:12:05
【问题描述】:

在 Python 中,我想编写一个函数make_cylinder_volume(r),它返回另一个函数。该返回的函数应该可以使用参数h 调用,并返回高度为h 和半径为r 的圆柱体的体积。

我知道如何从 Python 中的函数返回 ,但是如何返回 另一个函数

【问题讨论】:

标签: python function functional-programming currying


【解决方案1】:

这是一个庞大的例子,它涵盖了一个函数中的许多单个多参数情况

def maths(var='NA'):
if var.lower() == 'add':
    def add(*args):
        return "Sum is : "+str(sum(args))
    return add
elif var.lower() == 'substract':
    def substract(a,b):
        if a>b:
            return "Difference is : "+str(a-b)
        else:
            return "Difference is : "+str(b-a)
    return substract
elif var.lower() == 'multiply':
    def multiply(*args):
        temp = 1
        for x in args:
            temp = temp*x
        return "multiplication is : "+str(temp)
    return multiply
elif var.lower() == 'divide':
    def divide(a,b):
        return "Division is : "+str(a/b)
    return divide
else:
    print("Please choose one of given operations: 'add','substract','multiply','divide'")

这里先调用需要运算的数学函数,然后使用返回的函数进行实际计算

【讨论】:

    【解决方案2】:

    我知道我来晚了,但我想你可能会觉得这个解决方案很有趣。

    from math import pi
    from functools import partial
    
    def cylinder_volume(r, h):
        return pi * r * r * h
    
    make_cylinder_with_radius_2 = partial(cylinder_volume, 2)
    make_cylinder_with_height_3 = partial(cylinder_volume, h=3)
    
    print(cylinder_volume(2, 3))            # 37.6991118431
    print(make_cylinder_with_radius_2(3))   # 37.6991118431
    print(make_cylinder_with_height_3(2))   # 37.6991118431
    

    这里是documentationpartial 的工作原理。

    【讨论】:

      【解决方案3】:

      使用 lambda,也称为匿名函数,您可以将 make_cylinder_volume_func 内的 volume 函数抽象为一行。与 Óscar López 的回答没有什么不同,使用 lambda 的解决方案在某种意义上仍然“更具功能性”。

      这是您可以使用 lambda 表达式编写接受的答案的方法:

      import math
      def make_cylinder_volume_fun(r):
          return lambda h: math.pi * r * r * h
      

      然后像调用任何其他咖喱函数一样调用:

      volume_radius_1 = make_cylinder_volume_fun(1)
      volume_radius_1(1) 
      => 3.141592653589793
      

      【讨论】:

      • 我知道您正在回答所要求的内容,但为了我的理解,如果 lambda h: 被删除,该功能是否会起作用?
      • @schoon 不,在这种情况下它不起作用。这实际上是一个非常有趣的案例,突出了“变量作用域”和函数柯里化(基本上依赖于变量作用域)的概念。它不起作用的原因(在我的示例中)是因为return 会在返回之前尝试评估结果,并且因为它是一堆变量,它会返回一些浮点值(尝试返回一个函数,它会工作)。 lambda 告诉我们不应评估以下代码,并且变量 r 的范围将保留在 make_cylinder.. 返回的函数中。
      【解决方案4】:

      只是想指出你可以用 pymonad 做到这一点

       import pymonad 
      
       @pymonad.curry
       def add(a, b):
           return a + b
      
       add5 = add(5)
       add5(4)
       9
      

      【讨论】:

      • from functools import partial add5 = partial(add, 5) 完全一样
      【解决方案5】:

      用 Python 试试这个:

      import math
      def make_cylinder_volume_func(r):
          def volume(h):
              return math.pi * r * r * h
          return volume
      

      像这样使用它,例如与radius=10height=5

      volume_radius_10 = make_cylinder_volume_func(10)
      volume_radius_10(5)
      => 1570.7963267948967
      

      请注意,返回一个函数很简单,只需在函数内部定义一个新函数,然后在最后返回它——注意为每个函数传递适当的参数。仅供参考,从另一个函数返回一个函数的技术称为currying

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 2010-09-15
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      相关资源
      最近更新 更多