Bài 11. Comprehension và hàm nâng cao

Bài này giúp viết Python “đúng chất Python” (Pythonic): list/dict comprehension, *args/**kwargs, lambda, hàm bậc cao, decorator và pattern matching.

50 phútTrung cấp
Bạn sẽ học được
  • Viết comprehension cho list, dict, set
  • Dùng *args, **kwargs, tham số chỉ từ khóa
  • Dùng lambda với sorted, map, filter
  • Hiểu và viết decorator; dùng match-case
Thuật ngữ cần biết
Comprehension
Cú pháp tạo tập hợp từ vòng lặp trong một biểu thức.
Hàm bậc cao
Hàm nhận hoặc trả về hàm khác.
Decorator
Hàm bọc hàm khác để thêm chức năng.
Pattern matching
So khớp cấu trúc dữ liệu với match-case.

Khái niệm và lý thuyết

Trong Python, hàm là đối tượng hạng nhất: có thể gán vào biến, truyền làm tham số, trả về từ hàm khác. Đây là nền tảng của hàm bậc cao và decorator.

Comprehension là cách ngắn gọn, dễ đọc và thường nhanh hơn vòng lặp append. Tuy nhiên nếu logic dài hơn một dòng hoặc lồng quá hai tầng, hãy quay về vòng for để dễ đọc.

Comprehension

so = [3, 8, 1, 6, 10]
binh_phuong = [x * x for x in so]              # [9, 64, 1, 36, 100]
chan = [x for x in so if x % 2 == 0]           # [8, 6, 10]
diem = {"An": 8, "Bình": 4, "Chi": 9}
dat = {ten: d for ten, d in diem.items() if d >= 5}
chu_cai = {ten[0] for ten in diem}             # set
tong = sum(x * x for x in range(1_000_000))    # generator expression, tiết kiệm bộ nhớ

Tham số linh hoạt

def tao_the(tieu_de, *the, **thuoc_tinh):
    print(tieu_de, the, thuoc_tinh)

tao_the("Bài 1", "python", "cơ bản", mau="xanh", ghim=True)
# Bài 1 ('python', 'cơ bản') {'mau': 'xanh', 'ghim': True}

def chia(a, b, /, *, lam_tron=2):   # a, b chỉ theo vị trí; lam_tron chỉ theo tên
    return round(a / b, lam_tron)
chia(10, 3, lam_tron=3)

lambda và hàm bậc cao

sinh_vien = [("An", 8.5), ("Bình", 7.0), ("Chi", 9.2)]
xep = sorted(sinh_vien, key=lambda sv: sv[1], reverse=True)
cao_nhat = max(sinh_vien, key=lambda sv: sv[1])
ten_hoa = list(map(str.upper, ["an", "bình"]))

Decorator

import time
from functools import wraps

def do_thoi_gian(ham):
    @wraps(ham)
    def boc(*args, **kwargs):
        bd = time.perf_counter()
        kq = ham(*args, **kwargs)
        print(f"{ham.__name__} chạy {time.perf_counter() - bd:.3f}s")
        return kq
    return boc

@do_thoi_gian
def tinh_tong(n):
    return sum(range(n))
tinh_tong(10_000_000)

Thư viện chuẩn có sẵn decorator hữu ích: @functools.cache (nhớ kết quả), @property, @staticmethod.

match-case

def xu_ly(lenh: str):
    match lenh.split():
        case ["chao"]:
            return "Xin chào!"
        case ["cong", a, b]:
            return int(a) + int(b)
        case ["thoat" | "quit"]:
            return "Tạm biệt"
        case _:
            return "Không hiểu lệnh"
Mẹo hay

Gặp hàm đệ quy tính lại nhiều lần (như Fibonacci), thêm @cache có thể tăng tốc hàng nghìn lần.

Lưu ý

Đừng dùng giá trị mặc định có thể thay đổi như def f(ds=[]): danh sách bị dùng chung giữa các lần gọi. Dùng ds=None rồi tạo mới trong thân hàm.

Thực hành
  1. Dùng comprehension tạo danh sách số nguyên tố nhỏ hơn 100.
  2. Viết hàm thong_ke(*so) trả về (min, max, trung bình).
  3. Sắp xếp danh sách từ điển sinh viên theo điểm giảm dần, cùng điểm thì theo tên.
  4. Viết decorator thu_lai(n) chạy lại hàm tối đa n lần khi gặp lỗi.
Tóm tắt bài học
  • Comprehension ngắn gọn cho list, dict, set.
  • *args/**kwargs và /, * kiểm soát cách truyền tham số.
  • Hàm là đối tượng: lambda, hàm bậc cao, decorator.
  • match-case so khớp cấu trúc dữ liệu.