如何编写返回另一个函数的函数?


93

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

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


Answers:


191

使用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


1
那么10您传入的消息存储在某个地方?什么时候进行垃圾回收?
sudo


19

使用lambda(也称为匿名函数),您可以将volume函数内部的内容抽象make_cylinder_volume_func为一行。与ÓscarLó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 '18

2
@schoon不,在这种情况下不起作用。实际上,这是一个非常有趣的案例,突出了“变量作用域”和函数泛化(基本上依赖于变量作用域)的概念。它不起作用的原因(在我的示例中)是因为return它将尝试在返回之前评估结果,并且由于它是一堆变量,它将返回一些浮点值(尝试返回一个函数,它将起作用)。lambdatellsl告诉我们,不应评估以下代码,并且变量r的范围将保留在由返回的函数中make_cylinder..
DaveIdito

10

只想指出,您可以使用pymonad做到这一点

 import pymonad 

 @pymonad.curry
 def add(a, b):
     return a + b

 add5 = add(5)
 add5(4)
 9

1
from functools import partial add5 = partial(add, 5)
确实

1

我知道我参加聚会已经太迟了,但是我认为您可能会发现此解决方案很有趣。

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

这是有关工作原理的文档partial

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.