Mục lục Python

Docs / Python

Vòng lặp for trong Python

Vòng lặp for đi qua từng phần tử của một dãy, mỗi vòng xử lý một phần tử. Trừ máu cho mọi con quái, in từng món trong kho đồ, cộng điểm của cả đội: đều là việc của for.

Duyệt list

Người học C# hay nghĩ for phải có biến đếm i và điều kiện dừng. for trong Python khác: nó lấy thẳng từng phần tử, không cần chỉ số.

inventory = ["Kiếm", "Khiên", "Bình máu"]

for item in inventory:
    print("Trong túi có:", item)
# Trong túi có: Kiếm
# Trong túi có: Khiên
# Trong túi có: Bình máu

Mỗi vòng, item nhận giá trị của phần tử tiếp theo. Tên item do bạn đặt, nên chọn tên số ít của tên list: for enemy in enemies, for score in scores.

for duyệt được cả chuỗi (từng ký tự), tuple, set và dictionary.

Lặp theo số lần với range

range(n) tạo dãy số từ 0 tới n - 1:

for wave in range(3):
    print("Đợt quái số", wave)
# Đợt quái số 0
# Đợt quái số 1
# Đợt quái số 2

Lỗi hay gặp: tưởng range(3) chạy tới 3. Nó dừng trước 3, chỉ có 0, 1, 2. Muốn đếm từ 1 tới 3 thì viết range(1, 4).

range nhận tối đa ba tham số: bắt đầu, kết thúc (không lấy), bước nhảy.

print(list(range(1, 6)))       # [1, 2, 3, 4, 5]
print(list(range(0, 20, 5)))   # [0, 5, 10, 15]
print(list(range(10, 0, -3)))  # [10, 7, 4, 1]

Đếm ngược trước khi trận đấu bắt đầu:

for second in range(3, 0, -1):
    print(second)
print("Bắt đầu!")
# 3
# 2
# 1
# Bắt đầu!

Lấy cả chỉ số với enumerate

Khi cần cả vị trí lẫn giá trị, người mới hay viết for i in range(len(list)):

scores = [1500, 1200, 980]
for i in range(len(scores)):
    print(i + 1, scores[i])

Chạy được, nhưng Python có cách gọn hơn là enumerate. Nó trả về từng cặp (chỉ số, giá trị):

scores = [1500, 1200, 980]
for rank, score in enumerate(scores, start=1):
    print(f"Hạng {rank}: {score} điểm")
# Hạng 1: 1500 điểm
# Hạng 2: 1200 điểm
# Hạng 3: 980 điểm

start=1 để đếm từ 1 thay vì 0, hợp với bảng xếp hạng.

Duyệt dictionary

for trên dict mặc định lấy các khóa. Muốn cả khóa lẫn giá trị thì dùng items():

stock = {"Bình máu": 5, "Mũi tên": 40}

for item in stock:
    print(item)
# Bình máu
# Mũi tên

for item, amount in stock.items():
    print(f"{item} x{amount}")
# Bình máu x5
# Mũi tên x40

break và continue trong for

break và continue dùng giống như trong vòng lặp while:

enemies = ["Slime", "Bat", "Dragon", "Goblin"]

for enemy in enemies:
    if enemy == "Bat":
        continue          # bỏ qua dơi
    if enemy == "Dragon":
        print("Gặp rồng, rút lui!")
        break             # dừng hẳn
    print("Hạ", enemy)
# Hạ Slime
# Gặp rồng, rút lui!

Goblin không bao giờ được xét vì break đã thoát vòng lặp.

Sửa list trong khi duyệt

Muốn giảm máu cho mọi con quái, người mới hay viết:

enemy_hps = [30, 50, 20]
for hp in enemy_hps:
    hp -= 10
print(enemy_hps)  # [30, 50, 20], không đổi gì

hp chỉ là bản sao giá trị của từng phần tử, trừ nó không ảnh hưởng tới list. Phải gán lại qua chỉ số:

enemy_hps = [30, 50, 20]
for i, hp in enumerate(enemy_hps):
    enemy_hps[i] = hp - 10
print(enemy_hps)  # [20, 40, 10]

Vòng lặp lồng nhau

Duyệt bản đồ dạng lưới (list trong list) cần hai vòng for:

dungeon = [
    ["#", "E", "#"],
    [".", "@", "E"],
]
for row_index, row in enumerate(dungeon):
    for col_index, cell in enumerate(row):
        if cell == "E":
            print(f"Quái ở hàng {row_index}, cột {col_index}")
# Quái ở hàng 0, cột 1
# Quái ở hàng 1, cột 2

Bài tập

Cho party = {"Aki": 120, "Rin": 0, "Kai": 75} là máu của từng người. Dùng for để in tên những người còn sống kèm số máu, và đếm xem có bao nhiêu người còn sống.

Xem đáp án
party = {"Aki": 120, "Rin": 0, "Kai": 75}
alive_count = 0

for name, hp in party.items():
    if hp > 0:
        print(f"{name}: {hp} máu")
        alive_count += 1

print("Còn sống:", alive_count)
# Aki: 120 máu
# Kai: 75 máu
# Còn sống: 2