Trở lại năm 2006, PEP 3103 đã được nêu ra, khuyến nghị thực hiện câu lệnh switch-case. Tuy nhiên, sau một cuộc thăm dò tại PyCon 2007 không nhận được sự hỗ trợ nào cho tính năng này, các nhà phát triển Python đã bỏ nó.
Chuyển nhanh đến năm 2020 và Guido van Rossum, người tạo ra Python, đã cam kết tài liệu đầu tiên hiển thị các câu lệnh chuyển đổi mới, được đặt tên là So khớp mẫu cấu trúc, như được tìm thấy trong PEP 634
Tuy nhiên, những gì chúng ta có ở đây không chỉ là một câu lệnh trường hợp chuyển đổi đơn giản [do đó là trường hợp đối sánh], như chúng ta sẽ sớm thấy
Hãy xem logic mới này hoạt động như thế nào
> Structural Pattern Matching
- Intro
- Another Example
- Real Use-Case With JSON
Kết hợp mô hình cấu trúc
Khớp mẫu lấy một giá trị theo sau
http_code = "418"if http_code == "418":1 và cho phép chúng tôi viết ra một số trường hợp tiềm năng, mỗi trường hợp được xác định bởi
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"]
http_code = "418"if http_code == "418":2. Khi chúng tôi tìm thấy sự trùng khớp giữa
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"]
http_code = "418"if http_code == "418":1-
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"]
http_code = "418"if http_code == "418":2, chúng tôi sẽ thực thi mã tương ứng
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"]
Ví dụ
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"]
Ở đây, chúng tôi đang kiểm tra nhiều điều kiện và thực hiện các thao tác khác nhau dựa trên giá trị mà chúng tôi tìm thấy bên trong
http_code = "418"if http_code == "418":5
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"]
Luồng logic thông qua câu lệnh khớp trường hợp
Ngay lập tức rõ ràng là có, chúng ta có thể xây dựng logic tương tự bằng cách sử dụng một đoạn câu lệnh if-elif-else
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"]
Tuy nhiên, bằng cách sử dụng câu lệnh so khớp, chúng tôi loại bỏ sự lặp lại của
http_code = "418"match http_code:0Điều này có thể trông rõ ràng hơn nhiều khi thử nghiệm cho nhiều điều kiện khác nhau
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"]
Một vi dụ khac
Chúng ta có thể tìm thấy một số ví dụ tuyệt vời về việc sử dụng câu lệnh so khớp để cải thiện khả năng đọc mã trong PEP 635. Một trong số đó là ví dụ này chỉ cho chúng ta cách sử dụng trường hợp khớp để kiểm tra loại và cấu trúc của chủ đề của chúng ta
match x:
case host, port:
mode = "http"
case host, port, mode:
pass
Ở đây, chúng tôi mong muốn nhận được chi tiết kết nối ở định dạng tuple và gán các giá trị đã cho cho các biến chính xác
Trong trường hợp này, nếu kết nối
http_code = "418"match http_code:1 không được xác định trong bộ dữ liệu [e. g. , chỉ có hai giá trị được cung cấp —
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 = "418"match http_code:2 và
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 = "418"match http_code:3], chúng tôi giả định rằng chế độ kết nối là “http”
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"]
Tuy nhiên, trong các trường hợp khác, chúng tôi có thể mong đợi rằng chế độ được xác định rõ ràng. Vì vậy, thay vào đó, chúng tôi có thể nhận được một bộ dữ liệu như
http_code = "418"match http_code:4 - trong trường hợp đó, chúng tôi không muốn đặt
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 = "418"match http_code:1 thành “http”
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"]
Bây giờ, nếu chúng ta muốn viết cùng logic này bằng cách sử dụng câu lệnh if-else, chúng ta sẽ nhận được điều này
http_code = "418"match http_code:0
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"]
Tùy chọn nào được ưu tiên có thể khác nhau, nhưng đối với tôi, việc triển khai trường hợp đối sánh trông gọn gàng hơn nhiều
Trường hợp sử dụng thực tế với JSON
Một trường hợp sử dụng khác có vẻ thú vị là khả năng phân tích các đối tượng từ điển khác nhau dựa trên cấu trúc của chúng. Một trường hợp sử dụng thử nghiệm tuyệt vời cho việc này là phân tích bộ dữ liệu SQuAD 2
Bộ dữ liệu SQuAD 2 là một tập hợp các cặp câu hỏi-câu trả lời cực kỳ phổ biến được sử dụng để đào tạo các mô hình học máy để trả lời câu hỏi. Chúng tôi có thể tải xuống dữ liệu với
Nếu chúng ta xem xét cấu trúc của SQuAD, rõ ràng có một số cấp độ đối với nó, mà chúng ta sẽ cần xem xét khi phân tích cú pháp
Vấn đề mà chúng tôi gặp phải là không phải tất cả các mẫu đều sử dụng cùng một định dạng từ điển
Nếu xem xét một vài mẫu cuối cùng, chúng ta sẽ thấy rằng danh sách
http_code = "418"match http_code:6 chứa cả
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 = "418"match http_code:7 và
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 = "418"match http_code:8 — trong khi các mẫu trước đó chỉ chứa
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 = "418"match http_code:7
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"]
Mục cuối cùng trong tập huấn luyện SQuAD 2 JSON hiển thị một định dạng từ điển khác [được chia sẻ bởi một số mục trong toàn bộ tệp]
Hãy thử áp dụng các câu lệnh đối sánh trường hợp mới để xây dựng một giải pháp thay thế rõ ràng hơn cho logic if-else nặng nề cần thiết để giải quyết vấn đề này. Đầu tiên, chúng tôi tải dữ liệu
Chúng tôi tải dữ liệu bằng json. trọng tải
SQuAD JSON chứa nhiều lớp. Sau khi truy cập
http_code = "418"if http_code == "418":0, chúng tôi cần lặp lại qua từng
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"]
http_code = "418"if http_code == "418":1 câu hỏi, sau đó qua từng
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"]
http_code = "418"if http_code == "418":2, sau đó qua từng
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"]
http_code = "418"match http_code:6 [câu hỏi-câu trả lời] - điều này giống như
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"]
Và đây là nơi mọi thứ trở nên thú vị. Sử dụng logic
http_code = "418"if http_code == "418":4, chúng tôi nhận được một cái gì đó như thế này
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"]
Nó không đẹp, nhưng nó hoạt động. Bây giờ hãy viết lại điều này với một số logic
http_code = "418"if http_code == "418":5
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"]
Nó chắc chắn trông ít bận rộn hơn rất nhiều và là một sự thay thế khá thú vị cho phiên bản gốc của logic phân tích cú pháp
Đó là tất cả cho cái nhìn nhanh này về khớp mẫu cấu trúc mới được giới thiệu với Python 3. 10. Bản đầy đủ dự kiến vào đầu tháng 10 năm 2021
Cá nhân tôi nghĩ rằng cú pháp mới này trông thực sự tốt - mặc dù hiện tại tôi đánh giá 50/50 về nó. Khi có thêm người dùng bắt đầu viết mã bằng match-case, tôi tin rằng cộng đồng sẽ nhanh chóng thiết lập sự đồng thuận và các phương pháp hay nhất
Nhưng bây giờ, nó trông thật tuyệt - tôi rất phấn khích
Tôi hy vọng bạn thích bài viết. Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi hoặc đề xuất nào qua Twitter hoặc trong phần bình luận bên dưới. Nếu bạn quan tâm đến nhiều nội dung như thế này, tôi cũng đăng trên YouTube
Cảm ơn vì đã đọc
Nếu bạn muốn đọc về một số tính năng mới khác có trong Python 3. 10, hãy xem bài viết khác của tôi về một số bài viết hay nhất