Mỗi lần bạn viết for x in danh_sach, Python đang dùng iterator ở bên dưới. Nắm được cơ chế này mở ra cả một thư viện công cụ rất mạnh: itertools.
Iterable và iterator khác gì nhau?
Iterable là thứ có thể duyệt (list, tuple, dict, chuỗi). Iterator là thứ nhớ vị trí hiện tại và trả về phần tử tiếp theo khi gọi next().
ds = [1, 2, 3]
it = iter(ds) # tạo iterator từ iterable
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# next(it) nữa -> StopIteration
Tự viết một iterator
class DemNguoc:
def __init__(self, n):
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n <= 0:
raise StopIteration
self.n -= 1
return self.n + 1
for so in DemNguoc(3):
print(so) # 3 2 1
itertools: những hàm dùng nhiều nhất
from itertools import chain, islice, groupby, combinations, count, cycle
# Nối nhiều iterable thành một
list(chain([1, 2], [3, 4], [5])) # [1, 2, 3, 4, 5]
# Cắt lát mà không tạo list trung gian
list(islice(range(1000), 5)) # [0, 1, 2, 3, 4]
# Mọi cặp không lặp
list(combinations("ABC", 2)) # [('A','B'), ('A','C'), ('B','C')]
groupby: gom nhóm dữ liệu đã sắp xếp
nhan_vien = [
{"ten": "An", "phong": "Kinh doanh"},
{"ten": "Bình", "phong": "Kỹ thuật"},
{"ten": "Cường", "phong": "Kỹ thuật"},
]
nhan_vien.sort(key=lambda x: x["phong"]) # BẮT BUỘC sắp xếp trước
for phong, nhom in groupby(nhan_vien, key=lambda x: x["phong"]):
print(phong, [n["ten"] for n in nhom])
Lưu ý: groupby chỉ gom các phần tử liền kề. Quên sắp xếp trước là lỗi phổ biến nhất khi dùng hàm này.
Vì sao nên quan tâm?
Các hàm itertools trả về iterator, tức là chỉ tính khi cần. Xử lý file log 10 triệu dòng bằng islice và chain gần như không tốn thêm bộ nhớ, trong khi cách tạo list trung gian có thể làm treo máy.
