Các biểu thức Python có được đánh giá từ trái sang phải không?

Đánh giá lười biếng là một khái niệm mà nhiều ngôn ngữ lập trình sử dụng để giúp tối ưu hóa hiệu suất trong thời gian chạy

Về bản chất, đánh giá lười biếng có nghĩa là một đối tượng được đánh giá khi nó cần chứ không phải khi nó được tạo. Trong Python, một tính năng thú vị của đánh giá lười biếng là cách các điều kiện dựa trên toán tử logic được đánh giá. Ví dụ: giả sử tôi đã tạo một biến boolean, được gọi là boolean_result, có giá trị là kết quả của toán tử or của hai hàm mà cả hai đều trả về boolean

Tạo một biến có giá trị là toán tử OR kết quả của hai hàm trả về các phép toán luận

Nếu tôi chạy cái này, đầu ra sẽ như sau

Đầu ra của việc chạy mã trước đó

Lý do cho điều này là để một điều kiện or đánh giá thành True, biểu thức ở hai bên của or phải trả về True. Do hàm condition_one() trả về giá trị False nên hàm condition_two() được thực thi để kiểm tra xem giá trị trả về là bao nhiêu. Kết quả là cả hai hàm đều được thực thi và biến boolean_value sẽ có giá trị là False

Bây giờ hãy xem điều gì sẽ xảy ra khi chúng ta thay đổi dòng 8 và làm cho hàm condition_one() trả về True. Vì vậy, nếu chúng ta thực hiện thay đổi

Lưu ý dòng 8 trong condition_one() đang trả về True

Sau khi chạy nó, đầu ra sẽ là

Chỉ đầu ra của condition_one() được in

Điều này khá thú vị vì chỉ có hàm condition_one() được thực thi chứ không phải hàm condition_two(). Điều này xảy ra do hàm condition_one() trả về True và đối với các biểu thức logic dựa trên or, giá trị được đánh giá kết quả sẽ luôn là True bất kể giá trị của or9 là gì. Python đủ thông minh để biết điều này, vì vậy nó không chạy condition_two() mà thay vào đó đánh giá một cách uể oải giá trị kết quả là True

Mặc dù cả hai chức năng này chỉ in ra một dòng, nhưng bạn có thể tưởng tượng hai chức năng này trong môi trường làm việc thực sẽ chứa đầy logic nghiệp vụ và có thể mất nhiều giây — nếu không muốn nói là vài phút — để mỗi chức năng thực thi

Do đó, một mẹo hay mà bạn có thể sử dụng để tối ưu hóa các biểu thức or/or3 là liệt kê hàm ít tốn kém hơn về mặt tính toán trước vì các biểu thức được đánh giá theo thứ tự từ trái sang phải. Nếu hàm đó trả về False cho một biểu thức sử dụng toán tử logic or3 hoặc True cho một biểu thức sử dụng toán tử logic or, thì không có lý do gì để đánh giá phần còn lại của biểu thức, giúp bạn tiết kiệm thời gian và sức mạnh tính toán

Mặc dù ví dụ trên chỉ là hai biểu thức được kết hợp bởior, nhưng một ví dụ rất phóng đại về điều này có thể là

Khi chạy, điều này sẽ mang lại kết quả như sau

Nếu chúng tôi thay đổi dòng 9 trong condition_one() để trả về True, chúng tôi sẽ nhận được

Đầu ra sẽ là

Khá mát mẻ, phải không?

Một ví dụ thực tế

Một cách sử dụng khác của việc triển khai đánh giá lười biếng các điều kiện Python này là sử dụng nó để kiểm tra lỗi. Ví dụ: giả sử tôi đã cung cấp cho bạn một lớp đại diện cho bảng tic-tac-toe (ma trận 3x3). Tôi đã điền trước vào một số ô để giúp thử nghiệm phương pháp mà chúng tôi sắp tạo dễ dàng hơn vì tôi sẽ không triển khai toàn bộ trò chơi

Giả sử tôi muốn bạn viết một phương thức có tên là True1 nhận hai đối số là số hàng và số cột và kiểm tra xem vị trí đó trên bàn cờ có trống để người chơi đặt nước đi tiếp theo không

Bạn có thể cho rằng một ô sẽ có ba giá trị. một chuỗi rỗng True2, một True3 hoặc một True4. Xin lưu ý rằng số hàng và số cột có thể vượt quá giới hạn — i. e. , kiểm tra ô ở hàng thứ bảy và cột thứ bảy. Trong những trường hợp như thế này, hãy giả sử rằng chúng ta phải trả lại False vì dù sao thì ô đó cũng sẽ không trống. Để cho ngắn gọn, hãy giả sử rằng phương thức trợ giúp này sẽ được sử dụng trong một phương thức khác để thực sự tạo ra một trò chơi tic-tac-toe đang hoạt động

Một cách bạn có thể giải quyết vấn đề này là viết một cái gì đó như

Bây giờ điều này hoạt động tốt và tất cả, nhưng vì các biểu thức trong điều kiện được đánh giá theo thứ tự chúng xuất hiện, chúng tôi có thể cấu trúc lại True6 thành

Chúng tôi vẫn nhận được kết quả tương tự bởi vì nếu tất cả bốn điều kiện đầu tiên đánh giá là True, chúng tôi biết rằng cả True8 và True9 đều phải nằm trong khoảng từ 0 đến 2. Điều này cho phép chúng tôi ngay lập tức sử dụng các giá trị này để lập chỉ mục bảng trò chơi mà không phải lo lắng về lỗi ngoài chỉ mục vì các điều kiện được đánh giá từ trái sang phải theo thứ tự

Bây giờ, nếu chúng ta đặt điều kiện cuối cùng trước, chẳng hạn như …

… nó sẽ hoạt động nếu các ô được chỉ định nằm trong giới hạn, nhưng nếu chúng không nằm trong giới hạn (chẳng hạn như khi chúng tôi kiểm tra ô ở hàng thứ bảy và cột thứ bảy), chúng tôi sẽ gặp lỗi ngoài giới hạn

Như tôi đã nói trước đây, điều này xảy ra bởi vì Python đánh giá các điều kiện từ trái sang phải theo thứ tự mà chúng xuất hiện (chúng ta sẽ giả sử rằng không có dấu ngoặc đơn)

Tôi đã sử dụng mẹo này để thực hiện kiểm tra ngoài giới hạn trước khi lập chỉ mục khi triển khai các giải pháp dựa trên ma trận tìm kiếm theo chiều rộng và chiều sâu trước trong các cuộc phỏng vấn kỹ thuật

Python không chỉ đánh giá một cách lười biếng các biểu thức dựa trên toán tử logic mà JavaScript cũng vậy. Tôi hy vọng tất cả các bạn tìm thấy bài viết này hữu ích

Các biểu thức được đánh giá như thế nào trong Python?

Bạn có thể sử dụng eval() tích hợp sẵn của Python để đánh giá động các biểu thức từ đầu vào dựa trên chuỗi hoặc dựa trên mã được biên dịch. Nếu bạn chuyển một chuỗi vào eval() , thì hàm sẽ phân tích chuỗi đó, biên dịch nó thành mã byte và đánh giá nó dưới dạng biểu thức Python.

Các biểu thức có được đánh giá từ trái sang phải không?

Trong C#, tất cả các biểu thức được đánh giá từ trái sang phải và chúng được kết hợp theo tính kết hợp. Thay đổi quy tắc cho toán tử gán làm phức tạp quy tắc và quy tắc phức tạp tạo ra sự nhầm lẫn. (Ví dụ, hãy xem hầu hết mọi bài viết tôi đã viết về lập trình Win32 có tiêu đề “Tại sao…?”)

Toán tử nào được đánh giá từ phải sang trái trong Python?

Tất cả toán tử ngoại trừ toán tử lũy thừa (**) được đánh giá từ trái sang phải và được liệt kê trong bảng theo thứ tự ưu tiên cao nhất đến thấp nhất. Nghĩa là, các toán tử được liệt kê đầu tiên trong bảng được đánh giá trước các toán tử được liệt kê sau.

Phần nào của biểu thức sẽ được đánh giá Python đầu tiên?

Python tuân theo các quy tắc ưu tiên giống như toán học đối với các toán tử toán học của nó. Dấu ngoặc đơn có mức ưu tiên cao nhất và có thể được sử dụng để buộc một biểu thức phải đánh giá theo thứ tự bạn muốn . Vì các biểu thức trong ngoặc đơn được đánh giá trước, nên 2 * (3-1) là 4 và (1+1)**(5-2) là 8.