Vòng lặp là cách bạn bảo máy tính làm đi làm lại một việc. Python có hai loại vòng lặp, và việc chọn đúng loại giúp code ngắn gọn hơn nhiều.
Vòng lặp for
Khác với C hay Java, for trong Python không đếm số mà duyệt qua từng phần tử:
ngon_ngu = ["Python", "Go", "Rust"]
for ten in ngon_ngu:
print(f"Tôi đang học {ten}")
Khi cần đếm, dùng range:
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 10, 2): # 2, 4, 6, 8
print(i)
for i in range(10, 0, -1): # đếm ngược
print(i)
Cần cả chỉ số lẫn giá trị
Người mới hay viết thế này:
for i in range(len(ngon_ngu)): # cách của ngôn ngữ khác
print(i, ngon_ngu[i])
Python có cách gọn hơn:
for i, ten in enumerate(ngon_ngu):
print(i, ten)
for i, ten in enumerate(ngon_ngu, start=1): # đánh số từ 1
print(f"{i}. {ten}")
Duyệt hai danh sách cùng lúc
ten = ["An", "Bình", "Cường"]
diem = [8.5, 7.0, 9.2]
for t, d in zip(ten, diem):
print(f"{t}: {d}")
Lưu ý zip dừng ở danh sách ngắn nhất. Nếu muốn báo lỗi khi độ dài khác nhau, dùng zip(ten, diem, strict=True) — tham số có từ Python 3.10 và rất đáng dùng, vì độ dài lệch nhau thường là dấu hiệu dữ liệu có vấn đề.
Vòng lặp while
Dùng khi bạn không biết trước phải lặp bao nhiêu lần:
tong = 0
while tong < 100:
n = int(input("Nhập một số: "))
tong += n
print(f"Tổng hiện tại: {tong}")
Rủi ro lớn nhất của while là vòng lặp vô tận. Luôn tự hỏi: điều kiện này sẽ sai vào lúc nào?
i = 0
while i < 10:
print(i)
# quên i += 1 -> chạy mãi không dừng
break và continue
for so in [3, 7, 12, 5, 20]:
if so > 10:
print(f"Gặp {so}, dừng lại")
break # thoát hẳn vòng lặp
for so in range(10):
if so % 2:
continue # bỏ qua phần còn lại, sang vòng kế
print(so) # chỉ in số chẵn
Mệnh đề else của vòng lặp
Đây là tính năng ít người biết. Khối else chạy khi vòng lặp kết thúc mà không gặp break:
ds = [4, 8, 15, 16, 23]
for x in ds:
if x > 100:
print("Tìm thấy số lớn hơn 100")
break
else:
print("Không có số nào lớn hơn 100")
Cách này gọn hơn việc tạo một biến cờ rồi kiểm tra sau vòng lặp.
Vòng lặp lồng nhau
for i in range(1, 4):
for j in range(1, 4):
print(f"{i} x {j} = {i*j}")
break chỉ thoát vòng lặp gần nhất. Muốn thoát cả hai, cách sạch nhất là đưa vào hàm rồi return:
def tim(ma_tran, muc_tieu):
for hang in ma_tran:
for o in hang:
if o == muc_tieu:
return True
return False
Những lỗi thường gặp
Sửa danh sách trong lúc đang duyệt nó
ds = [1, 2, 3, 4, 5, 6]
for x in ds:
if x % 2 == 0:
ds.remove(x) # SAI - bỏ sót phần tử
print(ds) # [1, 3, 5] - trông có vẻ đúng nhưng không phải luôn thế
Khi bạn xóa phần tử, các phần tử phía sau dịch lên, còn con trỏ duyệt vẫn tiến tới — kết quả là vài phần tử bị bỏ qua. Hãy tạo danh sách mới:
ds = [x for x in ds if x % 2]
Quên rằng range không bao gồm điểm cuối
for i in range(1, 10): # chạy từ 1 tới 9, KHÔNG có 10
print(i)
Khi nào không cần vòng lặp
Python có sẵn nhiều hàm làm thay bạn, vừa ngắn vừa nhanh hơn:
ds = [4, 8, 15, 16, 23, 42]
tong = sum(ds)
lon_nhat = max(ds)
co_so_le = any(x % 2 for x in ds)
toan_duong = all(x > 0 for x in ds)
da_sap_xep = sorted(ds, reverse=True)
Nếu bạn đang viết vòng lặp chỉ để cộng dồn hoặc tìm giá trị lớn nhất, gần như chắc chắn có sẵn hàm làm việc đó.