Tính năng pattern matching của Python , được giới thiệu trong phiên bản 3.10, có một lỗ hổng bảo mật bất ngờ cho phép các nhà phát triển chiếm đoạt các câu lệnh match thông qua Abstract Base Classes ( ABCs ). Phát hiện này đã gây ra cuộc tranh luận sôi nổi trong cộng đồng Python về các quyết định thiết kế đằng sau cơ chế điều khiển luồng mới nhất của ngôn ngữ này.
Dòng thời gian lỗ hổng Pattern Matching của Python
- Python 3.10: Pattern matching được giới thiệu với các câu lệnh
match
/case
- Pattern matching sử dụng các kiểm tra
isinstance()
tuân theo các phương thức__subclasshook__
của ABC - Các ABC có thể định nghĩa logic tùy chỉnh để xác định lớp con
- Python 3.8: Protocols được giới thiệu như một giải pháp thay thế an toàn hơn cho structural typing
- Python 2.6: ABC với
__subclasshook__
lần đầu có sẵn (11 năm trước Protocols)
Lỗ hổng ẩn trong Pattern Matching
Vấn đề xuất phát từ cách pattern matching của Python tương tác với Abstract Base Classes và phương thức __subclasshook__
của chúng. Phương thức này cho phép ABCs định nghĩa logic tùy chỉnh để xác định liệu một lớp có được tính là lớp con hay không, ngay cả khi lớp đích không biết gì về ABC . Khi pattern matching kiểm tra isinstance(obj, class)
, nó tôn trọng các hook tùy chỉnh này, tạo ra cơ hội cho hành vi bất ngờ.
Một nhà phát triển có thể tạo một ABC khớp với các đối tượng dựa trên các điều kiện tùy ý - liệu chúng có các thuộc tính nhất định, tên của chúng có phải là palindrome hay không, hoặc thậm chí dựa trên đầu vào của người dùng. Điều này có nghĩa là một câu lệnh match có vẻ như kiểm tra các loại cụ thể thực sự có thể đang thực thi logic hoàn toàn khác phía sau.
Abstract Base Classes ( ABCs ): Các lớp Python định nghĩa giao diện mà các lớp khác nên triển khai, cho phép kiểm tra kiểu linh hoạt mà không cần kế thừa rõ ràng.
Mối quan ngại của cộng đồng về thiết kế ngôn ngữ
Cộng đồng Python đã bày tỏ những lo ngại đáng kể về hành vi này, đặc biệt là về khả năng đọc và bảo trì mã. Nhiều nhà phát triển lo lắng rằng tính năng này tạo ra hành động ma quái từ xa khiến việc gỡ lỗi trở nên gần như không thể khi các ABCs từ các phần khác nhau của codebase tương tác một cách bất ngờ.
Sự chỉ trích rộng hơn mở rộng đến chính việc triển khai pattern matching của Python . Không giống như các ngôn ngữ hàm xử lý pattern matching một cách tinh tế, phiên bản của Python đã bị chỉ trích vì hành vi không nhất quán với phạm vi biến và thiết kế dựa trên câu lệnh thay vì dựa trên biểu thức. Cộng đồng đã lưu ý rằng việc khớp với hằng số so với biến tạo ra kết quả khác biệt đáng kể, phá vỡ các kỳ vọng cơ bản về cách mã Python nên hoạt động.
Phạm vi biến: Cách các ngôn ngữ lập trình xác định nơi các biến có thể được truy cập và sửa đổi trong mã.
Các Vấn Đề Được Cộng Đồng Xác Định Với Pattern Matching Trong Python
- Phạm Vi Biến: Các biến bị rò rỉ ra ngoài khối match, phá vỡ kỳ vọng
- Cú Pháp Không Nhất Quán:
case 404
vàcase not_found
hoạt động hoàn toàn khác nhau - Statement vs Expression: Không giống các ngôn ngữ khác, pattern matching của Python dựa trên statement
- Tính Linh Hoạt Hạn Chế: Không thể sử dụng trực tiếp các biến mà không có giải pháp thay thế
- Thụt Lề Kép: Yêu cầu thêm các cấp độ thụt lề so với các cấu trúc khác
- Hành Vi Caching: Kết quả
__subclasshook__
được cache, hạn chế hành vi động
Các phương pháp thay thế và giải pháp tạm thời
Mặc dù có khả năng bị lạm dụng, một số thành viên cộng đồng nhìn thấy các ứng dụng hợp pháp cho chức năng này. Tính năng này về cơ bản cho phép structural typing - kiểm tra xem các đối tượng có triển khai các giao diện nhất định mà không cần kế thừa rõ ràng. Điều này đặc biệt có giá trị trước khi Python 3.8 giới thiệu Protocols , cung cấp một cách an toàn hơn để đạt được kết quả tương tự.
Tuy nhiên, sự đồng thuận vẫn mạnh mẽ chống lại việc sử dụng các kỹ thuật này trong mã sản xuất. Cộng đồng nhấn mạnh rằng mặc dù về mặt kỹ thuật là có thể, nhưng các phương pháp như vậy vi phạm nguyên tắc ít bất ngờ nhất và làm cho mã khó bảo trì và gỡ lỗi hơn đáng kể.
Cuộc tranh luận rộng hơn về Pattern Matching
Phát hiện này đã làm bùng phát lại các cuộc thảo luận về các lựa chọn thiết kế pattern matching của Python . Nhiều nhà phát triển cảm thấy tính năng này được triển khai kém so với chức năng tương tự trong các ngôn ngữ khác, trích dẫn các vấn đề như yêu cầu thụt lề kép, hỗ trợ biểu thức hạn chế và quy tắc cú pháp không nhất quán.
Tính năng pattern matching nhìn chung được thiết kế khá hợp lý, và mọi người sẽ mong đợi nó hoạt động theo những cách hợp lý. Trong khi subclasshook là ma thuật cực kỳ đen tối.
Phản ứng của cộng đồng làm nổi bật mối quan ngại ngày càng tăng về các bổ sung ngôn ngữ gần đây của Python . Một số nhà phát triển cho rằng các tính năng như pattern matching thêm độ phức tạp mà không cung cấp lợi ích tương xứng, đặc biệt khi các lựa chọn thay thế đơn giản hơn như dictionary hoặc câu lệnh if thường đủ.
Mặc dù kỹ thuật chiếm đoạt ABC này chứng minh tính linh hoạt của Python , nó cũng đóng vai trò như một câu chuyện cảnh báo về những hậu quả không mong muốn của việc kết hợp các tính năng ngôn ngữ mạnh mẽ. Khuyến nghị mạnh mẽ của cộng đồng Python vẫn rõ ràng: tránh những kỹ thuật này trong mã sản xuất để duy trì khả năng đọc và ngăn chặn những cơn ác mộng gỡ lỗi.
Tham khảo: CRIMES WITH PYTHON'S PATTERN MATCHING