Với and: nếu vế trái là False → không thèm xét vế phải (vì kết quả chắc chắn False)
Với or: nếu vế trái là True → không thèm xét vế phải (vì kết quả chắc chắn True)
# Vế phải sẽ gây lỗi chia cho 0, nhưng không bao giờ được chạyso_luong = 0print(so_luong > 0 and 100 / so_luong > 5) # False — an toàn
Nếu không có short-circuit, 100 / 0 sẽ gây ZeroDivisionError. Đây là kỹ thuật bảo vệ rất hay dùng:
ten = None# ❌ Lỗi# print(len(ten) > 0) # TypeError# ✅ An toàn nhờ short-circuitprint(ten is not None and len(ten) > 0) # False
4.4. and/or trả về GIÁ TRỊ, không phải chỉ True/False
Đây là điểm đặc biệt của Python mà nhiều người bất ngờ:
print(5 and 10) # 10 <- không phải Trueprint(0 and 10) # 0print(5 or 10) # 5print(0 or 10) # 10print("" or "mac dinh") # "mac dinh"print(None or 0 or "cuoi") # "cuoi"
Quy tắc:
A and B: nếu A là falsy → trả về A; ngược lại trả về B
A or B: nếu A là truthy → trả về A; ngược lại trả về B
Ứng dụng — giá trị mặc định:
ten_nhap = input("Nhap ten (Enter de bo qua): ")ten = ten_nhap or "Khach vang lai"print("Xin chao,", ten)
Nếu người dùng nhấn Enter luôn, ten_nhap là "" (falsy) → ten nhận "Khach vang lai".
Tương đương với ISNULL() / COALESCE() trong SQL
SELECT ISNULL(@Ten, N'Khach vang lai')
ten = ten_nhap or "Khach vang lai"
Khác biệt: SQL ISNULL chỉ xét NULL, còn Python or xét mọi giá trị falsy (bao gồm 0 và ""). Cẩn thận với trường hợp giá trị hợp lệ là số 0:
so_luong = 0kq = so_luong or 100 # kq = 100 — SAI Ý ĐỒ! 0 là giá trị hợp lệkq = so_luong if so_luong is not None else 100 # ĐÚNG
5. Toán tử đồng nhất và thành viên
5.1. is và is not — Identity Operators
== so sánh giá trị. is so sánh có phải cùng một đối tượng trong bộ nhớ không.
a = [1, 2, 3]b = [1, 2, 3]c = aprint(a == b) # True — cùng nội dungprint(a is b) # False — hai đối tượng khác nhau trong bộ nhớprint(a is c) # True — c chính là a
Chỉ dùng is với None, True, False
if x is None: # ✅ ĐÚNGif ten is "abc": # ❌ SAI — dùng == cho chuỗiif so is 1000: # ❌ SAI — dùng == cho số
Python có cơ chế caching cho số nhỏ (-5 đến 256) và một số chuỗi ngắn, khiến is đôi khi cho True một cách tình cờ:
a = 100b = 100print(a is b) # True — do cachinga = 1000b = 1000print(a is b) # False (thường vậy) — không được cache
Kết quả không đáng tin cậy và có thể khác nhau giữa các phiên bản Python. Nguyên tắc: is chỉ dành cho None, True, False.
5.2. in và not in — Membership Operators
# Với chuỗiprint("toan" in "Ke toan") # Trueprint("Toan" in "Ke toan") # False — phân biệt hoa thường# Với listdanh_sach = ["KH001", "KH002", "KH003"]print("KH002" in danh_sach) # Trueprint("KH999" not in danh_sach) # True# Với tupleprint("A" in ("A", "B", "C")) # True
Đây chính là IN của SQL:
WHERE MaKH IN ('KH001', 'KH002', 'KH003')
if ma_kh in ("KH001", "KH002", "KH003"): ...
6. Độ ưu tiên toán tử (Operator Precedence)
Bảng từ ưu tiên cao nhất xuống thấp nhất:
Mức
Toán tử
Tên
1
()
Ngoặc tròn
2
**
Lũy thừa
3
+x, -x, ~x
Dấu đơn nguyên
4
*, /, //, %
Nhân, chia
5
+, -
Cộng, trừ
6
<, <=, >, >=, !=, ==
So sánh
7
in, not in, is, is not
Thành viên, đồng nhất
8
not
Phủ định
9
and
Và
10
or
Hoặc
Ví dụ
print(2 + 3 * 4) # 14 (nhân trước: 2 + 12)print((2 + 3) * 4) # 20 (ngoặc trước)print(2 ** 3 ** 2) # 512 (** kết hợp PHẢI sang TRÁI: 2^(3^2) = 2^9)print((2 ** 3) ** 2) # 64print(-2 ** 2) # -4 (** trước dấu âm: -(2^2))print((-2) ** 2) # 4print(10 - 3 - 2) # 5 (trừ kết hợp TRÁI sang PHẢI: (10-3)-2)
print(True or False and False) # True (and trước or)print((True or False) and False) # False
Quy tắc thực dụng
Đừng cố nhớ hết bảng này. Hãy dùng dấu ngoặc.
# ❌ Đúng nhưng khó đọcif a > 5 and b < 10 or c == 0 and not d:# ✅ Rõ ràngif (a > 5 and b < 10) or (c == 0 and not d):
Dấu ngoặc không làm chậm chương trình, nhưng cứu bạn khỏi lỗi logic khó tìm.
7. Toán tử ba ngôi (Conditional Expression)
# Cú pháp: <giá trị nếu đúng> if <điều kiện> else <giá trị nếu sai>tuoi = 20loai = "Nguoi lon" if tuoi >= 18 else "Tre em"print(loai) # Nguoi lon
Tương đương với CASE WHEN trong SQL:
SELECT CASE WHEN Tuoi >= 18 THEN N'Nguoi lon' ELSE N'Tre em' END