✨ 14.4 Viết chương trình con và ứng dụng
📖 Giới thiệu
Viết chương trình con (functions) hiệu quả là kỹ năng quan trọng trong lập trình. Bài học này sẽ hướng dẫn cách thiết kế, tổ chức và ứng dụng functions vào các dự án thực tế, từ đơn giản đến phức tạp.
INFO
Functions giúp code dễ đọc, dễ bảo trì, và có thể tái sử dụng
🎯 Thiết kế functions hiệu quả
📝 Single Responsibility Principle
python
# ❌ Function làm quá nhiều việc
def xu_ly_hoc_sinh_xau(data):
"""Function này làm quá nhiều việc - không tốt"""
# Validate
if not data or not isinstance(data, dict):
return None
# Format tên
ten = data.get("ten", "").strip().title()
# Tính điểm TB
diem = data.get("diem", [])
if diem:
diem_tb = sum(diem) / len(diem)
else:
diem_tb = 0
# Phân loại
if diem_tb >= 8:
xep_loai = "Giỏi"
elif diem_tb >= 6.5:
xep_loai = "Khá"
else:
xep_loai = "Trung bình"
# Format output và in
ket_qua = f"{ten} - {diem_tb:.1f} - {xep_loai}"
print(ket_qua)
return ket_qua
# ✅ Chia thành nhiều function nhỏ - tốt hơn
def validate_hoc_sinh_data(data):
"""Kiểm tra dữ liệu học sinh hợp lệ"""
if not data or not isinstance(data, dict):
return False, "Dữ liệu không hợp lệ"
if "ten" not in data or not data["ten"].strip():
return False, "Thiếu tên học sinh"
if "diem" not in data or not isinstance(data["diem"], list):
return False, "Thiếu danh sách điểm"
return True, "Dữ liệu hợp lệ"
def format_ten_hoc_sinh(ten):
"""Chuẩn hóa tên học sinh"""
return ten.strip().title() if ten else ""
def tinh_diem_trung_binh(danh_sach_diem):
"""Tính điểm trung bình"""
if not danh_sach_diem:
return 0
return sum(danh_sach_diem) / len(danh_sach_diem)
def phan_loai_hoc_sinh(diem_tb):
"""Phân loại học sinh theo điểm TB"""
if diem_tb >= 8:
return "Giỏi"
elif diem_tb >= 6.5:
return "Khá"
elif diem_tb >= 5:
return "Trung bình"
else:
return "Yếu"
def tao_thong_tin_hoc_sinh(data):
"""Tạo thông tin học sinh hoàn chỉnh"""
# Validate
hop_le, thong_bao = validate_hoc_sinh_data(data)
if not hop_le:
return None, thong_bao
# Xử lý từng phần
ten = format_ten_hoc_sinh(data["ten"])
diem_tb = tinh_diem_trung_binh(data["diem"])
xep_loai = phan_loai_hoc_sinh(diem_tb)
return {
"ten": ten,
"diem_tb": diem_tb,
"xep_loai": xep_loai
}, "Thành công"
# Test hai cách tiếp cận
data_test = {
"ten": " nguyễn văn an ",
"diem": [8.5, 7.0, 9.0, 8.0]
}
print("✅ CÁCH TỐT - Functions nhỏ, rõ ràng:")
thong_tin, msg = tao_thong_tin_hoc_sinh(data_test)
if thong_tin:
print(f"👤 {thong_tin['ten']}")
print(f"📊 Điểm TB: {thong_tin['diem_tb']:.1f}")
print(f"🏆 Xếp loại: {thong_tin['xep_loai']}")TIP
Mỗi function chỉ nên làm một việc duy nhất và làm tốt việc đó
📥 Input/Output rõ ràng
python
def tinh_chi_phi_dien(so_kwh, bac_gia=None):
"""
Tính tiền điện theo bậc thang
Args:
so_kwh (float): Số kWh tiêu thụ
bac_gia (list): Danh sách bậc giá [mức, giá]. Mặc định là giá VN 2024
Returns:
dict: {
'so_kwh': float,
'tong_tien': float,
'chi_tiet': list,
'bac_cao_nhat': int
}
Raises:
ValueError: Nếu so_kwh < 0
"""
if so_kwh < 0:
raise ValueError("Số kWh không thể âm")
# Bậc giá mặc định (VN 2024)
if bac_gia is None:
bac_gia = [
(50, 1678), # 0-50 kWh
(100, 1734), # 51-100 kWh
(200, 2014), # 101-200 kWh
(300, 2536), # 201-300 kWh
(400, 2834), # 301-400 kWh
(float('inf'), 2927) # >400 kWh
]
tong_tien = 0
chi_tiet = []
kwh_con_lai = so_kwh
bac_hien_tai = 0
for muc, gia in bac_gia:
if kwh_con_lai <= 0:
break
bac_hien_tai += 1
kwh_bac_nay = min(kwh_con_lai, muc - sum(m for m, _ in bac_gia[:bac_hien_tai-1]))
if kwh_bac_nay > 0:
tien_bac_nay = kwh_bac_nay * gia
tong_tien += tien_bac_nay
chi_tiet.append({
'bac': bac_hien_tai,
'kwh': kwh_bac_nay,
'gia': gia,
'thanh_tien': tien_bac_nay
})
kwh_con_lai -= kwh_bac_nay
return {
'so_kwh': so_kwh,
'tong_tien': tong_tien,
'chi_tiet': chi_tiet,
'bac_cao_nhat': bac_hien_tai
}
# Test function với documentation rõ ràng
print("💡 TÍNH TIỀN ĐIỆN:")
try:
ket_qua = tinh_chi_phi_dien(250)
print(f"📊 Sử dụng: {ket_qua['so_kwh']} kWh")
print(f"💰 Tổng tiền: {ket_qua['tong_tien']:,.0f} VND")
print(f"📈 Bậc cao nhất: {ket_qua['bac_cao_nhat']}")
print(f"\n📋 Chi tiết:")
for bac in ket_qua['chi_tiet']:
print(f" Bậc {bac['bac']}: {bac['kwh']} kWh × {bac['gia']:,} = {bac['thanh_tien']:,.0f} VND")
except ValueError as e:
print(f"❌ Lỗi: {e}")🏗️ Tổ chức code với functions
🧩 Module hóa và composition
python
# Module xử lý văn bản
def dem_tu_trong_chuoi(text):
"""Đếm số từ trong chuỗi"""
return len(text.split()) if text else 0
def dem_ky_tu_khong_space(text):
"""Đếm ký tự không bao gồm khoảng trắng"""
return len(text.replace(" ", "")) if text else 0
def tim_tu_dai_nhat(text):
"""Tìm từ dài nhất trong chuỗi"""
if not text:
return ""
cac_tu = text.split()
return max(cac_tu, key=len) if cac_tu else ""
def tinh_ty_le_chu_hoa(text):
"""Tính tỷ lệ chữ hoa trong text"""
if not text:
return 0
chu_hoa = sum(1 for c in text if c.isupper())
return (chu_hoa / len(text)) * 100
# Module thống kê
def tao_bao_cao_van_ban(text):
"""Tạo báo cáo phân tích văn bản (function composition)"""
if not text:
return {"loi": "Văn bản trống"}
bao_cao = {
"van_ban": text,
"do_dai": len(text),
"so_tu": dem_tu_trong_chuoi(text),
"ky_tu_khong_space": dem_ky_tu_khong_space(text),
"tu_dai_nhat": tim_tu_dai_nhat(text),
"ty_le_chu_hoa": tinh_ty_le_chu_hoa(text),
"do_dai_tb_tu": 0
}
# Tính độ dài trung bình của từ
if bao_cao["so_tu"] > 0:
bao_cao["do_dai_tb_tu"] = bao_cao["ky_tu_khong_space"] / bao_cao["so_tu"]
return bao_cao
def in_bao_cao_van_ban(bao_cao):
"""In báo cáo văn bản đẹp"""
if "loi" in bao_cao:
print(f"❌ {bao_cao['loi']}")
return
print("📝 BÁO CÁO PHÂN TÍCH VĂN BẢN")
print("="*50)
print(f"📏 Độ dài: {bao_cao['do_dai']} ký tự")
print(f"🔤 Số từ: {bao_cao['so_tu']}")
print(f"📊 Ký tự (không space): {bao_cao['ky_tu_khong_space']}")
print(f"📐 Độ dài TB/từ: {bao_cao['do_dai_tb_tu']:.1f} ký tự")
print(f"🔤 Từ dài nhất: '{bao_cao['tu_dai_nhat']}' ({len(bao_cao['tu_dai_nhat'])} ký tự)")
print(f"🔠 Tỷ lệ chữ hoa: {bao_cao['ty_le_chu_hoa']:.1f}%")
# Test module composition
van_ban_test = """
Python là ngôn ngữ lập trình mạnh mẽ và DỄ HỌC.
Với cú pháp ĐƠN GIẢN, Python giúp lập trình viên
tập trung vào giải quyết vấn đề thay vì lo lắng về cú pháp.
"""
bao_cao = tao_bao_cao_van_ban(van_ban_test)
in_bao_cao_van_ban(bao_cao)🎯 Main function pattern
python
def doc_du_lieu_hoc_sinh():
"""Mô phỏng đọc dữ liệu từ file/database"""
return [
{"ten": "Nguyễn Văn An", "lop": "10A1", "diem": [8.5, 9.0, 7.5]},
{"ten": "Trần Thị Bình", "lop": "10A1", "diem": [7.0, 8.0, 8.5]},
{"ten": "Lê Văn Chi", "lop": "10A2", "diem": [9.0, 9.5, 8.0]},
{"ten": "Phạm Thị Dung", "lop": "10A2", "diem": [6.5, 7.0, 7.5]},
]
def xu_ly_du_lieu_hoc_sinh(data_list):
"""Xử lý dữ liệu học sinh"""
ket_qua = []
for data in data_list:
thong_tin, msg = tao_thong_tin_hoc_sinh(data)
if thong_tin:
ket_qua.append(thong_tin)
else:
print(f"⚠️ Lỗi xử lý {data.get('ten', 'Unknown')}: {msg}")
return ket_qua
def thong_ke_theo_lop(hoc_sinh_list, data_goc):
"""Thống kê theo lớp"""
lop_stats = {}
# Tạo dict mapping tên -> lớp
ten_to_lop = {hs["ten"]: hs["lop"] for hs in data_goc}
for hs in hoc_sinh_list:
lop = ten_to_lop.get(hs["ten"], "Unknown")
if lop not in lop_stats:
lop_stats[lop] = []
lop_stats[lop].append(hs)
return lop_stats
def in_bao_cao_tong_ket(lop_stats):
"""In báo cáo tổng kết"""
print("\n📊 BÁO CÁO TỔNG KẾT")
print("="*60)
for lop, hoc_sinh in lop_stats.items():
print(f"\n🏫 LỚP {lop} ({len(hoc_sinh)} học sinh):")
# Tính thống kê lớp
diem_tb_lop = sum(hs["diem_tb"] for hs in hoc_sinh) / len(hoc_sinh)
# Đếm xếp loại
xep_loai_count = {}
for hs in hoc_sinh:
xl = hs["xep_loai"]
xep_loai_count[xl] = xep_loai_count.get(xl, 0) + 1
print(f" 📊 Điểm TB lớp: {diem_tb_lop:.2f}")
print(f" 🏆 Phân bổ xếp loại:")
for xl, count in xep_loai_count.items():
ty_le = (count / len(hoc_sinh)) * 100
print(f" • {xl}: {count} HS ({ty_le:.1f}%)")
print(f" 📋 Chi tiết:")
for hs in sorted(hoc_sinh, key=lambda x: x["diem_tb"], reverse=True):
print(f" {hs['ten']:<15} {hs['diem_tb']:>5.1f} {hs['xep_loai']}")
def main():
"""Hàm main điều khiển luồng chương trình"""
print("🎓 HỆ THỐNG QUẢN LÝ HỌC SINH")
print("="*50)
try:
# 1. Đọc dữ liệu
print("📖 Đang đọc dữ liệu...")
data_hoc_sinh = doc_du_lieu_hoc_sinh()
print(f"✅ Đọc thành công {len(data_hoc_sinh)} học sinh")
# 2. Xử lý dữ liệu
print(f"\n🔄 Đang xử lý dữ liệu...")
hoc_sinh_processed = xu_ly_du_lieu_hoc_sinh(data_hoc_sinh)
print(f"✅ Xử lý thành công {len(hoc_sinh_processed)} học sinh")
# 3. Thống kê
print(f"\n📊 Đang tạo thống kê...")
lop_stats = thong_ke_theo_lop(hoc_sinh_processed, data_hoc_sinh)
# 4. Báo cáo
in_bao_cao_tong_ket(lop_stats)
print(f"\n✅ Hoàn thành!")
except Exception as e:
print(f"❌ Lỗi: {e}")
return False
return True
# Chạy chương trình
if __name__ == "__main__":
main()INFO
Pattern main() giúp code có cấu trúc rõ ràng và dễ test
🏆 Ứng dụng thực tế - Hệ thống quản lý cửa hàng
python
# === PRODUCT MANAGEMENT SYSTEM ===
def tao_san_pham(ma_sp, ten, gia, so_luong, danh_muc="Khác"):
"""Tạo sản phẩm mới"""
return {
"ma_sp": ma_sp,
"ten": ten,
"gia": gia,
"so_luong": so_luong,
"danh_muc": danh_muc,
"da_ban": 0
}
def validate_san_pham(san_pham):
"""Validate thông tin sản phẩm"""
if not san_pham.get("ma_sp"):
return False, "Thiếu mã sản phẩm"
if not san_pham.get("ten"):
return False, "Thiếu tên sản phẩm"
if san_pham.get("gia", 0) <= 0:
return False, "Giá phải lớn hơn 0"
if san_pham.get("so_luong", 0) < 0:
return False, "Số lượng không thể âm"
return True, "Hợp lệ"
def them_san_pham(kho, san_pham):
"""Thêm sản phẩm vào kho"""
hop_le, msg = validate_san_pham(san_pham)
if not hop_le:
return False, msg
if san_pham["ma_sp"] in kho:
return False, f"Sản phẩm {san_pham['ma_sp']} đã tồn tại"
kho[san_pham["ma_sp"]] = san_pham
return True, "Thêm sản phẩm thành công"
def cap_nhat_so_luong(kho, ma_sp, so_luong_moi):
"""Cập nhật số lượng sản phẩm"""
if ma_sp not in kho:
return False, f"Không tìm thấy sản phẩm {ma_sp}"
if so_luong_moi < 0:
return False, "Số lượng không thể âm"
kho[ma_sp]["so_luong"] = so_luong_moi
return True, f"Cập nhật số lượng {ma_sp}: {so_luong_moi}"
def ban_hang(kho, ma_sp, so_luong):
"""Xử lý bán hàng"""
if ma_sp not in kho:
return False, f"Không tìm thấy sản phẩm {ma_sp}", 0
san_pham = kho[ma_sp]
if san_pham["so_luong"] < so_luong:
return False, f"Không đủ hàng. Còn {san_pham['so_luong']}", 0
# Cập nhật số lượng
san_pham["so_luong"] -= so_luong
san_pham["da_ban"] += so_luong
# Tính tiền
thanh_tien = san_pham["gia"] * so_luong
return True, f"Bán thành công {so_luong} {san_pham['ten']}", thanh_tien
def tim_san_pham(kho, tu_khoa):
"""Tìm sản phẩm theo tên hoặc mã"""
ket_qua = []
tu_khoa_lower = tu_khoa.lower()
for ma_sp, sp in kho.items():
if (tu_khoa_lower in sp["ten"].lower() or
tu_khoa_lower in ma_sp.lower()):
ket_qua.append(sp)
return ket_qua
def thong_ke_kho(kho):
"""Thống kê tổng quan kho hàng"""
if not kho:
return {"thong_bao": "Kho trống"}
tong_san_pham = len(kho)
tong_gia_tri = sum(sp["gia"] * sp["so_luong"] for sp in kho.values())
tong_da_ban = sum(sp["da_ban"] for sp in kho.values())
tong_doanh_thu = sum(sp["gia"] * sp["da_ban"] for sp in kho.values())
# Thống kê theo danh mục
danh_muc_stats = {}
for sp in kho.values():
dm = sp["danh_muc"]
if dm not in danh_muc_stats:
danh_muc_stats[dm] = {"so_san_pham": 0, "gia_tri": 0}
danh_muc_stats[dm]["so_san_pham"] += 1
danh_muc_stats[dm]["gia_tri"] += sp["gia"] * sp["so_luong"]
# Sản phẩm sắp hết hàng
sap_het = [sp for sp in kho.values() if sp["so_luong"] < 10]
# Top sản phẩm bán chạy
ban_chay = sorted(kho.values(), key=lambda x: x["da_ban"], reverse=True)[:5]
return {
"tong_san_pham": tong_san_pham,
"tong_gia_tri": tong_gia_tri,
"tong_da_ban": tong_da_ban,
"tong_doanh_thu": tong_doanh_thu,
"danh_muc_stats": danh_muc_stats,
"sap_het": sap_het,
"ban_chay": ban_chay
}
def in_bao_cao_kho(thong_ke):
"""In báo cáo kho hàng"""
if "thong_bao" in thong_ke:
print(f"ℹ️ {thong_ke['thong_bao']}")
return
print("🏪 BÁO CÁO KHO HÀNG")
print("="*60)
print(f"📦 Tổng sản phẩm: {thong_ke['tong_san_pham']}")
print(f"💰 Tổng giá trị kho: {thong_ke['tong_gia_tri']:,} VND")
print(f"📊 Đã bán: {thong_ke['tong_da_ban']} sản phẩm")
print(f"💵 Doanh thu: {thong_ke['tong_doanh_thu']:,} VND")
print(f"\n📋 THỐNG KÊ THEO DANH MỤC:")
for dm, stats in thong_ke["danh_muc_stats"].items():
print(f" • {dm}: {stats['so_san_pham']} SP, {stats['gia_tri']:,} VND")
if thong_ke["sap_het"]:
print(f"\n⚠️ SẢN PHẨM SẮP HẾT ({len(thong_ke['sap_het'])}):")
for sp in thong_ke["sap_het"]:
print(f" • {sp['ten']}: {sp['so_luong']} còn lại")
print(f"\n🔥 TOP SẢN PHẨM BÁN CHẠY:")
for i, sp in enumerate(thong_ke["ban_chay"], 1):
print(f" {i}. {sp['ten']}: {sp['da_ban']} đã bán")
def demo_cua_hang():
"""Demo hệ thống cửa hàng hoàn chỉnh"""
print("🏪 DEMO HỆ THỐNG CỬA HÀNG")
print("="*50)
# Khởi tạo kho
kho = {}
# Thêm sản phẩm
san_pham_list = [
tao_san_pham("IP001", "iPhone 15", 25000000, 50, "Điện thoại"),
tao_san_pham("SS001", "Samsung S24", 22000000, 30, "Điện thoại"),
tao_san_pham("MB001", "MacBook Air", 35000000, 20, "Laptop"),
tao_san_pham("AP001", "AirPods Pro", 5000000, 100, "Phụ kiện"),
]
print("📦 Thêm sản phẩm vào kho:")
for sp in san_pham_list:
thanh_cong, msg = them_san_pham(kho, sp)
status = "✅" if thanh_cong else "❌"
print(f" {status} {msg}")
# Mô phỏng bán hàng
print(f"\n🛒 Mô phỏng bán hàng:")
ban_hang_list = [
("IP001", 5), # Bán 5 iPhone
("AP001", 15), # Bán 15 AirPods
("MB001", 2), # Bán 2 MacBook
("SS001", 8), # Bán 8 Samsung
]
tong_doanh_thu_ngay = 0
for ma_sp, so_luong in ban_hang_list:
thanh_cong, msg, thanh_tien = ban_hang(kho, ma_sp, so_luong)
status = "✅" if thanh_cong else "❌"
print(f" {status} {msg}")
if thanh_cong:
print(f" 💰 Thành tiền: {thanh_tien:,} VND")
tong_doanh_thu_ngay += thanh_tien
print(f"\n💵 Tổng doanh thu ngày: {tong_doanh_thu_ngay:,} VND")
# Báo cáo kho
print(f"\n" + "="*60)
thong_ke = thong_ke_kho(kho)
in_bao_cao_kho(thong_ke)
# Chạy demo
demo_cua_hang()📝 Bài tập thực hành
Bài tập 1: Hệ thống quản lý thư viện
Viết hệ thống quản lý thư viện với các function:
them_sach(thu_vien, sach)muon_sach(thu_vien, ma_sach, nguoi_muon)tra_sach(thu_vien, ma_sach)tim_sach(thu_vien, tu_khoa)thong_ke_thu_vien(thu_vien)
Gợi ý cấu trúc dữ liệu:
python
sach = {
"ma_sach": "S001",
"tieu_de": "Lập trình Python",
"tac_gia": "Nguyễn Văn A",
"nam_xb": 2023,
"tinh_trang": "có sẵn", # "có sẵn", "đã mượn"
"nguoi_muon": None,
"ngay_muon": None
}📚 Tóm tắt
Thiết kế function tốt:
- 📝 Single Responsibility: Mỗi function làm một việc
- 📥 Clear Input/Output: Tham số và return rõ ràng
- 📚 Documentation: Docstring mô tả đầy đủ
- ⚡ Descriptive Names: Tên function mô tả chức năng
Tổ chức code:
- 🧩 Modularization: Chia nhỏ thành các module
- 🔗 Function Composition: Kết hợp functions nhỏ thành lớn
- 📦 Helper Functions: Functions tiện ích tái sử dụng
- 🎯 Main Function: Điều khiển luồng chương trình
Best Practices:
- ✅ Validate input đầu vào
- 🛡️ Handle errors gracefully
- 🔄 Return meaningful values
- 📊 Separate logic and presentation
- 🧪 Design for testability
Ứng dụng thực tế:
- 🏫 Hệ thống quản lý (học sinh, nhân viên)
- 🛒 E-commerce và bán hàng
- 📊 Data processing và analysis
- 🎮 Game development
- 📝 Text processing applications
Lời khuyên cuối
Functions là nền tảng của code quality. Đầu tư thời gian thiết kế functions tốt sẽ tiết kiệm rất nhiều thời gian debug và maintain sau này!