Skip to content

Thực hành: Standard Library Mastery

🎯 Mục tiêu

🎯 Sau bài thực hành này, bạn sẽ:

  • Sử dụng thành thạo Counter, defaultdict, deque từ collections
  • Áp dụng lru_cache, partial, reduce từ functools
  • Làm việc với file system qua pathlib thay vì os.path

Mô tả bài tập

Python Standard Library chứa rất nhiều công cụ mạnh mẽ mà nhiều developer bỏ qua. Thay vì tự viết lại, hãy tận dụng những gì đã được tối ưu sẵn. Bài tập này giúp bạn khám phá những module hữu ích nhất.

Yêu cầu

Bài 1: Collections Module

Giải quyết các bài toán thực tế với Counter, defaultdict, deque.

python
from collections import Counter, defaultdict, deque

# --- Counter ---
words = "the quick brown fox jumps over the lazy dog the fox".split()
# TODO: Đếm tần suất từ, tìm 3 từ phổ biến nhất

# --- defaultdict ---
students = [
    ("Toán", "An"), ("Văn", "Bình"), ("Toán", "Cường"),
    ("Văn", "An"), ("", "Bình"), ("Toán", "Dũng"),
]
# TODO: Nhóm sinh viên theo môn học dùng defaultdict(list)

# --- deque ---
def sliding_window_max(nums: list[int], k: int) -> list[int]:
    """Tìm giá trị lớn nhất trong mỗi cửa sổ kích thước k."""
    # TODO: Dùng deque để giải O(n) thay vì O(n*k)
    pass

# Test
print(sliding_window_max([1, 3, -1, -3, 5, 3, 6, 7], 3))
# Output: [3, 3, 5, 5, 6, 7]

Bài 2: Functools Module

Tận dụng lru_cache, partial, reduce để viết code ngắn gọn hơn.

python
from functools import lru_cache, partial, reduce

# --- lru_cache ---
@lru_cache(maxsize=128)
def expensive_computation(n: int) -> int:
    """Tính số Fibonacci thứ n — có cache."""
    # TODO: Implement recursive fibonacci với cache
    pass

# --- partial ---
def power(base: int, exponent: int) -> int:
    return base ** exponent

# TODO: Tạo square và cube dùng partial
# square = partial(...)
# cube = partial(...)

# --- reduce ---
def compose(*functions):
    """Kết hợp nhiều hàm: compose(f, g, h)(x) = f(g(h(x)))"""
    # TODO: Dùng reduce để compose functions
    pass

# Test
add_one = lambda x: x + 1
double = lambda x: x * 2
square = lambda x: x ** 2
transform = compose(square, double, add_one)
print(transform(3))  # square(double(add_one(3))) = square(8) = 64

Bài 3: Pathlib — File System Hiện Đại

Sử dụng pathlib.Path thay cho os.path — code sạch và dễ đọc hơn.

python
from pathlib import Path

def analyze_directory(dir_path: str) -> dict:
    """Phân tích thư mục: đếm file theo extension, tổng kích thước."""
    path = Path(dir_path)
    # TODO:
    # 1. Đếm số file theo từng extension (.py, .txt, .md, ...)
    # 2. Tính tổng kích thước (bytes)
    # 3. Tìm file lớn nhất
    # Return: {"extensions": Counter, "total_size": int, "largest": Path}
    pass

def find_python_files(root: str) -> list[Path]:
    """Tìm tất cả file .py, bỏ qua __pycache__ và .venv."""
    # TODO: Dùng Path.rglob("*.py") với filter
    pass

Gợi ý

Gợi ý Bài 1
  • Counter(words).most_common(3) trả về top 3 phổ biến nhất
  • defaultdict(list) tự tạo list rỗng cho key mới: d[key].append(value)
  • deque hỗ trợ appendleft(), popleft() O(1) — lý tưởng cho sliding window
Gợi ý Bài 2
  • @lru_cache biến recursive fibonacci từ O(2^n) thành O(n)
  • partial(power, exponent=2) tạo hàm mới với argument cố định
  • reduce(lambda f, g: lambda x: f(g(x)), functions) cho compose
Gợi ý Bài 3
  • Path.iterdir() liệt kê files, Path.rglob("*.py") tìm đệ quy
  • file.suffix trả extension (.py), file.stat().st_size trả kích thước
  • Path.rglob kết hợp filter để bỏ __pycache__

Lời giải tham khảo

Xem lời giải
python
from collections import Counter, defaultdict
from functools import lru_cache, reduce

# Bài 1: Counter + defaultdict
words = "the quick brown fox jumps over the lazy dog the fox".split()
word_count = Counter(words)
top_3 = word_count.most_common(3)  # [('the', 3), ('fox', 2), ...]
students_by_subject = defaultdict(list)
for subject, name in students:
    students_by_subject[subject].append(name)

# Bài 2: lru_cache + compose
@lru_cache(maxsize=128)
def expensive_computation(n: int) -> int:
    if n < 2:
        return n
    return expensive_computation(n - 1) + expensive_computation(n - 2)

def compose(*functions):
    return reduce(lambda f, g: lambda x: f(g(x)), functions)