2.11. Điều kiện (Conditional)¶
Một điều kiện chạy một khối mã chỉ khi một kiểm tra nào đó được đánh giá là đúng. Từ khóa là if, tùy chọn theo sau bởi một hoặc nhiều nhánh elif ("else if") và một else cuối cùng.
n = 42
if n > 0:
print("positive")
elif n < 0:
print("negative")
else:
print("zero")
Phần thân của mỗi nhánh là tất cả những gì được thụt vào bên dưới nó (quy ước bốn khoảng trắng). Python duyệt qua các nhánh theo thứ tự, chạy nhánh đầu tiên có kiểm tra đúng, và bỏ qua phần còn lại. Khối else chỉ chạy nếu mọi kiểm tra trước đó đều sai; nó luôn là tùy chọn.
Chỉ một nhánh được chạy. Các kiểm tra được đánh giá từ trên xuống cho đến khi một kiểm tra thành công; phần còn lại bị bỏ qua.¶
2.11.1. Tính đúng/sai (Truthiness)¶
Một kiểm tra trong if không nhất thiết phải trả về True hay False -- bất kỳ giá trị nào cũng được tính là truthy (đúng) hoặc falsy (sai). Các giá trị falsy là:
Mọi thứ khác đều là truthy. Điều này cho phép bạn viết các kiểm tra gọn hơn:
if name: # false on empty string
print("hello", name)
if items: # false on empty list, dict, etc.
process(items)
Hãy lưu ý rằng tính truthy thay đổi ý nghĩa. if value: không giống như if value is not None: -- cái đầu tiên cũng là sai khi value là 0 hoặc "". Khi bạn thực sự muốn nói "đây chính xác là None", hãy dùng is None / is not None một cách rõ ràng.
2.11.2. Biểu thức ba ngôi (Ternary)¶
Một điều kiện có thể xuất hiện bên trong một biểu thức:
label = "even" if n % 2 == 0 else "odd"
Đọc là "label là "even" nếu n % 2 == 0 nếu không thì "odd"." Tiện cho các dòng đơn; với bất cứ thứ gì dài hơn một dòng, câu lệnh if đầy đủ dễ đọc hơn.
2.11.3. Lồng nhau và trả về sớm¶
Các điều kiện có thể lồng tùy ý sâu, nhưng mỗi lớp thụt vào thêm làm cho hàm khó đọc hơn. Ví dụ dưới đây kiểm tra bốn điều kiện trước khi thực hiện công việc thực sự và để dòng hữu ích bị chôn vùi dưới bốn lớp thụt:
def process(item):
if item is not None:
if item.is_valid():
if item.size() > 0:
if item.owner == "me":
return do_the_work(item)
return None
Hai mẫu giúp làm phẳng loại mã này.
2.11.3.1. Trả về sớm cho các bộ bảo vệ¶
Xử lý từng trường hợp "thoát ra" trước, mỗi trường hợp với return riêng, để logic chính ở lại thụt vào ngoài cùng. Mỗi bộ bảo vệ được đọc như "đây không phải trường hợp chúng ta xử lý; thoát ra":
def process(item):
if item is None:
return None
if not item.is_valid():
return None
if item.size() == 0:
return None
if item.owner != "me":
return None
return do_the_work(item)
"Con đường chính" bây giờ là một dòng ở cuối hàm, không bị chôn vùi trong bốn lớp. Phong cách này đôi khi được gọi là mẫu mệnh đề bảo vệ (guard clause).
2.11.3.2. Kết hợp kiểm tra với and / or¶
Khi nhiều điều kiện đều phải thỏa mãn cùng một nhánh, hãy kết hợp chúng bằng and thay vì lồng nhau. Các điều kiện mà mỗi điều kiện độc lập kích hoạt nhánh được kết hợp với or:
# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
save()
# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
whitespace_count += 1
Cả hai dạng đều short-circuit, vì vậy một kiểm tra tốn kém ở vế phải chỉ chạy khi các kiểm tra rẻ hơn ở vế trái chưa giải quyết xong câu hỏi.