Giới thiệu
List comprehension giúp dễ dàng tạo danh sách dẫn xuất từ danh sách nguồn bằng cách áp dụng biểu thức. Ví dụ: nhân mỗi phần tử với 5.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
multiply_by_5 = [x * 5 for x in a]
print(multiply_by_5) # [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
Xử lý nhiều iterator cùng lúc với zip()
Giả sử có 2 danh sách cần cộng phần tử tương ứng:
list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]
# Cách dùng vòng lặp
list3 = []
for i in range(len(list1)):
list3.append(list1[i] + list2[i])
# [600, 800, 1000, 1200]
# Cách dùng zip() - gọn nhẹ hơn
list4 = [(a + b) for a, b in zip(list1, list2)]
print(list4) # [600, 800, 1000, 1200]
zip() ghép các phần tử cùng chỉ số thành tuple, lặp qua chúng đồng thời.
Vấn đề nghiêm trọng: zip() với iterator độ dài khác nhau
list1.append(1000) # list1 giờ dài hơn list2
print(len(list1), len(list2)) # 5, 4
list5 = [(a + b) for a, b in zip(list1, list2)]
print(list5) # [600, 800, 1000, 1200] - phần tử thứ 5 bị mất!
zip() dừng lại khi bất kỳ iterator nào hết. Không ném ngoại lệ → dễ gây bug lặng lẽ trong production.
Giải pháp: itertools.zip_longest()
zip_longest tiếp tục lặp cho đến khi tất cả iterator đều hết. Phần tử thiếu được điền bằng None (hoặc giá trị fillvalue tuỳ chỉnh).
from itertools import zip_longest
list6 = []
for a, b in zip_longest(list1, list2):
if b is None:
print(" << xử lý khi list2 hết >>")
elif a is None:
print(" << xử lý khi list1 hết >>")
else:
list6.append(a + b)
print(list6) # [600, 800, 1000, 1200]
Kết luận
zip()rất tiện để lặp song song nhiều iterator.zip()hoạt động khác khi iterator độ dài khác nhau (dừng sớm, không báo lỗi).- Cần iterator độ dài khác nhau → dùng
zip_longest()từitertools.