Giao diện
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,dequetừ collections - Áp dụng
lru_cache,partial,reducetừ functools - Làm việc với file system qua
pathlibthay 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"), ("Lý", "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) = 64Bà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
passGợi ý
Gợi ý Bài 1
Counter(words).most_common(3)trả về top 3 phổ biến nhấtdefaultdict(list)tự tạo list rỗng cho key mới:d[key].append(value)dequehỗ trợappendleft(),popleft()O(1) — lý tưởng cho sliding window
Gợi ý Bài 2
@lru_cachebiế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ố địnhreduce(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 đệ quyfile.suffixtrả extension (.py),file.stat().st_sizetrả kích thướcPath.rglobkế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)