Mục lục
Mục tiêu bài học
Sau bài này bạn sẽ:
- Viết được vòng lặp
whilevới điều kiện dừng đúng. - Biết khi nào nên dùng
whilethay vìfor. - Tránh được bẫy infinite loop và biết cách dừng tiến trình đang treo.
- Dùng
breakđể thoát loop,continueđể bỏ qua iteration. - Biết pattern
while True+breakvà mệnh đềwhile ... else. - Áp dụng
whilevào pattern retry với exponential backoff khi gọi API model.
Cú pháp while
while lặp lại khối lệnh khi điều kiện còn True. Trước mỗi lần lặp, Python kiểm tra lại điều kiện; khi điều kiện thành False thì thoát loop.
while <condition>:
<body>
Ví dụ đếm từ 1 đến 5:
i = 1
while i <= 5:
print(i)
i += 1 # cập nhật biến điều kiện
# 1
# 2
# 3
# 4
# 5
Ba phần luôn cần có khi viết while:
- Khởi tạo biến điều kiện trước loop (
i = 1). - Điều kiện kiểm tra ở đầu mỗi lần lặp (
i <= 5). - Cập nhật biến điều kiện trong body (
i += 1) — thiếu bước này là dính infinite loop.
Khi nào dùng while thay vì for
Dùng for khi biết trước số lần lặp hoặc đang duyệt một iterable (list, range, file, ...). Dùng while khi số lần lặp phụ thuộc điều kiện động mà bạn không biết trước.
Các tình huống điển hình của while:
- Đọc input từ người dùng đến khi họ gõ
"quit". - Retry một network call cho đến khi success hoặc hết quota.
- Lặp huấn luyện đến khi loss nhỏ hơn ngưỡng (early stopping theo điều kiện).
- Đọc dữ liệu streaming đến khi nguồn đóng.
command = ""
while command != "quit":
command = input("> ")
print(f"Bạn vừa gõ: {command}")
Đoạn này không thể viết bằng for đơn giản, vì số lần lặp phụ thuộc người dùng.
Bẫy infinite loop và cách dừng
Lỗi phổ biến nhất với while là quên cập nhật biến điều kiện, khiến điều kiện luôn True:
# SAI — vòng lặp vô hạn, không bao giờ thoát
i = 1
while i <= 5:
print(i)
# thiếu i += 1
Cách dừng một loop đang treo:
- Terminal (python file.py): nhấn Ctrl + C để gửi tín hiệu
KeyboardInterrupt. - Google Colab / Jupyter: bấm nút Stop (hình vuông) bên trái cell, hoặc menu Runtime → Interrupt execution.
- VS Code Notebook: nút Interrupt trên thanh cell.
Một biến thể tinh vi hơn: điều kiện về mặt logic không bao giờ False vì kiểu dữ liệu sai:
n = "5" # n là str, không phải int!
while n > 0: # so sánh str với int -> TypeError trong Python 3
print(n)
n -= 1
Trước khi chạy while trên dữ liệu ngoài, kiểm tra kiểu bằng type() hoặc convert tường minh.
break — thoát vòng lặp
break thoát ngay lập tức khỏi vòng lặp gần nhất, không kiểm tra lại điều kiện.
i = 1
while i <= 10:
if i == 4:
break # dừng khi i = 4
print(i)
i += 1
# 1
# 2
# 3
break chỉ thoát loop chứa nó trực tiếp. Nếu lồng nhiều loop, mỗi lần break chỉ thoát một cấp.
continue — bỏ qua iteration
continue bỏ qua phần còn lại của iteration hiện tại, quay về kiểm tra điều kiện cho lần lặp kế tiếp.
# In các số lẻ từ 1 đến 10
i = 0
while i < 10:
i += 1
if i % 2 == 0:
continue # nếu chẵn, bỏ qua print
print(i)
# 1 3 5 7 9
Lưu ý đặt i += 1 trước continue; nếu đặt sau, khi gặp số chẵn loop sẽ không tăng i và treo vô hạn.
while True + break
Khi điều kiện thoát nằm ở giữa loop chứ không ở đầu, pattern phổ biến là while True + break:
while True:
command = input("Nhập lệnh (quit để thoát): ")
if command == "quit":
break
print(f"Đang chạy: {command}")
Cách này tránh phải khởi tạo command trước loop chỉ để vượt qua điều kiện ở đầu, code đọc thẳng hơn so với:
command = ""
while command != "quit":
command = input("Nhập lệnh (quit để thoát): ")
if command != "quit":
print(f"Đang chạy: {command}")
Cảnh giác: vì điều kiện luôn True, phải có break nằm trên đường thực thi, nếu không sẽ infinite loop.
while ... else
Python cho phép gắn else vào sau while. Khối else chạy khi loop kết thúc bình thường (điều kiện thành False), không chạy nếu loop thoát bằng break.
i = 1
while i <= 3:
print(i)
i += 1
else:
print("Loop chạy hết, không gặp break")
# 1
# 2
# 3
# Loop chạy hết, không gặp break
Có break thì else bị bỏ qua:
i = 1
while i <= 3:
if i == 2:
break
i += 1
else:
print("Không in dòng này")
Cú pháp này ít gặp; chủ yếu hữu ích khi cần phân biệt "tìm được" (break) và "tìm hết không thấy" (else chạy).
So sánh while vs for
| Tiêu chí | for |
while |
|---|---|---|
| Số lần lặp | Biết trước (độ dài iterable) | Phụ thuộc điều kiện động |
| Đầu vào | Một iterable (list, range, file, ...) | Một biểu thức boolean |
| Cập nhật biến đếm | Tự động | Phải tự cập nhật trong body |
| Nguy cơ infinite loop | Thấp | Cao nếu quên update |
| Use case AI/ML | Duyệt dataset, epoch cố định | Retry call, early stopping, streaming |
Quy tắc đơn giản: có iterable thì dùng for, có điều kiện thì dùng while.
Use case: retry API với exponential backoff
Khi gọi API model (OpenAI, Anthropic, HuggingFace Inference, ...), đôi khi gặp lỗi mạng hoặc rate limit (HTTP 429, 503). Pattern chuẩn là retry: thử lại vài lần, mỗi lần đợi lâu hơn lần trước — gọi là exponential backoff.
import time
import random
max_retries = 5
attempt = 0
delay = 1.0 # giây
while attempt < max_retries:
try:
# giả lập gọi API — thực tế là openai.chat.completions.create(...)
if random.random() < 0.7:
raise ConnectionError("503 Service Unavailable")
result = "OK"
print(f"Thành công ở lần thử {attempt + 1}")
break
except ConnectionError as e:
attempt += 1
if attempt >= max_retries:
print(f"Hết {max_retries} lần thử, bỏ cuộc")
raise
print(f"Lần {attempt} lỗi: {e}. Đợi {delay}s rồi thử lại")
time.sleep(delay)
delay *= 2 # 1s, 2s, 4s, 8s, 16s
Ý nghĩa từng phần:
while attempt < max_retries— giới hạn số lần thử, không treo vô hạn.break— thoát ngay khi thành công.delay *= 2— mỗi lần thất bại, đợi gấp đôi lần trước. Server có thời gian phục hồi, client không spam.raiseở lần cuối — ném exception ra ngoài để caller biết thật sự lỗi.
Pattern này gần như bắt buộc khi pipeline AI gọi nhiều API liên tiếp trong một batch.
Bài tập
Bài 1: Đoán số bằng binary search. Máy chọn ngẫu nhiên một số bí mật từ 1 đến 100. Viết chương trình tự đoán bằng binary search, in ra mỗi lần đoán và số lần đoán tổng cộng. Với khoảng 1-100, binary search cần tối đa 7 lần.
import random
secret = random.randint(1, 100)
low, high = 1, 100
attempts = 0
# TODO: dùng while để binary search
# - guess = (low + high) // 2
# - nếu guess == secret -> break
# - nếu guess < secret -> low = guess + 1
# - nếu guess > secret -> high = guess - 1
Bài 2: Đếm số chữ số của n. Cho một số nguyên dương n (ví dụ n = 12345), đếm xem nó có bao nhiêu chữ số bằng vòng lặp while và phép chia nguyên //. Không dùng str(n) rồi lấy len.
n = 12345
count = 0
# TODO: while n > 0 -> n //= 10, count += 1
# Kết quả mong đợi: count = 5
Mở rộng: xử lý cả trường hợp n = 0 (kết quả nên là 1) và n < 0 (lấy giá trị tuyệt đối trước).
Tóm tắt
while condition:lặp khiconditioncòn True; kiểm tra lại đầu mỗi iteration.- Luôn có 3 phần: khởi tạo, điều kiện, cập nhật biến điều kiện — quên phần thứ 3 là infinite loop.
- Dừng loop đang treo: Ctrl + C trong terminal; nút Stop / Interrupt trong Colab / Jupyter.
breakthoát ngay loop chứa nó;continuebỏ qua phần còn lại của iteration và lên kiểm tra điều kiện.- Pattern
while True+breakdùng khi điều kiện thoát ở giữa loop. while ... else:elsechạy khi loop kết thúc bình thường, không chạy nếu thoát bằngbreak.- Dùng
forvới iterable biết trước, dùngwhilevới điều kiện động (retry, streaming, early stopping). - Exponential backoff = retry với delay nhân đôi sau mỗi lần thất bại — pattern chuẩn khi gọi API model.
Bài tiếp theo sẽ học hàm (function) — đóng gói logic thành đơn vị tái sử dụng, bước đầu để viết code AI có cấu trúc.
