ทำให้โค้ด "ส่วนหนึ่ง" ของ Python สามารถ "รันอีกรอบ" ได้
มันมีหลาย ๆ กรณีเช่นหากโค้ดส่วนหนึ่งของเราเจอปัญหา อาจจะเกิด error ขึ้นแล้ว exception handler ของเราจับได้ หากว่าปัญหานี้สามารถแก้ได้ด้วยการ “ลองอีกครั้ง” เราก็อาจจะต้องแก้ปัญหาด้วยวิธีการวน loop ครอบไว้ส่วนของโค้ดนี้ เช่น
while True:
try:
... do stuff ...
break
except Exception:
continue
ซึ่งก็จะทำงานได้ตามปรกติ … แต่สำหรับผมแล้วผมมองว่ามันอ่านเข้าใจได้ยาก เพราะการใช้ while loop นั่นเอง .. มันไม่ได้บอกเราตรง ๆ ว่าเรากำลังจะทำอะไร คนอ่านจะต้อง “อ่านโค้ดให้หมด” จึงจะเข้าใจสิ่งที่เราทำ แล้วเราก็อาจจะพลาดการใส่ break ตอนสุดท้ายของโค้ดไปได้ง่าย ๆ … ซึ่งไม่ดีเลย
ผมเลยลองหาวิธีใหม่ที่น่าจะงดงามกว่านี้ ควรจะอ่านเป็นภาษาอังกฤษแล้วเข้าใจได้เลย แล้วก็ทนทานต่อปัญหาหยุมหยิบแบบนี้มากกว่านี้ (ก็ไม่รู้เหมือนกันว่าวิธีที่เสอนนี่จะดีขนาดไหน) ซึ่งก็จะได้เป็น function decorator แบบนี้ครับ
def autorun(fn):
def rerun():
wrapper(rerun)
def wrapper(rerun):
fn(rerun)
wrapper(rerun)
return wrapper
decorator นี้ชื่อว่า autorun
ซึ่งต้องการ function ที่รับ parameter 1 ตัว ซึ่งก็คือ function สำหรับรันตัวเองอีกครั้ง ลองดูวิธีการใช้งานเลยดีกว่า
shared = {'a': 0}
@autorun
def _(retry):
print('rerun')
shared['a'] += 1
if shared['a'] < 10:
retry()
assert shared['a'] == 10
ผมได้ลองสร้างฟังก์ชันไร้นาม _
ขึ้นมาหนึ่งตัวแล้วก็ใส่ decorator ให้มันเสีย ซึ่งจะเห็นจากโค้ดได้ว่าฟังก์ชัน _
ถูกรันเองเลยเราไม่ต้องไปสั่งให้มันทำงานตรง ๆ แต่อย่างใด
ถ้าเขียนเป็นโค้ดโดยทั่วไปก็จะเป็นแบบนี้
@autorun
def _(retry):
try:
... do stuff ...
except Exception:
retry()
หวังว่านี่น่าจะงดงามขึ้นกว่าอันเดิมที่ใช้ while loop นะครับ ๕๕๕