Như đã trình bày trước đây, đối với Python và Raku [Perl 6], trong
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]1 khi
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]2 sai, biểu thức tiếp theo
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]3 sẽ không được đánh giá. Rốt cuộc,
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]4 sẽ không đánh giá
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]5 khi
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]2 sai. Vì vậy, luôn háo hức đánh giá
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]3 là sự thay đổi đột phá về mặt tinh thần
Có những ngôn ngữ khác với các toán tử chuỗi
Trong Julia thứ tự đánh giá là không xác định [bleh], e. g.
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]1 trong Julia trước tiên sẽ đánh giá [háo hức]
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]9, sau đó [háo hức]
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]0 và cuối cùng là [lười biếng]
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]3. Điều này phá vỡ sự đảm bảo thứ tự từ trái sang phải của Rust, nhưng sự lười biếng có điều kiện vẫn còn đó
Toán tử so sánh của Scheme và Clojure có thể chấp nhận nhiều giá trị e. g.
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]21 trong đó tất cả
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]0,
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]9 và
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]3 được đánh giá một cách háo hức. Nhưng
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]25 không phải là toán tử đặc biệt trong các ngôn ngữ Lispy này và do đó không thực sự áp dụng được cho Rust
Lấy cảm hứng từ PEP 335 và dựa trên giao thức ngắt mạch được mô tả trong PEP 532, PEP này đề xuất thay đổi định nghĩa về so sánh theo chuỗi, trong đó chuỗi so sánh sẽ được cập nhật để sử dụng toán tử ngắt mạch kết hợp bên trái [
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]0] thay vì
Mặc dù có một số phức tạp thực tế phát sinh từ việc xử lý các mảng có giá trị đơn hiện tại trong NumPy, nhưng thay đổi này phải đủ để cho phép các hoạt động so sánh theo chuỗi phần tử cho ma trận, trong đó kết quả là ma trận gồm các giá trị boolean, thay vì tăng
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]2 hoặc trả về một cách tự nhiên
Mối quan hệ với các PEP khác
PEP này đã được trích xuất từ các lần lặp lại trước đó của PEP 532, như một trường hợp sử dụng tiếp theo cho giao thức ngắt mạch, chứ không phải là một phần thiết yếu trong phần giới thiệu của nó
Đề xuất cụ thể trong PEP này để xử lý trường hợp sử dụng so sánh theo từng yếu tố bằng cách thay đổi định nghĩa ngữ nghĩa của chuỗi so sánh được rút ra trực tiếp từ việc Guido từ chối PEP 335
Sự chỉ rõ
Một so sánh chuỗi như
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]4 được viết là
LEFT_BOUND LEFT_OP EXPR RIGHT_OP RIGHT_BOUND
hiện tại gần tương đương về mặt ngữ nghĩa với
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]
Sử dụng các khái niệm ngắt mạch được giới thiệu trong PEP 532, PEP này đề xuất thay đổi chuỗi so sánh để kiểm tra rõ ràng xem phép so sánh bên trái có trả về một bộ ngắt mạch hay không và nếu vậy, hãy sử dụng
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]0 thay vì
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]1 để triển khai chuỗi so sánh
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr if hasattr[type[_lhs_result], "__else__"]: _expr_result = _lhs_result else [_expr RIGHT_OP RIGHT_BOUND] else: _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]
Điều này cho phép các loại như mảng NumPy kiểm soát hành vi so sánh theo chuỗi bằng cách trả về các bộ ngắt mạch được xác định phù hợp từ các hoạt động so sánh
Việc mở rộng logic này thành một số lượng tùy ý các hoạt động so sánh theo chuỗi sẽ giống như việc mở rộng hiện tại cho
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]1
cơ sở lý luận
Khi cuối cùng từ chối PEP 335, Guido van Rossum lưu ý [1]
Những người NumPy đã đưa ra một vấn đề hơi riêng biệt. đối với họ, trường hợp sử dụng phổ biến nhất là so sánh theo chuỗi [e. g. A < B < C]
Để hiểu quan sát này, trước tiên chúng ta cần xem cách so sánh hoạt động với mảng NumPy
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]1
Ở đây, chúng ta thấy rằng các phép so sánh mảng NumPy theo mặc định là theo từng phần tử, so sánh từng phần tử trong mảng bên trái với phần tử tương ứng trong mảng bên phải và tạo ra một ma trận kết quả boolean
Nếu một trong hai bên của phép so sánh là một giá trị vô hướng, thì nó sẽ được phát trên toàn mảng và được so sánh với từng phần tử riêng lẻ
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]2
Tuy nhiên, thành ngữ phát sóng này bị hỏng nếu chúng ta cố gắng sử dụng các phép so sánh theo chuỗi
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]3
Vấn đề là trong nội bộ, Python ngầm mở rộng so sánh chuỗi này thành dạng
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]4
Và NumPy chỉ cho phép ép buộc ngầm đối với giá trị boolean cho các mảng một phần tử trong đó
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]8 và
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]9 có thể được đảm bảo có cùng kết quả
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]7
Đề xuất trong PEP này sẽ cho phép thay đổi tình huống này bằng cách cập nhật định nghĩa về các hoạt động so sánh theo từng phần tử trong NumPy để trả về một lớp con chuyên dụng thực hiện giao thức ngắt mạch mới và cũng thay đổi cách diễn giải của mảng kết quả trong ngữ cảnh boolean để luôn trả về
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]9
Với thay đổi này, ví dụ so sánh chuỗi ở trên sẽ có thể trả về
_expr = EXPR _lhs_result = LEFT_BOUND LEFT_OP _expr _expr_result = _lhs_result and [_expr RIGHT_OP RIGHT_BOUND]0
Thực hiện
Việc triển khai thực tế đã bị hoãn lại do sự quan tâm về nguyên tắc đang chờ xử lý đối với ý tưởng thực hiện các thay đổi được đề xuất trong PEP 532
…TBD…
Người giới thiệu
[1]Thông báo từ chối PEP 335 [https. //email. con trăn. org/pipermail/python-dev/2012-tháng 3/117510. html]bản quyền
Tài liệu này đã được đặt trong phạm vi công cộng theo các điều khoản của CC0 1. 0 giấy phép. https. //Commons sáng tạo. tổ chức/miền công cộng/không/1. 0/