ฉันจะเขียนฟังก์ชันที่ส่งคืนฟังก์ชันอื่นได้อย่างไร


93

ใน Python ฉันต้องการเขียนฟังก์ชันmake_cylinder_volume(r)ที่ส่งคืนฟังก์ชันอื่น ฟังก์ชั่นที่ควรจะกลับ callable กับพารามิเตอร์hและกลับปริมาตรของทรงกระบอกที่มีความสูงและรัศมีhr

ฉันรู้วิธีคืนค่าจากฟังก์ชันใน Python แต่ฉันจะคืนค่าฟังก์ชันอื่นได้อย่างไร


คำตอบ:


191

ลองใช้ Python:

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

ใช้แบบนี้เช่นกับradius=10และheight=5:

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

สังเกตว่าการส่งคืนฟังก์ชันเป็นเรื่องง่ายๆในการกำหนดฟังก์ชันใหม่ภายในฟังก์ชันและส่งคืนฟังก์ชันในตอนท้ายโดยระมัดระวังในการส่งผ่านพารามิเตอร์ที่เหมาะสมสำหรับแต่ละฟังก์ชัน FYI เทคนิคของการกลับมาจากการทำงานฟังก์ชั่นอื่นเป็นที่รู้จักกันcurrying


1
ดังนั้น10คุณผ่านจะถูกเก็บไว้ที่อื่น? เมื่อไหร่จะได้รับขยะ?
sudo


19

การใช้ lambdas หรือที่เรียกว่าฟังก์ชันที่ไม่ระบุตัวตนคุณสามารถสรุปvolumeฟังก์ชันภายในmake_cylinder_volume_funcบรรทัดเดียวได้ ไม่แตกต่างจากคำตอบของÓscarLópez แต่อย่างใดการแก้ปัญหาโดยใช้ lambda ยังคงมีความหมายว่า 'ใช้งานได้ดีกว่า'

นี่คือวิธีที่คุณสามารถเขียนคำตอบที่ยอมรับโดยใช้นิพจน์แลมบ์ดา:

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

จากนั้นเรียกตามที่คุณต้องการฟังก์ชั่น curried อื่น ๆ :

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

ฉันรู้ว่าคุณกำลังตอบรับสิ่งที่ร้องขอ แต่เพื่อความเข้าใจของฉันถ้าlambda h:ถูกลบออกฟังก์ชันจะทำงานเหมือนเดิมหรือไม่?
schoon

2
@schoon ไม่มันจะใช้ไม่ได้ในกรณีนี้ นี่เป็นกรณีที่น่าสนใจมากในการเน้นแนวคิดของ 'การกำหนดขอบเขตตัวแปร' และการทำงานของแกง (ซึ่งโดยพื้นฐานแล้วขึ้นอยู่กับขอบเขตตัวแปร) สาเหตุที่ไม่ได้ผล (ในตัวอย่างของฉัน) เป็นเพราะreturnจะพยายามประเมินผลลัพธ์ก่อนที่จะส่งคืนและเนื่องจากเป็นตัวแปรจำนวนมากจึงส่งคืนค่า float (ลองส่งคืนฟังก์ชันและจะได้ผล) 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ทำงาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.