Rẽ nhánh — điều kiện là một biểu thức đúng hoặc sai
Lần đầu tiên thứ tự trên xuống bị bẻ. Máy tính điều kiện ra đúng hoặc sai, đi đúng một nhánh, và bỏ qua hoàn toàn các nhánh còn lại — kể cả nhánh trông có vẻ cũng hợp.
TL;DR: Một điều kiện không phải câu mệnh lệnh, nó là một câu hỏi mà máy tính ra đúng hoặc sai. Gặp if rồi một chuỗi elif, máy hỏi từng câu theo thứ tự từ trên xuống, dừng ở câu đúng đầu tiên, chạy đúng khối đó rồi nhảy thẳng xuống dưới cả cụm. Tài liệu tham chiếu Python viết thẳng rằng khi một nhánh đã chạy thì "không phần nào khác của câu lệnh if được thi hành hoặc được tính". Hệ quả trực tiếp cho việc trace: nhánh không được chọn hoàn toàn vắng mặt khỏi bảng trace, không để lại một hàng nào.
Từ đầu khoá tới giờ, mọi chương trình bạn đọc đều chạy thẳng một mạch: dòng 1, dòng 2, dòng 3, hết. Nhưng chương trình thật phải biết chọn. Đơn hàng trên hai trăm nghìn thì phí ship khác, dưới thì khác. Điểm từ tám trở lên xếp giỏi, không thì không.
Bài này cho bạn cấu trúc để máy chọn đường — và quan trọng hơn, cho bạn cách nhìn ra nhánh nào không chạy, thứ mà đọc lướt gần như không bao giờ thấy.
1. Analogy — quầy soát vé có nhiều cửa
Bạn xếp hàng vào một sự kiện có ba cửa, treo biển theo thứ tự: cửa VIP, cửa vé thường, cửa vé mời. Nhân viên nhìn vé bạn, hỏi lần lượt từ trái sang. "VIP không?" Không. "Vé thường không?" Đúng rồi — thế là bạn đi cửa hai, và nhân viên không thèm hỏi tiếp câu thứ ba. Không phải anh ta hỏi rồi bỏ qua câu trả lời; anh ta dừng luôn ở đó.
| Quầy soát vé | Rẽ nhánh trong code |
|---|---|
| Mỗi biển là một câu hỏi có/không | Mỗi điều kiện cho ra đúng hoặc sai |
| Hỏi lần lượt từ trái sang phải | Máy tính từng điều kiện từ trên xuống |
| Dừng ở câu trả lời "đúng" đầu tiên | Dừng ở nhánh đúng đầu tiên |
| Các biển sau không được hỏi tới | Các nhánh sau không được tính tới |
| Không khớp biển nào thì đi cửa cuối | Không nhánh nào đúng thì chạy else |
if và elif là câu hỏi. else là cửa cuối — nó không hỏi gì cả, nó chỉ nhận những ai không lọt qua cửa nào phía trên.
2. Điều kiện là một câu hỏi, không phải một mệnh lệnh
Dấu = một gạch là phép gán: nó chép giá trị vào ô nhớ bên trái. Nó không hỏi gì hết. Bài này dùng dấu == hai gạch, và đó là thứ hoàn toàn khác: một câu hỏi so sánh hai bên có bằng nhau không.
Trước khi xem if, hãy nhìn riêng phần điều kiện. Với diem đang bằng 7:
diem = 7
# Moi dong duoi day la mot CAU HOI, khong phai mot menh lenh
print(diem >= 8)
print(diem >= 5)
print(diem == 7)
Output thật:
False
True
True
False và True là hai giá trị duy nhất một câu hỏi có thể cho ra. Chúng là một kiểu riêng, y như số và chuỗi là hai kiểu riêng ở module trước. Cả if lẫn elif đều không làm gì khác ngoài việc nhìn vào một trong hai giá trị này rồi quyết định có chạy khối bên dưới hay không.
Các câu hỏi so sánh bạn dùng suốt module: == (bằng nhau), != (khác nhau), > và < (lớn hơn, nhỏ hơn), >= và <= (lớn hơn hoặc bằng, nhỏ hơn hoặc bằng).
diem = 8 là gán: nó đặt diem thành 8, xoá mất giá trị cũ. diem == 8 là hỏi: nó không đổi gì cả, chỉ cho ra True hoặc False. Viết nhầm một gạch vào chỗ cần hỏi là lỗi kinh điển của người mới ở mọi ngôn ngữ.
3. Máy chạy nhánh nào khi hai điều kiện cùng đúng?
Đoạn code xếp loại theo điểm:
diem = 7
if diem >= 8:
xep_loai = "Gioi"
elif diem >= 5:
xep_loai = "Kha"
else:
xep_loai = "Yeu"
print(xep_loai)
Máy đi thế này, từng nhịp một:

Hai ô mờ trên hình là thứ đáng để ý nhất. Với diem bằng 7, máy chưa từng đọc tới dòng xep_loai = "Gioi" lẫn dòng xep_loai = "Yeu". Chúng không chạy rồi bị ghi đè; chúng đứng ngoài đường đi.
Tài liệu tham chiếu Python nói đúng chuyện này: câu lệnh if "chọn đúng một trong các khối bằng cách tính các biểu thức lần lượt cho tới khi gặp một biểu thức đúng; rồi khối đó được thi hành (và không phần nào khác của câu lệnh if được thi hành hoặc được tính)".
Từ elif là viết tắt của "else if", đúng như tài liệu ghi. Nghĩa là nó vừa đóng vai "nếu các câu trên đều sai", vừa đặt thêm một câu hỏi mới.
4. Thử đoán trước khi đọc tiếp
Vẫn đoạn code ở mục 3, nhưng đổi dòng đầu thành diem = 9.
Chương trình in ra chuỗi nào? Và trong ba dòng gán xep_loai, có bao nhiêu dòng thật sự chạy? Viết cả hai câu trả lời ra giấy rồi mới bấm nút.
Output thật:
Gioi
Đúng một dòng gán chạy, là dòng xep_loai = "Gioi". Câu hỏi đầu tiên diem >= 8 cho ra True, máy chạy khối ngay dưới nó rồi nhảy thẳng xuống print.
Chỗ đáng để ý: diem >= 5 cũng đúng với diem bằng 9. Nhưng máy không bao giờ hỏi câu đó. elif chỉ được tính khi mọi câu phía trên đã sai — mà câu phía trên vừa đúng.
5. Tới lượt bạn — điền cột "câu hỏi ra gì"
Bảng trace: cột là biến, hàng là dòng lệnh vừa chạy xong, mỗi hàng ghi lại giá trị hiện tại của mọi biến. Bài này giữ nguyên cách đọc đó và thêm đúng một cột mới — kết quả của câu hỏi ở dòng đó.
Đoạn code tính phí ship:
tong_don = 250000
if tong_don >= 500000:
phi = 0
elif tong_don >= 200000:
phi = 15000
else:
phi = 30000
print(phi)
Bảng trace dưới đây điền sẵn hai hàng đầu. Ba hàng còn lại để trống — cột "Câu hỏi ra gì" ghi True, False, hoặc dấu gạch khi dòng đó không phải câu hỏi; cột phi ghi giá trị sau khi dòng đó chạy xong.
| Dòng | Lệnh | Câu hỏi ra gì | tong_don | phi |
|---|---|---|---|---|
| 1 | tong_don = 250000 | – | 250000 | – |
| 3 | if tong_don >= 500000: | False | 250000 | – |
| 5 | elif tong_don >= 200000: | … | … | … |
| 6 | phi = 15000 | … | … | … |
| 10 | print(phi) | … | … | … |
Chép bảng ra giấy và điền nốt. Rồi trả lời thêm một câu không có trong bảng: dòng nào của đoạn code này không hề chạy? Xong hết mới bấm nút bên dưới.
| Dòng | Lệnh | Câu hỏi ra gì | tong_don | phi |
|---|---|---|---|---|
| 1 | tong_don = 250000 | – | 250000 | – |
| 3 | if tong_don >= 500000: | False | 250000 | – |
| 5 | elif tong_don >= 200000: | True | 250000 | – |
| 6 | phi = 15000 | – | 250000 | 15000 |
| 10 | print(phi) | – | 250000 | 15000 |
Hai dòng không hề chạy: dòng 4 (phi = 0) và dòng 8 (phi = 30000). Chúng vắng mặt khỏi bảng trace, và đó chính là điều bảng trace đang chứng minh — một hàng chỉ xuất hiện khi dòng đó thật sự chạy.
Để ý hàng 5: câu hỏi cho ra True nhưng cột phi vẫn còn dấu gạch. Dòng elif chỉ hỏi, nó không gán gì cả. Giá trị của phi chỉ xuất hiện ở hàng 6.
6. Bẫy thường gặp khi viết nhiều nhánh
❌ Nhầm 1 — tưởng mọi nhánh đều được kiểm tra. Người mới hay nghĩ máy chạy hết cả cụm rồi mới chọn kết quả cuối. Nếu đúng vậy thì với diem bằng 9, xep_loai sẽ thành "Kha" (nhánh sau ghi đè nhánh trước), chứ không phải "Gioi".
✅ Máy dừng ở nhánh đúng đầu tiên rồi nhảy hẳn ra ngoài cụm. Muốn kiểm tra suy nghĩ của mình, hỏi: "nếu hai điều kiện cùng đúng, cái nào thắng?" — luôn là cái ở trên.
❌ Nhầm 2 — xếp thứ tự nhánh sai mà không báo lỗi. Đảo hai nhánh của đoạn xếp loại:
if diem >= 5:
xep_loai = "Kha"
elif diem >= 8:
xep_loai = "Gioi"
Đoạn này chạy trơn tru, không lỗi cú pháp, không lỗi lúc chạy. Nhưng diem bằng 9 giờ ra "Kha" — vì diem >= 5 đúng trước, và nhánh "Gioi" vĩnh viễn không bao giờ chạy được với bất kỳ giá trị nào.
✅ Với các nhánh so sánh theo ngưỡng, xếp từ hẹp nhất tới rộng nhất. Nhánh nào bao trùm nhánh khác phải đứng sau.
7. 📚 Đào sâu — tài liệu tham chiếu Python
8. Compound statements — Python documentation — mục "The if statement" là nguồn của câu trích ở mục 3. Đây là tài liệu tham chiếu, viết cho người cần độ chính xác tuyệt đối, nên câu chữ khô hơn hẳn tài liệu hướng dẫn — nhưng đúng chỗ này thì cái khô đó lại quý: nó nói thẳng "no other part of the if statement is executed or evaluated", tức là không tính, không chỉ là không chạy.
4. More Control Flow Tools — Python documentation — bản hướng dẫn dễ đọc hơn cho cùng chủ đề, kèm câu giải thích elif là viết tắt của "else if".
8. Liên hệ các bài khác
- Bài 1 module trước — Chương trình là dãy lệnh — máy chạy đúng thứ tự từng dòng. Rẽ nhánh là lần đầu tiên thứ tự đó bị bẻ, nhưng bẻ theo luật, không phải nhảy cóc tuỳ hứng.
- Bài 4 module trước — Bảng trace — công cụ bạn vừa dùng lại ở mục 5, chỉ thêm một cột.
- Bài 2 — Điều kiện phức hợp — khi một câu hỏi chưa đủ và bạn cần ghép nhiều câu bằng
and,or,not. Ba cái bẫy ở đó đều bắt nguồn từ chuyện điều kiện là biểu thức, không phải câu tiếng Việt. - Bài 3 — Vòng lặp while — cũng dùng một điều kiện đúng/sai y hệt bài này, nhưng hỏi đi hỏi lại thay vì hỏi một lần.
9. Tóm tắt
- Nghi thứ tự nhánh sai? Lấy một giá trị nằm trong vùng chồng lấn của hai ngưỡng rồi hỏi nhánh nào thắng; ra khác ý bạn là thứ tự đang sai.
- Có nhánh nào trong code bạn chưa bao giờ thấy chạy? Kiểm xem nhánh phía trên nó có bao trùm nó không — nhánh chết không báo lỗi bao giờ.
- Trace mà bảng thiếu hàng cho một dòng gán? Đúng rồi, không phải bạn quên: dòng ở nhánh không được chọn thì không có hàng nào cả.
- Trace tới dòng
elifmà không biết điền gì vào cột biến? Điền dấu gạch:elifchỉ hỏi, việc gán nằm ở dòng bên trong khối. - Định viết
if x = 5? Python sẽ dừng ngay tại đó — đây là một trong số ít lỗi loại này mà bạn được báo thẳng.
10. Tự kiểm tra
- Q1Vì sao nói các nhánh không được chọn là "không hề chạy", chứ không phải "chạy rồi bị bỏ kết quả"? Hai cách nói này khác nhau ở đâu?
- Q2Với
diem = 9, cả hai điều kiệndiem >= 8vàdiem >= 5đều đúng. Vì sao chỉ một nhánh chạy, và nhánh nào? - Q3Nếu đảo hai nhánh thành
if diem >= 5trước rồielif diem >= 8, chương trình có báo lỗi không? Chuyện gì xảy ra? - Q4Ở bảng trace mục 5, hàng của dòng
elif tong_don >= 200000:có cột câu hỏi bằngTruenhưng cộtphivẫn để trống. Vì sao? - Q5Dấu
=và dấu==khác nhau thế nào? Điều gì xảy ra nếu bạn định hỏi mà lại viết một gạch? - Q6Khi xếp nhiều nhánh so sánh theo ngưỡng, vì sao phải đặt ngưỡng hẹp nhất lên trên? Cho một cách tự kiểm tra nhanh trước khi chạy code.
Bài tiếp theo: Điều kiện phức hợp — and, or, not
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên