Bỏ qua đến nội dung chính
Học Python
Logo Python cạnh cửa sổ code trên nền xanh

Vòng lặp for trong Python: range, list, ví dụ dễ hiểu

AIDev TeamTham vấn chuyên môn: Nguyễn Việt Chung

Đăng 11 phút đọc

Mục lục · 19

Bài này dành cho người mới học Python, đi từ cú pháp vòng lặp for trong Python qua ví dụ giỏ hàng, bảng cửu chương và đơn hàng: range(), list, dict, enumerate, zip, break, continue. Mọi output chạy thật trên Python 3.15.1, kèm các lỗi người mới hay gặp và phép đo for so với while.

Vòng lặp for trong Python lấy lần lượt từng phần tử của một dãy, gán phần tử đó vào một biến, rồi chạy khối lệnh thụt lề bên dưới cho mỗi phần tử. Dãy ở đây có thể là list, chuỗi, dict (kiểu dữ liệu lưu từng cặp khóa và giá trị) hay một dãy số tạo bằng range(). Khi hết phần tử, vòng lặp tự dừng, bạn không phải tự đếm.

Mọi đoạn code trong bài, mình chạy ngày 26/10/2026 trên Python 3.15.1, máy CPU thuê theo giờ của AIDev Cloud chạy Ubuntu 24.04. Output trong ảnh là output thật. Mấy điều nên nắm trước:

  • for hợp với việc biết trước sẽ lặp qua cái gì: một list đơn hàng, 10 dòng của bảng cửu chương, các khóa của dict.

  • range(a, b) cho dãy số từ a đến b - 1, không gồm b. Người mới hay nhầm ở chỗ này.

  • enumerate() cho thêm số thứ tự, zip() ghép hai list chạy song song.

  • break dừng hẳn vòng lặp, continue bỏ qua phần còn lại của lượt hiện tại.

Cú pháp vòng lặp for trong Python viết thế nào?

Một vòng for có ba phần: từ khóa for, tên biến nhận phần tử, và dãy cần lặp sau chữ in. Cuối dòng có dấu hai chấm. Các dòng thuộc vòng lặp phải thụt lề như nhau, thường là bốn dấu cách. Tài liệu chính thức mô tả cú pháp này ở mục for Statements của Python Tutorial. Ví dụ dưới đây cộng tiền một giỏ hàng ba món:

python
gio_hang = [("Cà phê sữa", 29000), ("Bánh mì", 25000), ("Trà đào", 35000)]

tong = 0
for ten, gia in gio_hang:
    print(f"{ten:<12}{gia:>8,}đ")
    tong += gia

print(f"{'Tổng':<12}{tong:>8,}đ")

Mỗi phần tử của gio_hang là một tuple (cặp giá trị đặt trong ngoặc tròn) gồm tên món và giá. Viết for ten, gia in gio_hang thì Python tách sẵn mỗi cặp vào hai biến ten và gia. Trong f-string (chuỗi có chữ f phía trước, giá trị đặt trong ngoặc nhọn), :<12 căn trái tên món trong 12 ô, còn :>8, căn phải giá và thêm dấu phẩy ngăn hàng nghìn. Dòng print cuối cùng không thụt lề nên nằm ngoài vòng lặp và chỉ chạy một lần, sau khi đã cộng xong.

Terminal Python 3.15.1 trên AIDev Cloud: chạy gio_hang.py in ra Cà phê sữa 29,000đ, Bánh mì 25,000đ, Trà đào 35,000đ và dòng Tổng 89,000đ

Biến tong là biến tích lũy: gán bằng 0 trước vòng lặp, mỗi lượt cộng thêm một ít. Bạn sẽ gặp cách viết này ở gần như mọi bài toán đếm, cộng hay tìm số lớn nhất.

Dùng range() trong vòng for như thế nào?

Khi cần lặp theo số lần thay vì theo một list có sẵn, bạn dùng range(). Hàm này nhận một, hai hoặc ba số:

Cách viết

Ra dãy

Ghi nhớ

range(5)

0, 1, 2, 3, 4

bắt đầu từ 0, dừng trước 5

range(1, 6)

1, 2, 3, 4, 5

muốn có 5 thì ghi 6

range(0, 10, 2)

0, 2, 4, 6, 8

số thứ ba là bước nhảy

range(10, 0, -3)

10, 7, 4, 1

bước âm để đếm ngược

range(5, 1)

(rỗng)

bước mặc định là +1 nên không đi được từ 5 xuống 1

range() không tạo sẵn cả dãy trong bộ nhớ, nó sinh từng số khi vòng lặp cần. Muốn xem cả dãy thì bọc trong list(), như mình làm trong file range_demo.py:

Terminal Python 3.15.1: list(range(5)) ra 0 đến 4, range(1, 6) ra 1 đến 5, range(0, 10, 2) ra các số chẵn, range(10, 0, -3) ra 10 7 4 1, range(5, 1) ra list rỗng

Dòng cuối là một list rỗng, và Python không báo lỗi gì. Nếu vòng for i in range(5, 1) của bạn không chạy lượt nào, hãy nhìn lại thứ tự hai số và bước nhảy.

Lặp qua list, dict và lấy số thứ tự ra sao?

Muốn in số thứ tự kèm phần tử, người mới hay viết for i in range(len(ten)) rồi lấy ten[i]. Cách đó chạy được, nhưng enumerate() gọn hơn và tránh được lỗi chỉ số. Khi có hai list cùng độ dài, zip() lấy từng cặp phần tử ở cùng vị trí:

python
ten = ["An", "Bình", "Chi"]
diem = [8.5, 6.0, 9.25]

for stt, hoc_vien in enumerate(ten, start=1):
    print(stt, hoc_vien)

for hoc_vien, d in zip(ten, diem):
    print(f"{hoc_vien}: {d}")

Với dict, vòng for mặc định chỉ lặp qua khóa. Thêm .items() để lấy cả khóa lẫn giá trị:

python
ton_kho = {"áo thun": 12, "quần jean": 0, "mũ": 5}

for mat_hang, so_luong in ton_kho.items():
    if so_luong == 0:
        print(f"{mat_hang}: hết hàng")
    else:
        print(f"{mat_hang}: còn {so_luong}")
Terminal Python 3.15.1: enumerate in 1 An, 2 Bình, 3 Chi; zip in An 8.5, Bình 6.0, Chi 9.25; lặp dict tồn kho in áo thun còn 12, quần jean hết hàng, mũ còn 5

Chuỗi cũng lặp được theo từng ký tự: for chu in "Python" cho sáu lượt, mỗi lượt một chữ cái.

Vòng for lồng nhau

Đặt một vòng for bên trong vòng khác thì vòng trong chạy hết một lượt cho mỗi phần tử của vòng ngoài. Bảng cửu chương là ví dụ quen thuộc:

python
for i in range(2, 5):
    for j in range(1, 6):
        print(f"{i} x {j} = {i * j:<3}", end="  ")
    print()

end=" " giữ các phép nhân trên cùng một dòng, còn print() rỗng ở vòng ngoài xuống dòng sau mỗi bảng. Vòng ngoài chạy ba lượt, vòng trong năm lượt, nên có 15 phép nhân:

Terminal Python 3.15.1: bảng cửu chương 2, 3, 4 mỗi bảng từ x 1 đến x 5 in trên ba dòng

break, continue và else trong vòng for dùng khi nào?

continue bỏ qua phần còn lại của lượt đang chạy và sang phần tử kế tiếp. break dừng hẳn vòng lặp. Vòng for còn có nhánh else: nhánh này chạy khi vòng lặp đi hết dãy mà không gặp break. Ví dụ với bốn đơn hàng:

python
don_hang = [("DH01", "Hoàn tất", 320000), ("DH02", "Hủy", 150000),
            ("DH03", "Hoàn tất", 1250000), ("DH04", "Hoàn tất", 90000)]

doanh_thu = 0  # continue: bỏ qua đơn hủy
for ma, trang_thai, tien in don_hang:
    if trang_thai == "Hủy":
        continue
    doanh_thu += tien
print("Doanh thu:", doanh_thu)

for ma, trang_thai, tien in don_hang:  # break: dừng ở đơn đầu tiên từ 1 triệu
    if tien >= 1_000_000:
        print("Đơn lớn đầu tiên:", ma)
        break
else:
    print("Không có đơn nào từ 1 triệu")
Terminal Python 3.15.1: break_continue.py in Doanh thu 1660000 và Đơn lớn đầu tiên DH03

Doanh thu 1.660.000 đồng là tổng ba đơn hoàn tất, đơn DH02 bị bỏ qua. Vòng thứ hai dừng ở DH03 nên dòng trong else không in ra. Nếu đổi giá DH03 xuống dưới 1 triệu, vòng lặp đi hết bốn đơn và dòng "Không có đơn nào từ 1 triệu" sẽ hiện.

Vòng lặp for có chậm không, so với while và comprehension?

Mình tính tổng bình phương của 10 triệu số đầu tiên bằng bốn cách: vòng for, vòng while, list comprehension (viết vòng lặp tạo list trong một dòng, [i * i for i in range(N)]) và generator (giống comprehension nhưng dùng ngoặc tròn, sinh từng số thay vì tạo cả list). Mỗi cách chạy năm lần bằng timeit (module đo thời gian có sẵn trong Python), lấy lần nhanh nhất. Script kiểm cả bốn cách ra cùng một kết quả trước khi đo.

Biểu đồ thời gian tính tổng bình phương 10 triệu số trên Python 3.15.1, máy CPU AIDev Cloud: for 0,96 giây, generator 1,04 giây, comprehension 1,13 giây, while 1,16 giây

Ở phép tính này, vòng for nhanh nhất, còn while chậm hơn khoảng 21% vì mỗi lượt phải tự so sánh i < N và tự tăng i. Mình chạy thêm hai lượt đo nữa, thứ tự bốn cách vẫn giữ nguyên, while chậm hơn for lần lượt 26% và 24%. Chênh lệch về tốc độ không lớn, nhưng chênh lệch về RAM thì lớn hơn nhiều. Mình đo RAM đỉnh (lượng RAM cao nhất chương trình dùng trong lúc chạy) của từng cách, mỗi cách chạy trong một tiến trình riêng:

Terminal Python 3.15.1: RAM đỉnh khi không làm gì 11,4 MB, vòng for 11,4 MB, comprehension 394,2 MB, generator 11,5 MB

Cách viết

Thời gian (giây)

RAM đỉnh (MB)

vòng for

0,96

11,4

generator

1,04

11,5

list comprehension

1,13

394,2

vòng while

1,16

chưa đo

List comprehension phải tạo xong list 10 triệu số rồi mới cộng, nên tốn gần 400 MB. Vòng for và generator chỉ giữ một con số tại mỗi thời điểm. Với dữ liệu nhỏ vài nghìn phần tử, cách nào cũng xong trong nháy mắt, bạn cứ chọn cách dễ đọc nhất.

Những lỗi nào hay gặp với vòng lặp for?

Mình cố tình viết sai từng lỗi dưới đây rồi chạy trên Python 3.15.1 để lấy đúng error message. Bạn có thể chép dòng cuối của error message để tìm trên Google.

Lặp qua một con số, quên dấu hai chấm, quên thụt lề

text
TypeError: 'int' object is not iterable
SyntaxError: expected ':'
IndentationError: expected an indented block after 'for' statement on line 1
Terminal Python 3.15.1: loi_int.py báo TypeError int object is not iterable ở dòng for i in n; loi_hai_cham.py báo SyntaxError expected dấu hai chấm; loi_thut_le.py báo IndentationError expected an indented block after for statement on line 1

TypeError xuất hiện khi viết for i in n với n = 5. Một con số không phải là dãy nên Python không lặp qua được. Muốn lặp n lần thì viết for i in range(n). Hai lỗi còn lại sửa đúng như error message chỉ ra: thêm dấu : cuối dòng for, và thụt dòng print(i) vào bốn dấu cách.

Lặp quá phần tử cuối của list

Khi dùng chỉ số, người mới hay cộng thêm 1 vào len() vì sợ thiếu phần tử cuối:

python
diem = [7, 8, 9]
for i in range(len(diem) + 1):
    print(diem[i])
Terminal Python 3.15.1: loi_index.py in 7, 8, 9 rồi báo IndexError list index out of range ở dòng in diem theo chỉ số i

List có ba phần tử thì chỉ số hợp lệ là 0, 1, 2. Ở lượt thứ tư, code đọc diem[3] nên Python báo IndexError: list index out of range. Cách sửa an toàn nhất là bỏ chỉ số, viết for d in diem.

Xóa phần tử của list ngay trong vòng lặp

Lỗi này khó thấy nhất vì Python không báo gì cả. Mình muốn bỏ các điểm dưới 5 khỏi list [4, 3, 8, 2, 9], kết quả đúng phải là [8, 9]:

python
diem = [4, 3, 8, 2, 9]
for d in diem:
    if d < 5:
        diem.remove(d)
print(diem)
Terminal Python 3.15.1: loi_xoa.py, xóa trong lúc lặp in ra 3, 8, 9 còn sót số 3; cách dùng comprehension in ra 8, 9 đúng

Kết quả còn sót số 3. Khi số 4 ở vị trí 0 bị xóa, cả list dồn lên một ô, số 3 vào vị trí 0, trong khi vòng lặp đã đi tiếp sang vị trí 1 nên bỏ qua số 3. Cách sửa là tạo list mới thay vì sửa list đang lặp: diem = [d for d in diem if d >= 5], ra đúng [8, 9].

Khi nào không nên dùng vòng for?

Vòng lặp for trong Python không hợp khi bạn chưa biết phải lặp bao nhiêu lần, ví dụ hỏi mật khẩu cho tới khi người dùng gõ đúng. Trường hợp đó dùng while. Với các phép tính có sẵn hàm, như cộng một list số, sum(ds) ngắn hơn và dễ đọc hơn một vòng for tự viết.

Khi làm với bảng dữ liệu hàng trăm nghìn dòng, vòng for duyệt từng dòng thường là cách chậm nhất. Library pandas tính trên cả cột một lần, bài pandas là gì có ví dụ đọc 6.000 đơn hàng của một cửa hàng mẫu. Mình chưa đo riêng chênh lệch giữa for và pandas cho bài này, nên không đưa ra con số.

Câu hỏi thường gặp

Vòng for và vòng while khác nhau thế nào?

for lặp qua một dãy có sẵn và tự dừng khi hết dãy. while lặp chừng nào điều kiện còn đúng, và bạn phải tự làm cho điều kiện sai đi, nếu không vòng lặp chạy mãi. Trong phép đo tốc độ của bài này, cùng một phép tính viết bằng while chậm hơn for từ 21% đến 26% qua ba lượt đo.

Làm sao lặp ngược từ cuối list lên đầu?

Dùng reversed(): for x in reversed(ds). Với dãy số, dùng bước âm như range(10, 0, -1) để đếm từ 10 xuống 1. Hàm reversed() không tạo list mới nên không tốn thêm bộ nhớ.

Có cần đặt tên biến là i không?

Không bắt buộc. i, j hợp với chỉ số và số đếm. Khi lặp qua dữ liệu, tên có nghĩa như don, mon, hoc_vien giúp đọc lại code dễ hơn nhiều. Nếu không dùng tới biến, có thể đặt tên là _, ví dụ for _ in range(3).

Vòng for trong Python khác C hay Java ở đâu?

Trong C hay Java, vòng for thường có ba phần: khởi tạo, điều kiện, bước tăng. Python không có dạng đó. Vòng for của Python luôn lặp qua một dãy, còn việc đếm số giao cho range(). Vì vậy code Python ít khi phải tự quản lý biến đếm.

Bước tiếp theo

Trong lộ trình tám chặng ở bài học Python từ số 0, vòng lặp nằm ở chặng 3, cùng với câu lệnh điều kiện. Bạn có thể luyện ngay với bộ bài tập Python có máy tự chấm: bài 4, 6 và 11 đều cần vòng lặp. Muốn xem vòng lặp nằm trong một chương trình hoàn chỉnh, bài chương trình Python mẫu có chương trình đoán số, tính tiết kiệm và đếm ngược. Nếu chưa chọn được chỗ gõ code, bài phần mềm lập trình Python so VS Code, PyCharm và Thonny.

Chương 2 của ebook Python từ số 0 dạy for, while, vòng lặp lồng nhau và biến tích lũy, kết bằng bài mẫu máy ATM rút tiền theo mệnh giá. Sách có lời giải cho bài tập cuối chương.

Code trong bài chạy trên Python 3.15.1, máy CPU Starter của AIDev Cloud (Intel Xeon E5-2680 v4, 8 vCPU, 16 GB RAM, Ubuntu 24.04.4), ngày 26/10/2026.

Tham vấn chuyên môn

Nguyễn Việt Chung

Nhà sáng lập AIDev và VietPlatform · Thạc sĩ AI MSE

  • Tốt nghiệp thủ khoa xuất sắc Thạc sĩ AI MSE.
  • Đồng sáng lập, CTO E-University, SVOnline: số hóa 10+ đại học, 40.000+ sinh viên.
  • Xây hệ thống AI cho doanh nghiệp tại VietPlatform.
Biên soạn: AIDev Team · Rà soát · Quy trình biên tập