別の関数を返す関数を作成するにはどうすればよいですか?


93

Pythonで、make_cylinder_volume(r)別の関数を返す関数を書きたいのですが。返される関数は、パラメータを使用して呼び出すことができh、高さhと半径を持つ円柱の体積を返す必要がありますr

Pythonの関数からを返す方法を知っていますが、別の関数を返すにはどうすればよいですか?


回答:


191

Pythonを使用して、これを試してください。

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

このように使用します。たとえば、radius=10and height=5

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

関数を返すことは、関数内に新しい関数を定義し、最後にそれを返すという単純な問題であることに注意してください。各関数に適切なパラメーターを渡すように注意してください。参考までに、別の関数から関数を返す手法は、カリー化と呼ばれます


1
それで、10あなたが渡したあなたはどこかに保存されていますか?ガベージコレクションはいつ行われますか?
sudo 2016年


19

匿名関数とも呼ばれるラムダを使用すると、volume内部の関数を抽象化できます。make_cylinder_volume_func1行に。ÓscarLópezの答えと何ら変わりはありませんが、ラムダを使用したソリューションは、ある意味で「より機能的」です。

これは、ラムダ式を使用して受け入れられた回答を書く方法です。

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:削除された場合、関数は同じように機能しますか?
スクーン2018

2
@schoonいいえ、この場合は機能しません。これは実際には、「変数スコープ」と関数カリー化(基本的にバリバールスコープに依存)のアイデアを強調するための非常に興味深いケースです。それが機能しない理由(私の例では)は、returnが戻る前に結果を評価しようとし、変数の束であるため、float値を返すためです(関数を返してみれば機能します)。lambda次のコードは評価されるべきではなく、変数rのスコープはmake_cylinder..。によって返される関数に保持されることを示しています。
daveIdito 2018

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)まったく同じことをします
R3ctor

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です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.