2013-01-10 6 views
44

In Python, mi piacerebbe scrivere una funzione make_cylinder_volume(r) che restituisce un'altra funzione. Questa funzione restituita deve essere richiamabile con un parametro h e restituire il volume di un cilindro con altezza h e raggio r.Come si scrive una funzione che restituisce un'altra funzione?

so come restituire valori dalle funzioni in Python, ma come faccio a restituire un'altra funzione?

+2

http://stackoverflow.com/questions/245192/what-are-first-class-objects –

risposta

101

Prova questo, utilizzando Python:

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

usare in questo modo, per esempio con radius=10 e height=5:

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

Si noti che il ritorno di una funzione è stata una semplice questione di definire una nuova funzione all'interno della funzione e restituendola alla fine, facendo attenzione a passare i parametri appropriati per ciascuna funzione. Cordiali saluti, la tecnica di restituzione di una funzione da un'altra funzione è nota come currying.

+2

Grazie per l'aggiunta del riferimento al currying. Spero solo di poter invitare due volte. – HeatfanJohn

+1

Quindi il '10' che hai passato è memorizzato da qualche parte? Quando viene raccolto dalla spazzatura? – sudo

+3

@sudo dai un'occhiata a https://en.wikipedia.org/wiki/Closure_(computer_programming) –

6

Voglio solo far notare che si può fare questo con pymonad

import pymonad 

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

add5 = add(5) 
add5(4) 
9 
4

Utilizzando lambda, noto anche come funzioni anonime, si può astrarre la funzione volume all'interno della make_cylinder_volume_func a una singola linea. In nessun modo diverso dalla risposta di Óscar López, la soluzione che utilizza lambda è ancora in un certo senso "più funzionale".

Questo è come si può scrivere la risposta accettata utilizzando un'espressione lambda:

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

E quindi chiamare come ci si qualsiasi altra funzione al curry:

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