คำสั่งแบบ Switch-Case Statements จะสามารถใช้ร่วมกับ Python ได้แล้ว!

Python คำสั่ง
เวอร์ชั่นที่ออกมาใหม่ล่าสุดเผยให้เห็น New Logic (ตรรกะแบบใหม่)
Python 3.10 เริ่มจะเต็มไปด้วยฟีเจอร์ใหม่ ๆ น่าทึ่งหลายอย่าง มีฟีเจอร์หนึ่งที่น่าสนใจมาก — Structural Pattern Matching (การเทียบเคียงรูปแบบแบบมีโครงสร้าง) — หรือที่พวกเรารู้จักกันคือ switch/case statement ซึ่ง Switch-statement ห่างหายไปจาก Python มานานแม้ว่าจะเป็นฟีเจอร์ทั่วไปของเกือบทุกภาษา
ย้อนกลับไปปี 2006 ที่มีการสร้าง PEP 3103 ขึ้น โดยแนะนำให้ดำเนินการตามคำสั่ง Switch-case Statement แต่หลังจากทำแบบสำรวจที่ PyCon 2007 หรืองานสัมมนาเกี่ยวกับภาษาที่ใช้เขียนโปรแกรม พบว่าฟีเจอร์ดังกล่าวไม่ได้รับการสนับสนุนผู้พัฒนา Python จึงล้มเลิกการพัฒนาฟีเจอร์นี้ไป ในปี 2020 และ Guido van Rossum (กวีโด แวน รอสซัม) ผู้สร้าง Python นำเสนอเอกสารกำกับโปรแกรมฉบับแรกภายใต้หัวข้อ Switch-statement แบบใหม่ ที่ถูกตั้งชื่อว่า Structural Pattern Matching ตามที่พบใน PEP 634
โดยสิ่งที่เรามีในตอนนี้เป็นมากกว่าแค่ Switch-case Statement แบบเรียบง่าย ซึ่งเดี๋ยวเราจะได้เห็นกันในบทความนี้
มาดูกันว่าตรรกะแบบใหม่นี้ทำงานอย่างไร
> Structural Pattern Matching
- Intro
- Another Example
- Real Use-Case With JSON
Structural Pattern Matching
Pattern Matching ใช้ค่าตัวเลขหลังจาก match
และช่วยให้เราเขียนเคสที่อาจมีออกมาหลายกรณี โดยแต่ละกรณีจำกัดความว่าเป็น case
ที่เท่าไหร่ และถ้าเราต้องจับคู่ระหว่าง Match และ Case หรือ match-case
เราจะต้องใช้งานโค้ดตามลำดับ
ตัวอย่างเช่น:
http_code = "418"
match http_code:
case "200":
print("OK")
do_something_good()
case "404":
print("Not Found")
do_something_bad()
case "418":
print("I'm a teapot")
make_coffee()
case _:
print("Code not found")
ในส่วนนี้เราต้องตรวจดูเงื่อนไขหลายอย่าง รวมถึงการดำเนินการปฏิบัติการที่แตกต่างกัน โดยขึ้นอยู่กับค่าตัวเลขที่เราพบภายใน http_code

จากแผนผังในด้านบน จะเห็นได้ชัดในทันทีว่าเราสามารถสร้างตรรกะเดียวกันโดยใช้กลุ่มของ If-elif-else Statement:
http_code = "418"
if http_code == "418":
print("OK")
do_something_good()
elif http_code == "404":
print("Not Found")
do_something_bad()
elif http_code == "418"
print("I'm a teapot")
make_coffee()
else:
print("Code not found")
อย่างไรก็ตาม เราสามารถใช้ Match-case Statement ลบการทำซ้ำของ http_code ==
ออก ซึ่งเมื่อทดสอบกับหลากหลายเงื่อนไขจะให้ผลลัพธ์ที่ดูง่ายกว่า
อีกหนึ่งตัวอย่างของ Match-case Statement
เราจะศึกษาตัวอย่างที่ดีของการใช้ Match-case Statement เพื่อปรับปรุงความสามารถในการอ่านโค้ดใน PEP 635 หนึ่งในนั้นคือตัวอย่างนี้ ซึ่งแสดงให้เราเห็นวิธีใช้ Match-case เพื่อตรวจดูประเภทและโครงสร้างของตัวทดสอบของเรา:
match x:
case host, port:
mode = "http"
case host, port, mode:
pass
ในส่วนนี้เรามักจะคาดหวังที่จะได้รายละเอียดการเชื่อมโยงในรูปแบบ Tuple (ทูเพิล) และมอบหมายค่าตัวเลขที่ให้มากับตัวแปรที่ถูกต้อง ซึ่งถ้า mode
การเชื่อมโยงยังไม่ถูกกำหนดภายใน Tuple (ตัวอย่างเช่น มีเพียงค่าตัวเลขสองค่าที่ให้มาคือ host
และ port
) เราสันนิษฐานได้ว่าโหมดการเชื่อมโยงคือ “http”.
อย่างไรก็ตามในกรณีอื่น ๆ เราอาจคาดการณ์ได้ว่าโหมดถูกกำหนดไว้แล้วอย่างชัดเจน เราจึงอาจจะได้รับ Tuple แบบ (<host>, <port>, "ftp")
— ซึ่งในกรณีนี้เราไม่ได้อยากตั้ง mode
เป็น “http”
และถ้าเราอยากจะเขียนตรรกะเดียวกันโดยใช้ If-else Statement เราจะได้สิ่งนี้:
if isinstance(x, tuple) and len(x) == 2:
host, port = x
mode = "http"
elif isinstance(x, tuple) and len(x) == 3:
host, port, mode = x
การเลือกใช้ของแต่ละคนอาจจะแตกต่างกันตามความ แต่สำหรับผมแล้วการใช้งาน Match-case ดูได้สบายตากว่ามาก
กรณีศึกษาของ JSON
อีกกรณีศึกษาหนึ่งที่ดูน่าสนใจคือความสามารถในการแยกวิเคราะห์คำในพจนานุกรมที่แตกต่างกันตามโครงสร้างของมัน กรณีทดสอบที่ดีของเรื่องนี้คือการแยกวิเคราะห์ชุดข้อมูล SQuAD 2 โดยชุดข้อมูล SQuAD 2 เป็นชุดถาม-ตอบที่เป็นที่นิยมมาก ซึ่งใช้ในการฝึกโมเดลเรียนรู้ของเครื่องจักรสำหรับการถาม-ตอบ เราสามารถดาวน์โหลดข้อมูลได้ด้วย:

ถ้าเรามาลองดูโครงสร้างของ SQuAD จะเห็นชัดว่ามีหลากหลายระดับ ซึ่งเราจะต้องพิจารณาเมื่อทำการแยกวิเคราะห์:

แต่ปัญหาคือ ไม่ใช่ว่าทุกตัวอย่างจะสามารถใช้รูปแบบพจนานุกรมแบบเดียวกันได้ ถ้าเราดูสองสามตัวอย่างสุดท้าย เราจะเห็นรายการ qas
มีทั้ง answers
และ plausible_answers
— ขณะที่ตัวอย่างมีเพียงแค่ answers
:

ทีนี้ลองมาใช้ Match-case Statement แบบใหม่เพื่อสร้างทางเลือกที่สบายตากว่าสำหรับตรรกะหนัก ๆ แบบ if-else ที่จำเป็นต้องใช้กับสิ่งนี้ อย่างแรก เราต้องโหลดข้อมูลมาก่อน:

SQuAD JSON มีหลายระดับชั้น หลังจากเข้าถึง squad['data']
เราจำเป็นต้องทำซ้ำในคำถามแต่ละ group
: จากนั้นในแต่ละ paragraph
แล้วในแต่ละ qas
(คำถาม-คำตอบ) — ซึ่งดูเหมือน:
for group in squad['data']:
for paragraph in group['paragraphs']:
for qa in paragraph['qas']:
# insert code here
และนี่คือจุดที่เริ่มสนุกแล้วล่ะ การใช้ตรรกะแบบ if-else เราจะได้อะไรแบบนี้:


แม้ว่ามันจะดูไม่ค่อยสวย แต่มันก็สามารถใช้งานได้ ลองมาเขียนใหม่โดยใช้ตรรกะแบบ match-case
ดูบ้าง:

จะเห็นได้ว่า การใช้ ตรรกะนี้จะช่วยให้ดูซับซ้อนน้อยลงและถือเป็นอีกหนึ่งทางเลือกที่ดีเมื่อเทียบกับเวอร์ชั่นดั้งเดิมที่ใช้ตรรกะการแยกวิเคราะห์
ทั้งหมดมีแค่นี้เป็นเรื่องของ Structural Pattern Matching แบบใหม่ที่นำเสนอใน Python 3.10! แบบสั้น ๆ เท่านั้น เวอร์ชั่นเต็มคาดว่าจะออกมาในต้นเดือนตุลาคม 2021
ส่วนตัวแล้ว ผมคิดว่า Syntax แบบใหม่นี้ดูดีมาก ๆ — แม้ว่าตอนนี้จะมั่นใจได้แค่ 50/50 แต่เมื่อมีผู้ใช้ match-case ทำโค้ดมากขึ้น ผมมั่นใจว่าพวกเขาจะเลือกวิธีการที่ดีที่สุดในการเขียน
บทความโดย James Briggs
เนื้อหาจากบทความของ Medium
แปลและเรียบเรียงโดย ไอสวรรค์ ไชยชะนะ
ตรวจทานและปรับปรุงโดยนววิทย์ พงศ์อนันต์