Bài 11 · Vận dụng · 30 phút· Cập nhật 11/06/2026
Dự án cuối khoá: 3 app Python
Biên soạn bởi Nguyễn Anh Tuấn
Dự án Python cho người mới: dựng 3 app dòng lệnh (CLI) chạy được - quiz, sổ việc lưu JSON, phân tích văn bản - rồi đưa lên GitHub làm portfolio.
Bạn đã đi qua biến → kiểu dữ liệu → điều khiển luồng → hàm → cấu trúc dữ liệu → lỗi → module, và hiểu cả bản chất bytecode. Giờ ghép tất cả thành ba app dòng lệnh chạy được. Cả ba chung một khung đơn giản - chọn dự án để xem:
❓ Quiz trắc nghiệm - Hỏi từng câu, người dùng chọn số, chấm điểm cuối cùng.
- ▸Khung chung: Dữ liệu (list/dict) → Xử lý (vòng lặp/hàm) → Nhập-Xuất.
- ▸Quiz là bản mẫu đầy đủ; Sổ việc & Phân tích văn bản là đề bài có cột mốc.
- ▸Mục tiêu: ba sản phẩm chạy được để đưa lên GitHub.
Câu hỏi là một list các dict; một hàm hỏi từng câu và trả đúng/sai; vòng lặp cộng điểm. try/except giúp nhập sai không làm sập:
quiz.py
cau_hoi = [
{"hoi": "Thu do Viet Nam?", "dap_an": ["Ha Noi", "Hue"], "dung": 1},
{"hoi": "2 + 2 * 2 = ?", "dap_an": ["6", "8"], "dung": 1},
{"hoi": "Python thuoc loai ngon ngu nao?",
"dap_an": ["Bien dich thang ra ma may", "Thong dich (qua bytecode)"], "dung": 2},
]
def hoi_mot_cau(cau):
print("\n" + cau["hoi"])
for i, da in enumerate(cau["dap_an"], start=1):
print(f" {i}. {da}")
while True:
try:
chon = int(input("Chon (so): "))
if 1 <= chon <= len(cau["dap_an"]):
return chon == cau["dung"]
print(" So ngoai pham vi, thu lai.")
except ValueError:
print(" Phai nhap mot SO.") # nhap "abc" -> khong sap
def main():
diem = 0
for cau in cau_hoi:
if hoi_mot_cau(cau):
diem += 1
print(f"\nKet qua: {diem}/{len(cau_hoi)}")
if __name__ == "__main__":
main() Kết quả khi chạy
Thu do Viet Nam? 1. Ha Noi 2. Hue Chon (so): 1 ... Ket qua: 3/3
- ▸Dữ liệu: list các dict {hoi, dap_an, dung} - dễ thêm câu mới.
- ▸enumerate(..., start=1) để đánh số lựa chọn từ 1.
- ▸try/except ValueError + while: nhập sai thì hỏi lại, không sập.
Cùng khung, đổi dữ liệu thành list các dict việc và thêm phần lưu file để app “nhớ”. Module json đổi list/dict ↔ str JSON:
phần lưu/đọc - việc của bạn ghép vào CLI
import json
def tai(path):
try:
with open(path) as f:
return json.load(f) # JSON -> list cac dict
except FileNotFoundError:
return [] # chua co file -> rong
def luu(path, viec):
with open(path, "w") as f:
json.dump(viec, f, ensure_ascii=False, indent=2)
# moi viec la mot dict: {"ten": "hoc Python", "xong": False}
con_lai = sum(1 for v in viec if not v["xong"]) # dem viec chua xong - ▸Cột mốc 1: tai(path) đọc todo.json; chưa có file → trả list rỗng (try/except).
- ▸Cột mốc 2: luu(path, viec) ghi JSON (ensure_ascii=False để giữ tiếng Việt).
- ▸Cột mốc 3: lệnh thêm việc & đánh dấu xong (sửa dict trong list).
- ▸Cột mốc 4: đếm “còn N việc chưa xong”, lưu lại khi thoát.
Trọng tâm là dict & set: tách từ, đếm tần suất, và tìm số từ khác nhau:
lõi đếm từ - verify chạy thật
text = "python la python python"
tu = text.split() # ['python', 'la', 'python', 'python']
dem = {}
for t in tu:
dem[t] = dem.get(t, 0) + 1 # dem tan suat
print(dem) # {'python': 3, 'la': 1}
print("tu khac nhau:", len(set(tu))) # 2 Kết quả khi chạy
{'python': 3, 'la': 1}
tu khac nhau: 2- ▸Cột mốc 1: tách văn bản thành list từ bằng .split().
- ▸Cột mốc 2: đếm bằng dict.get(t, 0) + 1.
- ▸Cột mốc 3: số từ khác nhau = len(set(tu)).
- ▸Cột mốc 4: từ dài nhất max(tu, key=len); lọc từ > 3 ký tự bằng comprehension.
Một app chạy được là tốt; một app người khác cài & chạy được mới là sản phẩm. Hoàn thiện mỗi app theo checklist nhỏ này:
cấu trúc gọn cho mỗi app
quiz/
├── quiz.py
├── README.md # app lam gi + cach chay (python quiz.py)
└── .gitignore # bo __pycache__/, .venv/
# Dua len GitHub:
git init && git add . && git commit -m "feat: app quiz trac nghiem"
git remote add origin <url> && git push -u origin main - ▸README ngắn: app làm gì + lệnh chạy - để người khác (và bạn sau này) dùng được ngay.
- ▸.gitignore bỏ __pycache__/ và .venv/ - đừng commit thứ sinh ra tự động.
- ▸if __name__ == "__main__": để file vừa chạy trực tiếp, vừa import lại được (tái dùng hàm).
- ▸Bonus: tách hàm thuần (đếm điểm, đếm từ) để sau dễ VIẾT TEST (khoá nâng cao).
Hết khoá Python cơ bản 🎉 - bạn đã có 3 sản phẩm
Câu hỏi thường gặp
Vì hầu hết app dòng lệnh đều theo khuôn: có DỮ LIỆU (list/dict), có phần XỬ LÝ (vòng lặp/hàm), và phần NHẬP-XUẤT (print/input/file). Nhận ra khuôn chung giúp bạn dựng app mới nhanh: chỉ thay dữ liệu và nghiệp vụ.
Bọc int(input(...)) trong try/except ValueError (bài 8). Nếu người dùng gõ "abc", int() ném ValueError; ta bắt và yêu cầu nhập lại trong một vòng while - chương trình không sập.
JSON là một định dạng văn bản để biểu diễn dữ liệu (list, dict, int/float, str). Module json đổi list/dict Python ↔ str JSON, nên rất hợp để lưu một list các dict ra file rồi đọc lại - dữ liệu “nhớ” qua mỗi lần chạy.
with open(path) as f: tự ĐÓNG file khi xong (kể cả khi có lỗi) - an toàn và gọn hơn tự gọi f.close(). Đây là một “context manager”; bạn sẽ học kỹ hơn ở khoá nâng cao.
Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.
Trả lời vài câu để chắc rằng em đã nắm bài.
Khung chung mà cả ba app dòng lệnh trong bài đều theo là gì?
- 1
Dựng Quiz
Gõ lại app Quiz ở Bước 2, thêm 2 câu hỏi của riêng bạn, chạy và chấm điểm.
Hoàn thành khi: Chạy bằng
python(hoặcuv run); nhập đáp án ra đúng điểm N/đúng; gõ chữ không làm sập. - 2
Sổ việc nhớ được
Viết app Sổ việc: thêm việc, đánh dấu xong, lưu vào
todo.json; mở lại thấy còn nguyên.Hoàn thành khi:
json.dump/json.loadhoạt động; thoát rồi mở lại, danh sách việc vẫn còn. - 3
Đếm từ
Viết app Phân tích văn bản: nhập một đoạn, in mỗi từ xuất hiện mấy lần và số từ khác nhau.
Hoàn thành khi: Dùng
split+dict.getđể đếm;len(set(...))cho số từ khác nhau. - 4
Từ dài nhất
Bổ sung app đếm từ: in TỪ DÀI NHẤT (dùng
maxvớikey=len) và các từ > 3 ký tự (comprehension).Hoàn thành khi:
max(tu, key=len)ra từ dài nhất;[t for t in tu if len(t) > 3]lọc đúng. - 5
Khung chung
Chọn một dự án ở Bước 1 và viết ra đâu là Dữ liệu, đâu là Xử lý, đâu là Nhập-Xuất.
Hoàn thành khi: Chỉ rõ ba phần - đúng khuôn list/dict → vòng lặp/hàm →
print/input/file. - 6
Lên GitHub
Đưa một dự án lên GitHub kèm README ghi cách chạy.
Hoàn thành khi: Repo có mã nguồn + README (vd “uv run main.py”). Sản phẩm Python đầu tay của bạn.