Python cơ bản: rẽ nhánh và vòng lặp
if/elif/else cho tiêu chí OK/NG, for, range, enumerate, while có giới hạn, break, continue và bài tập dừng dây chuyền.
Học xong bài này, bạn sẽ
- Viết if/elif/else cho tiêu chí OK/NG
- Dùng for, while, range, break, continue
- Tránh vòng lặp vô hạn
Nên học trước: Biến, kiểu dữ liệu và toán tử
Nội dung bài viết
Một trạm kiểm tra làm hai việc lặp đi lặp lại: ra quyết định (sản phẩm này OK hay NG?) và lặp (làm thế với hàng nghìn sản phẩm). Bài này dạy hai công cụ tương ứng: câu lệnh if và vòng lặp for, while.
1. Thụt lề: cách Python nhóm lệnh
Python không dùng dấu ngoặc nhọn như C# hay C++. Các lệnh thuộc cùng một khối được thụt vào 4 dấu cách sau một dòng kết thúc bằng dấu hai chấm :. VS Code tự thụt lề khi bạn nhấn Enter sau dấu :.
2. if, elif, else
do_sang = 42 # độ sáng trung bình của ảnh, 0–255
if do_sang < 50:
print("Ảnh quá tối: kiểm tra đèn")
elif do_sang > 200:
print("Ảnh quá sáng: giảm thời gian phơi sáng")
else:
print("Độ sáng bình thường")
Ảnh quá tối: kiểm tra đèn
Python kiểm tra lần lượt từ trên xuống, gặp điều kiện đúng đầu tiên thì chạy khối đó và bỏ qua phần còn lại. elif và else là tùy chọn.
Ví dụ thực tế: phân loại theo nhiều tiêu chí
duong_kinh = 12.53
co_ba_via = False
lech_tam = 0.08
if co_ba_via:
ket_qua, ly_do = "NG", "có ba via"
elif not (12.40 <= duong_kinh <= 12.60):
ket_qua, ly_do = "NG", f"đường kính {duong_kinh} ngoài dung sai"
elif lech_tam > 0.10:
ket_qua, ly_do = "NG", "lệch tâm quá 0.10 mm"
else:
ket_qua, ly_do = "OK", ""
print(ket_qua, ly_do)
OK
Kiểm tra lỗi nghiêm trọng nhất trước và ghi lại lý do NG. Khi trạm loại một sản phẩm, người vận hành luôn hỏi "vì sao", và bạn cần câu trả lời có sẵn trong log.
Biểu thức điều kiện một dòng
diem = 0.87
nhan = "NG" if diem >= 0.5 else "OK"
print(nhan) # NG
3. Vòng lặp for
for duyệt lần lượt qua từng phần tử của một dãy:
ket_qua_ca = ["OK", "OK", "NG", "OK", "NG", "OK"]
so_ng = 0
for kq in ket_qua_ca:
if kq == "NG":
so_ng += 1 # viết gọn của so_ng = so_ng + 1
print(f"{so_ng}/{len(ket_qua_ca)} sản phẩm NG")
2/6 sản phẩm NG
range(): lặp theo số
for i in range(3): # 0, 1, 2
print("Chụp ảnh lần", i)
for x in range(0, 640, 160): # bắt đầu 0, dừng trước 640, bước 160
print("Vạch chia tại cột", x)
Chụp ảnh lần 0
Chụp ảnh lần 1
Chụp ảnh lần 2
Vạch chia tại cột 0
Vạch chia tại cột 160
Vạch chia tại cột 320
Vạch chia tại cột 480
range(a, b) không bao gồm b. Đây là quy ước chung của Python (và của cắt ảnh bằng NumPy ở các bài sau), nên hãy làm quen ngay từ đầu.
enumerate(): vừa lấy số thứ tự vừa lấy phần tử
for stt, kq in enumerate(ket_qua_ca, start=1):
if kq == "NG":
print(f"Sản phẩm thứ {stt} bị NG")
Sản phẩm thứ 3 bị NG
Sản phẩm thứ 5 bị NG
Vòng lặp lồng nhau: duyệt lưới ô
Ảnh thường được chia thành lưới ô để kiểm tra từng vùng. Hai vòng lặp lồng nhau duyệt qua mọi ô:
rong, cao, o = 640, 480, 160
for y in range(0, cao, o):
for x in range(0, rong, o):
print(f"({x},{y})", end=" ")
print() # xuống dòng sau mỗi hàng
(0,0) (160,0) (320,0) (480,0)
(0,160) (160,160) (320,160) (480,160)
(0,320) (160,320) (320,320) (480,320)
4. Vòng lặp while
while lặp chừng nào điều kiện còn đúng. Dùng khi không biết trước số lần lặp, ví dụ thử lại kết nối camera:
so_lan_thu = 0
ket_noi_duoc = False
while not ket_noi_duoc and so_lan_thu < 5:
so_lan_thu += 1
print("Thử kết nối camera lần", so_lan_thu)
ket_noi_duoc = so_lan_thu == 3 # giả lập: lần 3 thì kết nối được
print("Kết nối:", ket_noi_duoc)
Thử kết nối camera lần 1
Thử kết nối camera lần 2
Thử kết nối camera lần 3
Kết nối: True
so_lan_thu < 5) hoặc lệnh break. Nếu lỡ chạy vô hạn, nhấn Ctrl+C trong terminal để dừng.5. break và continue
break: thoát hẳn khỏi vòng lặp.continue: bỏ qua phần còn lại của lượt hiện tại, sang lượt tiếp theo.
ten_files = ["a.png", "ghi_chu.txt", "b.png", "LOI.png", "c.png"]
for ten in ten_files:
if not ten.endswith(".png"):
continue # bỏ qua file không phải ảnh
if ten.startswith("LOI"):
print("Gặp ảnh lỗi, dừng xử lý:", ten)
break
print("Xử lý", ten)
Xử lý a.png
Xử lý b.png
Gặp ảnh lỗi, dừng xử lý: LOI.png
Vòng lặp chính của mọi chương trình camera bạn viết sau này có dạng while True: và thoát bằng break khi người dùng nhấn phím q. Bạn sẽ gặp lại ở chặng OpenCV.
Tóm tắt
- Khối lệnh = dòng kết thúc bằng
:+ thụt lề 4 dấu cách. if/elif/elsekiểm tra từ trên xuống, dừng ở điều kiện đúng đầu tiên. Ghi lại lý do NG.forduyệt dãy;range(a, b, buoc)không gồm b;enumeratecho số thứ tự.whilecần giới hạn để không chạy vô hạn;breakthoát,continuebỏ qua.
Bài tập
Bài 1. Phân loại độ sáng
Cho danh sách độ sáng của 8 ảnh: [12, 130, 245, 88, 47, 201, 150, 30]. In mỗi ảnh là "tối" (<50), "sáng" (>200) hay "tốt", và đếm số ảnh tốt.
Xem đáp án
do_sang_anh = [12, 130, 245, 88, 47, 201, 150, 30]
so_tot = 0
for i, v in enumerate(do_sang_anh, start=1):
if v < 50:
loai = "tối"
elif v > 200:
loai = "sáng"
else:
loai = "tốt"
so_tot += 1
print(f"Ảnh {i}: {v} → {loai}")
print("Số ảnh tốt:", so_tot)
Ảnh 1: 12 → tối
Ảnh 2: 130 → tốt
Ảnh 3: 245 → sáng
Ảnh 4: 88 → tốt
Ảnh 5: 47 → tối
Ảnh 6: 201 → sáng
Ảnh 7: 150 → tốt
Ảnh 8: 30 → tối
Số ảnh tốt: 3
Bài 2. Ba NG liên tiếp
Dây chuyền phải dừng nếu có 3 sản phẩm NG liên tiếp (dấu hiệu máy hỏng). Với ["OK","NG","NG","OK","NG","NG","NG","OK"], in vị trí (bắt đầu từ 1) của sản phẩm thứ ba trong chuỗi NG đó rồi dừng vòng lặp.
Xem đáp án
ds = ["OK", "NG", "NG", "OK", "NG", "NG", "NG", "OK"]
lien_tiep = 0
for stt, kq in enumerate(ds, start=1):
if kq == "NG":
lien_tiep += 1
else:
lien_tiep = 0 # gặp OK thì đếm lại từ đầu
if lien_tiep == 3:
print("DỪNG DÂY CHUYỀN tại sản phẩm", stt)
break
DỪNG DÂY CHUYỀN tại sản phẩm 7
Bài 3. Bảng thời gian phơi sáng
In bảng thời gian phơi sáng từ 100 µs đến 1000 µs, bước 100 µs, kèm độ nhòe (pixel) khi vật chạy 0,5 m/s và mỗi pixel là 0,05 mm. Gợi ý: quãng đường vật đi = vận tốc × thời gian; đổi đơn vị cẩn thận.
Xem đáp án
van_toc_mm_s = 0.5 * 1000 # 0,5 m/s = 500 mm/s
mm_moi_px = 0.05
for t_us in range(100, 1001, 100):
quang_duong_mm = van_toc_mm_s * t_us / 1_000_000
nhoe_px = quang_duong_mm / mm_moi_px
canh_bao = " ← nhòe quá 1 pixel" if nhoe_px > 1 else ""
print(f"{t_us:5d} µs: nhòe {nhoe_px:.1f} px{canh_bao}")
100 µs: nhòe 1.0 px
200 µs: nhòe 2.0 px ← nhòe quá 1 pixel
300 µs: nhòe 3.0 px ← nhòe quá 1 pixel
400 µs: nhòe 4.0 px ← nhòe quá 1 pixel
500 µs: nhòe 5.0 px ← nhòe quá 1 pixel
600 µs: nhòe 6.0 px ← nhòe quá 1 pixel
700 µs: nhòe 7.0 px ← nhòe quá 1 pixel
800 µs: nhòe 8.0 px ← nhòe quá 1 pixel
900 µs: nhòe 9.0 px ← nhòe quá 1 pixel
1000 µs: nhòe 10.0 px ← nhòe quá 1 pixel
Kết luận: muốn ảnh không nhòe quá 1 pixel ở tốc độ này, thời gian phơi sáng phải ≤ 100 µs. Đó là lý do phải dùng đèn strobe ở chặng 5.


