Iterator và itertools: duyệt dữ liệu hiệu quả trong Python

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 islicechain 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.

Lên đầu trang