สัญชาตญาณของคุณเกี่ยวกับเรื่องนี้ถูกต้องมีวิธีที่ดีกว่าที่จะทำเช่นนี้: monads
Monads คืออะไร
Monads คือ (เพื่อแปลความหมาย Wikipedia) วิธีการผูกมัดการดำเนินงานร่วมกันในขณะที่ซ่อนกลไกการผูกมัด; ในกรณีของคุณกลไกการผูกมัดเป็นif
s ที่ซ้อนกัน ซ่อนที่และรหัสของคุณจะมีกลิ่นหอมมากดีกว่า
มีพระสองสามองค์ที่จะทำเช่นนั้น ("อาจจะ" และ "ทั้งสอง") และโชคดีสำหรับคุณพวกเขาเป็นส่วนหนึ่งของห้องสมุดไพ ธ อนที่ดีจริงๆ!
สิ่งที่พวกเขาสามารถทำเพื่อรหัสของคุณ
นี่คือตัวอย่างการใช้ monad "Either" ("Failable" ในไลบรารีที่เชื่อมโยงกับ) ซึ่งฟังก์ชันสามารถส่งคืนสำเร็จหรือล้มเหลวขึ้นอยู่กับสิ่งที่เกิดขึ้น:
import os
class DoSomething(object):
def remove_file(self, filename):
try:
os.remove(filename)
return Success(None)
except OSError:
return Failure("There was an OS Error.")
@do(Failable)
def process_file(self, filename):
do_something()
yield remove_file(filename)
do_something_else()
mreturn(Success("All ok."))
ตอนนี้สิ่งนี้อาจดูไม่แตกต่างจากที่คุณมีในตอนนี้มากนัก แต่ให้พิจารณาว่าจะเป็นอย่างไรถ้าคุณมีการดำเนินการมากขึ้นซึ่งอาจส่งผลให้เกิดความล้มเหลว:
def action_that_might_fail_and_returns_something(self):
# get some random value between 0 and 1 here
if value < 0.5:
return Success(value)
else:
return Failure("Bad value! Bad! Go to your room!")
@do(Failable)
def process_file(self, filename):
do_something()
yield remove_file(filename)
yield action_that_might_fail(somearg)
yield another_action_that_might_fail(someotherarg)
some_val = yield action_that_might_fail_and_returns_something()
yield something_that_used_the_return_value(some_val)
do_something_else()
mreturn(Success("All ok."))
ที่แต่ละyield
s ในprocess_file
ฟังก์ชั่นถ้าการเรียกฟังก์ชั่นส่งกลับความล้มเหลวแล้วprocess_file
ฟังก์ชั่นจะออกจากที่จุดนั้นคืนค่าความล้มเหลวจากฟังก์ชั่นที่ล้มเหลวแทนการดำเนินการต่อผ่านส่วนที่เหลือและกลับSuccess("All ok.")
ตอนนี้ลองนึกภาพทำข้างต้นกับif
s ซ้อนกัน! (คุณจะจัดการกับค่าส่งคืนได้อย่างไร!)
ข้อสรุป
Monads นั้นดี :)
หมายเหตุ:
ฉันไม่ใช่โปรแกรมเมอร์ของ Python - ฉันใช้ไลบรารี่ monad ที่ลิงค์ไปด้านบนในสคริปต์ที่ฉันนินจาทำเพื่อการทำโปรเจ็กต์อัตโนมัติ แม้ว่าฉันจะรวบรวมว่าโดยทั่วไปแล้ววิธีการใช้สำนวนที่ต้องการคือการใช้ข้อยกเว้น
IIRC มีการพิมพ์ผิดในสคริปต์ lib บนหน้าเชื่อมโยงถึงแม้ว่าฉันจะลืมว่ามันอยู่ที่ไหน ATM ฉันจะอัปเดตถ้าฉันจำได้ ฉันกระจายเวอร์ชันของฉันกับหน้าและพบว่า: def failable_monad_examle():
-> def failable_monad_example():
- p
ในexample
นั้นหายไป
เพื่อให้ได้ผลลัพธ์ของฟังก์ชั่นการตกแต่งที่พร้อมใช้งาน (เช่นprocess_file
) คุณต้องจับผลลัพธ์ในvariable
และทำvariable.value
เพื่อให้ได้รับ