Ba từ thay cho ký hiệu
Toán tử (operator) logic của Python là các từ tiếng Anh and, or và not. Những ngôn ngữ khác viết chúng là &&, || và !. Trong Python, && và || gây SyntaxError, còn ! chỉ xuất hiện trong != ("khác").
Với True và False, quy tắc đúng như bạn nghĩ:
a | b | a and b | a or b | not a |
|---|---|---|---|---|
True | True | True | True | False |
True | False | False | True | False |
False | True | False | True | True |
False | False | False | False | True |
and cần cả hai vế đều đúng. or chỉ cần ít nhất một vế. not nhận một giá trị và đảo ngược nó.
Trong code thực tế, hai vế thường là phép so sánh, và kết quả được đưa vào if hoặc while:
Đầu ra:
eligible
standard ticket
Chừng đó là đủ cho phần lớn điều kiện. Phần còn lại của trang này nói về những gì các toán tử làm với giá trị không phải True hay False, và những quy tắc quyết định vế nào của biểu thức được chạy.
Giá trị truthy và falsy
and, or và not nhận mọi giá trị, không chỉ boolean. Python quyết định một giá trị có được coi là đúng hay không dựa vào tính truthy của nó. Những giá trị sau là falsy:
FalsevàNone- số không của mọi kiểu số:
0,0.0 - chuỗi và tập hợp rỗng:
"",[],(),{},set(),range(0)
Mọi thứ còn lại đều là truthy, kể cả "0", "False", [0] và -1. Bạn có thể xem Python phân loại một giá trị thế nào bằng bool():
Đầu ra:
0 False
1 True
-1 True
'' False
'0' True
[] False
[0] True
None False
0.0 False
Chuỗi "0" là truthy vì đó là một chuỗi không rỗng. Điều này hay làm khó những ai đọc số từ đầu vào rồi kiểm tra trước khi chuyển kiểu. Trang về số và boolean giải thích mối quan hệ giữa bool và int.
and và or trả về một toán hạng
Đây là chỗ Python khác với phần lớn ngôn ngữ. and và or không tạo ra một True hay False mới. Chúng trả về một trong hai giá trị bạn đưa vào:
x or ytrả vềxnếuxlà truthy, ngược lại trả vềy.x and ytrả vềxnếuxlà falsy, ngược lại trả vềy.
Khi cả hai toán hạng đều là boolean, "trả về một toán hạng" và "trả về một boolean" là một, vì thế sự khác biệt này không ai để ý cho đến khi bạn trộn thêm kiểu dữ liệu khác.
not là ngoại lệ: nó luôn trả về True hoặc False.
Nếu bạn cần một boolean thật sự từ biểu thức and/or, chẳng hạn để lưu lại hoặc trả về từ một hàm hứa hẹn trả về bool, hãy bọc nó trong bool():
Đánh giá short-circuit
Python đánh giá and và or từ trái sang phải và dừng ngay khi đã biết kết quả:
anddừng ở giá trị falsy đầu tiên, vì không gì phía sau có thể làm cả biểu thức thành đúng.ordừng ở giá trị truthy đầu tiên, vì không gì phía sau có thể làm cả biểu thức thành sai.
Vế bị bỏ qua hoàn toàn không được chạy. Bạn có thể thấy điều này qua các hàm in ra khi được gọi:
Đầu ra:
and:
checking A
False
or:
checking A
True
B không bao giờ được kiểm tra trong cả hai trường hợp. Chính short-circuit giúp các điều kiện bảo vệ trở nên an toàn. Nửa sau của mỗi điều kiện dưới đây sẽ gây lỗi nếu chạy riêng, nhưng nó chỉ chạy sau khi nửa đầu đã loại trừ trường hợp xấu:
Đặt phép kiểm tra rẻ hoặc mang tính bảo vệ lên trước. Nếu đảo thứ tự thành user.startswith("admin") and user is not None, bạn sẽ gặp AttributeError khi user là None.
Những mẫu code dựa trên or và and
Vì or trả về toán hạng truthy đầu tiên, nó cho bạn một cách đặt giá trị mặc định trên một dòng:
Đầu ra:
Hello, Ada!
Hello, guest!
Hello, guest!
Điểm cần lưu ý là or thay thế mọi giá trị falsy, không chỉ None. Nếu 0, "" hay [] là đầu vào hợp lệ, or sẽ vứt nó đi:
Dùng x if x is not None else default khi số không hoặc giá trị rỗng là hợp lệ. Trang if/else giải thích biểu thức điều kiện đó.
and cũng có một mẫu tương ứng: "chỉ dùng giá trị này nếu giá trị đầu đã có". Mẫu này ít gặp hơn và thường viết thành if sẽ rõ hơn, nên hãy dùng tiết chế:
Thứ tự ưu tiên: not, rồi and, rồi or
Khi một biểu thức trộn cả ba, Python áp dụng not trước, rồi and, rồi or. Các phép so sánh như ==, < và in được áp dụng trước tất cả.
a or b and c và (a or b) and c cho kết quả khác nhau với cùng giá trị, vì vậy điều kiện hỗn hợp nên có dấu ngoặc kể cả khi thứ tự mặc định tình cờ đúng. Dấu ngoặc chẳng tốn gì và giúp người đọc sau không phải băn khoăn.
and/or so với &/|
& và | trông giống and và or, đôi khi còn cho cùng kết quả, nhưng chúng là những toán tử khác nhau.
and/orkiểm tra tính truthy, có short-circuit và trả về một trong các toán hạng.&/|là toán tử bitwise. Với số nguyên, chúng kết hợp các bit của hai số. Với set, chúng là phép giao và phép hợp. VớiTruevàFalse, chúng trả về boolean. Chúng không bao giờ short-circuit: cả hai vế luôn được đánh giá.
Toán tử bitwise còn có độ ưu tiên cao hơn phép so sánh, khiến một điều kiện viết bằng & biến thành thứ hoàn toàn khác:
1 & y là 1 & 5, tức là 1, nên dòng ở giữa trở thành chuỗi so sánh 5 > 1 > 1, mà 1 > 1 là sai. Trong code Python thông thường, hãy dùng and, or và not cho điều kiện.
Chỗ duy nhất mà &, | và ~ là đúng cho điều kiện là NumPy và pandas. Một mảng chứa nhiều giá trị nên không có một giá trị đúng sai duy nhất, và and sẽ báo ValueError: The truth value of an array ... is ambiguous. Các thư viện này nạp chồng & và | để làm việc theo từng phần tử, đó là lý do bộ lọc pandas trông như df[(df.age > 18) & (df.country == "CA")], với dấu ngoặc quanh mỗi phép so sánh vì lý do độ ưu tiên đã nói ở trên.
any() và all(): and và or trên cả một list
Để kết hợp cả một dãy điều kiện, hãy dùng các hàm có sẵn all() (một phép and qua mọi phần tử) và any() (một phép or qua mọi phần tử). Cả hai đều short-circuit theo cùng cách:
Khác với and và or, any() và all() luôn trả về boolean.
Những lỗi thường gặp
So sánh một biến với nhiều giá trị bằng or. Điều kiện này luôn đúng:
Python đọc điều kiện đầu tiên thành (color == "red") or "blue". Phép so sánh là False, nên or trả về "blue", một chuỗi không rỗng, tức là truthy. Hãy lặp lại phép so sánh ở cả hai vế, hoặc tốt hơn, kiểm tra bằng in.
Viết && hoặc ||. Cả hai đều gây SyntaxError. Dùng and và or.
Chờ đợi boolean từ and/or. x = a or b lưu chính a hoặc b. Thường đó là điều bạn muốn, nhưng nếu một hàm phải trả về True hoặc False, hãy chuyển đổi bằng bool().
Dựa vào thứ tự ưu tiên trong điều kiện hỗn hợp. a or b and c hợp lệ và có nghĩa rõ ràng, nhưng hãy thêm dấu ngoặc để không ai phải nhớ quy tắc.
Câu hỏi thường gặp
Toán tử and làm gì trong Python?
a and b chỉ đúng khi cả hai vế đều đúng. Python đánh giá a trước; nếu a là falsy thì trả về a mà không xét b, ngược lại thì trả về b. Với boolean thông thường, kết quả đúng như bạn quen: True and False là False.
Vì sao 0 or 5 trả về 5 chứ không phải True?
or và and trả về một trong các toán hạng của chúng, không tạo ra boolean mới. x or y trả về x nếu x là truthy, ngược lại trả về y. 0 là falsy nên 0 or 5 trả về 5. Hãy bọc biểu thức trong bool() nếu bạn cần đúng True hoặc False.
and và & trong Python khác nhau thế nào?
and là toán tử logic: nó kiểm tra tính truthy và có short-circuit. & là toán tử bitwise: với số nguyên nó kết hợp các bit (6 & 3 là 2), với set nó lấy phần giao, và nó luôn đánh giá cả hai vế. Dùng and trong điều kiện if. Ngoại lệ là NumPy và pandas, nơi & là phép and theo từng phần tử.
Trong Python, and hay or được thực hiện trước?
not có độ ưu tiên cao nhất, rồi đến and, rồi or. Vì vậy a or b and c nghĩa là a or (b and c), còn not a or b nghĩa là (not a) or b. Các phép so sánh như == và < có độ ưu tiên cao hơn cả ba.
Có dùng được && và || trong Python không?
Không. && và || gây SyntaxError trong Python. Toán tử logic là các từ and, or và not. Một dấu & hoặc | đơn lẻ thì hợp lệ nhưng mang nghĩa khác (and/or bitwise).