Trong bài này
Lan ghi điểm kiểm tra của lớp. Với 8 điểm, Lan muốn in mức “Tốt”; với 6 điểm, Lan muốn in “Đạt”. Chương trình cần chọn đúng một mức theo số điểm nhận được.
Dùng elif để chọn một trong nhiều nhánh
Ở Bài 3, bạn dùng if và else để chọn giữa hai trường hợp. Khi có ba trường hợp, bạn có thể thêm elif vào giữa:
diem = 8
if diem >= 8:
print("Tot")
elif diem >= 5:
print("Dat")
else:
print("Can on tap")Tot
Python kiểm tra diem >= 8 trước. Điều kiện đúng nên chương trình in Tot và bỏ qua các nhánh còn lại. Từ khóa elif viết tắt của “else if”: nó đưa ra điều kiện bổ sung (additional condition) khi các điều kiện trước chưa đúng.
Thử điểm khác bằng cách đọc dữ liệu:
6
diem = int(input())
if diem >= 8:
print("Tot")
elif diem >= 5:
print("Dat")
else:
print("Can on tap")Dat
Với 6, điều kiện đầu sai và điều kiện ở elif đúng. Python thực hiện khối lệnh dưới elif, rồi đi tiếp sau toàn bộ cấu trúc. else không có điều kiện; nó nhận các trường hợp không khớp nhánh trước.
Kiểm tra đầuĐiểm từ 8: chọn TotNếu chưa chọnĐiểm từ 5: chọn DatNếu chưa chọnChọn Can on tap
Bạn có thể viết nhiều elif, hoặc bỏ else nếu không cần xử lý các trường hợp còn lại. Mỗi dòng if và elif cần điều kiện cùng dấu hai chấm. Dòng else chỉ có dấu hai chấm. Mỗi khối lệnh phải thụt vào; các từ khóa cùng cấp thẳng hàng.
mau = "vang"
if mau == "do":
print("Dung")
elif mau == "vang":
print("Cham")
elif mau == "xanh":
print("Di")
else:
print("Khong co tin hieu")
print("Da kiem tra")Cham Da kiem tra
Lệnh cuối không thụt vào nên nằm sau cấu trúc, không thuộc riêng nhánh else. Nếu quên dấu hai chấm sau điều kiện, chương trình báo lỗi cú pháp:
diem = 6
if diem >= 8:
print("Tot")
elif diem >= 5
print("Dat")Lỗi khi chạy, ở dòng 4
SyntaxError: expected ':'
Hãy thêm : vào cuối dòng elif. elif không thể đứng riêng: nó phải nối tiếp if hoặc một elif cùng cấp, trước else nếu có.
Khối của một nhánh có thể gồm nhiều lệnh. Tất cả các lệnh đó cần cùng mức thụt lề để cùng thuộc nhánh:
so_sach = 3
if so_sach > 0:
print("Co sach")
print("Hay xep len ke")
else:
print("Chua co sach")Co sach Hay xep len ke
Khi so_sach lớn hơn 0, cả hai lời nhắc trong khối đầu được in. Nếu lệnh thứ hai được đưa ra ngoài bằng cách bỏ thụt lề, nó sẽ chạy cả khi không có sách. Hãy xác định câu nào thực sự phụ thuộc điều kiện trước khi đặt nó vào khối.
Thứ tự nhánh quyết định trường hợp nào được chọn
Một điều kiện rộng có thể đúng cho cả những giá trị thuộc điều kiện hẹp hơn. Xét chương trình sau:
diem = 9
if diem >= 5:
print("Dat")
elif diem >= 8:
print("Tot")
else:
print("Can on tap")Dat
Điểm 9 thỏa cả hai điều kiện, nhưng nhánh đầu đã được chọn. Vì vậy chương trình in Dat, không in Tot. Muốn ưu tiên mức từ 8, hãy đặt điều kiện đó trước:
diem = 9
if diem >= 8:
print("Tot")
elif diem >= 5:
print("Dat")
else:
print("Can on tap")Tot
Một chuỗi if / elif / else chỉ chọn nhiều nhất một nhánh. Các lệnh if độc lập thì khác: mỗi điều kiện đều được kiểm tra.
diem = 9
if diem >= 8:
print("Tot")
if diem >= 5:
print("Dat")Tot Dat
Ở đây cả hai dòng đều được in. Dùng hai if khi bạn thật sự muốn kiểm tra hai việc riêng. Dùng elif khi các mức loại trừ nhau và bạn chỉ muốn chọn một mức.
Sau khi nhánh diem >= 8 sai, chương trình đã biết diem < 8. Vì thế, điều kiện diem >= 5 ở nhánh tiếp theo đủ để chọn khoảng từ 5 đến dưới 8. Kết luận này chỉ đúng nếu thứ tự các nhánh không đổi.
Thứ tự tăng dần cũng có thể đúng nếu bạn chọn cận trên thay vì cận dưới. Ví dụ sau chia số quyển sách thành ba nhóm, từ nhóm ít nhất:
so_sach = 4
if so_sach < 3:
print("It")
elif so_sach < 6:
print("Vua")
else:
print("Nhieu")Vua
Với 4 quyển, nhánh đầu sai và nhánh thứ hai đúng. Nếu chuyển so_sach < 6 lên đầu, nhánh đó cũng nhận cả 2 quyển. Không có quy tắc bắt buộc mọi số phải được viết theo thứ tự giảm; điều quan trọng là mỗi giá trị đến đúng nhánh.
So sánh liên tiếp mô tả một khoảng giá trị
Một phòng đọc nhận học sinh từ 10 đến dưới 15 tuổi cho một hoạt động. Bạn có thể viết hai phép so sánh cạnh nhau:
tuoi = 12
if 10 <= tuoi < 15:
print("Phu hop")
else:
print("Ngoai khoang")Phu hop
Biểu thức 10 <= tuoi < 15 đúng khi cả 10 <= tuoi và tuoi < 15 đều đúng. Đây là so sánh liên tiếp (chained comparison). Dấu <= lấy cả mốc 10; dấu < không lấy mốc 15.
tuoi = 15
if 10 <= tuoi and tuoi < 15:
print("Phu hop")
else:
print("Ngoai khoang")Ngoai khoang
Hai cách kiểm tra cùng khoảng trong ví dụ này. Với tuổi 15, điều kiện thứ hai sai nên kết quả là Ngoai khoang. Nếu đề muốn nhận cả tuổi 15, hãy thay < 15 bằng <= 15.
Đừng nhầm 10 <= tuoi < 15 với 10 <= tuoi > 15. Biểu thức sau yêu cầu tuổi vừa không nhỏ hơn 10 vừa lớn hơn 15; nó không diễn tả khoảng mong muốn.
tuoi = 12
print(10 <= tuoi < 15)
print(10 <= tuoi > 15)True False
Trước khi viết điều kiện, hãy đọc kỹ mốc có được tính hay không. “Từ 10 đến dưới 15” khác “từ 10 đến 15”.
Bạn cũng có thể dùng khoảng trong một chuỗi nhiều nhánh. Bảng sau phân nhóm số sách không âm; mỗi số chỉ thuộc một khoảng:
| Số sách | Nhóm |
|---|---|
| Từ 0 đến dưới 3 | Ít |
| Từ 3 đến dưới 6 | Vừa |
| Từ 6 trở lên | Nhiều |
so_sach = 3
if 0 <= so_sach < 3:
print("It")
elif 3 <= so_sach < 6:
print("Vua")
else:
print("Nhieu")Vua
Mốc 3 thuộc nhóm vừa, vì 3 <= so_sach đúng. Ví dụ này giả sử dữ liệu không âm. Nếu cần xử lý số âm, phải thêm quy tắc kiểm tra dữ liệu trước; nếu không else cũng nhận số âm.
Điều kiện lồng nhau kiểm tra tiếp trong một trường hợp
Một câu lạc bộ chỉ xem kết quả bài thử sau khi kiểm tra tuổi. Nếu đủ 10 tuổi, bạn cần đạt bài thử để được nhận:
tuoi = 12
ket_qua = "dat"
if tuoi >= 10:
if ket_qua == "dat":
print("Du dieu kien")
else:
print("Can on tap")
else:
print("Chua du tuoi")Du dieu kien
if ket_qua == "dat" nằm trong khối của if tuoi >= 10. Đây là điều kiện lồng nhau (nested conditional). Khi tuổi nhỏ hơn 10, Python bỏ qua toàn bộ khối bên trong và chạy else ngoài.
Mỗi else thuộc if cùng mức thụt lề. else bên trong xử lý kết quả bài thử; else bên ngoài xử lý tuổi. Hãy giữ cách thụt lề nhất quán để thấy mối liên hệ này.
tuoi = 9
ket_qua = "dat"
if tuoi >= 10:
if ket_qua == "dat":
print("Du dieu kien")
else:
print("Can on tap")
else:
print("Chua du tuoi")Chua du tuoi
Dù ket_qua là "dat", nhánh trong không được kiểm tra vì điều kiện tuổi sai. Đặt nhánh sai mức thụt lề có thể làm else gắn với if khác, khiến chương trình chạy nhưng cho kết quả sai. Nếu khối không được thụt vào sau dấu hai chấm, Python báo lỗi:
tuoi = 12
if tuoi >= 10:
print("Du tuoi")Lỗi khi chạy, ở dòng 3
IndentationError: expected an indented block after 'if' statement on line 2
Khi hai điều kiện chỉ cần cùng đúng để chọn một hành động, bạn cũng có thể kết hợp chúng bằng and đã học ở Bài 3:
tuoi = 12
ket_qua = "chua"
if tuoi >= 10 and ket_qua == "dat":
print("Du dieu kien")
else:
print("Chua du dieu kien")Chua du dieu kien
Cách này cho một thông báo chung khi một trong hai điều kiện sai. Nếu cần phân biệt “chưa đủ tuổi” với “cần ôn tập”, hãy giữ các nhánh riêng như ví dụ lồng nhau. Chọn cấu trúc theo thông tin bạn muốn chương trình trả về.
Bảng phân loại giúp chọn công thức và kiểm tra biên
Một cửa hàng tính phí giao hàng theo giá trị đơn hàng. Đơn dưới 100 nghìn đồng trả 20 nghìn. Đơn từ 100 đến dưới 200 trả 10 nghìn; từ 200 trở lên được miễn phí. Số tiền trong ví dụ là số nguyên tính bằng nghìn đồng.
| Giá trị đơn | Phí |
|---|---|
| Dưới 100 | 20 |
| Từ 100 đến dưới 200 | 10 |
| Từ 200 trở lên | 0 |
100
don = int(input())
if don < 100:
phi = 20
elif don < 200:
phi = 10
else:
phi = 0
print(phi)10
Khi don bằng 100, điều kiện đầu sai và điều kiện thứ hai đúng. Lệnh print(phi) nằm ngoài cấu trúc vì cả ba nhánh đều đã gán phi. Bảng trên chọn một mức phí cho toàn đơn; đó không phải phép tính cộng dồn theo từng bậc.
Trường hợp biên (boundary case) là dữ liệu ở ngay mốc hoặc sát mốc phân loại. Với số nguyên và mốc 100, hãy thử 99, 100 và 101. Với mốc 200, hãy thử 199, 200 và 201. Bảng sau cho thấy phí được tính bằng cùng quy tắc cho từng giá trị:
| Đơn | Phí |
|---|---|
| 99 | 20 |
| 100 | 10 |
| 101 | 10 |
| 199 | 10 |
| 200 | 0 |
| 201 | 0 |
Nếu đề cho phép đơn bằng 0, hãy thử thêm 0. Nếu đề giới hạn dữ liệu không âm, bạn không cần tự đoán cách xử lý số âm. Khi cần báo dữ liệu sai, hãy quy định rõ trường hợp đó và đặt kiểm tra phù hợp trước khi phân loại.
diem = 11
if diem < 0 or diem > 10:
print("Diem khong hop le")
elif diem >= 8:
print("Tot")
elif diem >= 5:
print("Dat")
else:
print("Can on tap")Diem khong hop le
Kiểm tra dữ liệu sai trước giúp 11 không bị xếp vào mức Tot. Với dữ liệu hợp lệ, chương trình tiếp tục kiểm tra các mức điểm. Bạn cũng nên thử đúng hai đầu 0 và 10.
Để tự kiểm tra, hãy viết kết quả mong đợi trước khi chạy. Sau đó nhập từng giá trị và so sánh kết quả thực tế. Nếu chỉ thử 6 và 9, bạn có thể bỏ qua lỗi tại 5, 8 hoặc 10.
Với bảng phí, bạn có thể cần tính thêm tổng số tiền khách trả. Việc này được thực hiện sau khi đã chọn phí:
don = 140
if don < 100:
phi = 20
elif don < 200:
phi = 10
else:
phi = 0
tong = don + phi
print(tong)150
Biến phi được gán ở cả ba nhánh, nên lệnh tính tong có giá trị để dùng. Nếu bỏ một phép gán ở nhánh có thể xảy ra, việc dùng biến sau đó có thể gây lỗi. Hãy kiểm tra từng đường đi từ đầu đến lệnh in.
Lỗi thường gặp
| Lỗi | Vì sao sai | Cách sửa |
|---|---|---|
Thiếu : sau elif | Python không nhận được đầu khối lệnh. | Thêm : sau điều kiện. |
Đặt diem >= 5 trước diem >= 8 | Mức rộng nhận cả điểm từ 8. | Kiểm tra mức từ 8 trước. |
Dùng hai if để chọn một mức | Cả hai khối có thể cùng chạy. | Nối nhánh thứ hai bằng elif. |
Dùng < khi đề tính cả mốc | Giá trị đúng mốc bị loại. | Đổi sang <= nếu đề gồm mốc. |
Thụt else sai cấp | else có thể gắn với if khác. | Căn else với if tương ứng. |
| Chỉ thử số nằm giữa các khoảng | Không phát hiện sai ở mốc. | Thử mốc và số sát hai bên. |
Dùng = trong điều kiện | = là phép gán, không phải so sánh. | Dùng == để so sánh bằng. |
Tóm tắt
if/elif/elsexét từ trên xuống và chọn tối đa một nhánh.- Điều kiện rộng đặt trước có thể che điều kiện hẹp; hãy sắp xếp theo mục tiêu.
a <= x < blấy mốcavà không lấy mốcb.- Điều kiện lồng nhau chỉ được xét khi chương trình đi vào khối chứa nó.
- Lập bảng khoảng và thử các mốc giúp phát hiện lỗi phân loại.