M17 — Dự án tổng kết

← 16 - Python kết nối Database | Quay lại Bắt đầu

Mục tiêu module

Xây dựng một ứng dụng hoàn chỉnh từ đầu tới cuối, tổng hợp toàn bộ 16 module đã học. Đây là bằng chứng cho thấy bạn đã nắm được nền tảng lập trình.

Thời lượng: ~8 giờ | Tuần: 26


1. Đề bài: Sổ Thu Chi Cá Nhân

1.1. Mô tả

Xây dựng ứng dụng dòng lệnh quản lý thu chi cá nhân, lưu dữ liệu vào SQLite.

1.2. Yêu cầu chức năng

#Chức năngMô tả
1Thêm giao dịchNgày, loại (Thu/Chi), danh mục, số tiền, ghi chú
2Xem danh sáchCó phân trang, lọc theo tháng / loại / danh mục
3Sửa giao dịchSửa theo ID
4Xóa giao dịchCó xác nhận trước khi xóa
5Quản lý danh mụcThêm/sửa/xóa danh mục thu, chi
6Báo cáo thángTổng thu, tổng chi, số dư, chi tiết theo danh mục
7Báo cáo nămBảng 12 tháng, biểu đồ cột bằng ký tự
8Xuất CSVXuất dữ liệu ra file Excel đọc được
9Sao lưu / phục hồiXuất/nhập JSON

1.3. Yêu cầu kỹ thuật

  • Chia thành ít nhất 4 module (.py riêng)
  • Dùng class cho ít nhất 2 thành phần (@dataclass cho model, class cho tầng lưu trữ)
  • Dùng SQLite với parameterized query 100%
  • Dùng Decimal cho mọi số tiền
  • Dùng date / datetime cho ngày tháng
  • Xử lý lỗi đầy đủ — chương trình không bao giờ crash
  • Mọi hàm có docstring
  • Tên biến/hàm theo PEP 8
  • Có requirements.txt, .gitignore, README.md
  • Chạy trong môi trường ảo

2. Cấu trúc dự án đề xuất

so_thu_chi/
├── .venv/
├── .gitignore
├── README.md
├── requirements.txt
├── main.py                  <- Điểm khởi chạy, menu
├── cau_hinh.py              <- Hằng số, đường dẫn
├── models.py                <- @dataclass: GiaoDich, DanhMuc
├── kho_du_lieu.py           <- Tầng database: CRUD
├── nghiep_vu.py             <- Logic tính toán, báo cáo
├── giao_dien.py             <- Hàm in ấn, nhập liệu
├── tien_ich.py              <- Hàm dùng chung
└── du_lieu/
    └── so_thu_chi.db

Sơ đồ phụ thuộc giữa các module

graph TD
    A[main.py] --> B[giao_dien.py]
    A --> C[nghiep_vu.py]
    B --> D[tien_ich.py]
    C --> E[kho_du_lieu.py]
    C --> F[models.py]
    E --> F
    E --> G[cau_hinh.py]
    C --> G
    B --> G

Nguyên tắc phân tầng

Mũi tên chỉ chiều phụ thuộc. kho_du_lieu.py không được import giao_dien.py — tầng dưới không biết gì về tầng trên. Đây là nguyên tắc kiến trúc phần mềm cơ bản, bạn đã gặp trong các hệ thống ERP: tầng Data Access, tầng Business Logic, tầng Presentation.


3. Code khởi đầu

Dưới đây là bộ khung để bạn bắt đầu. Không copy toàn bộ — hãy gõ lại và tự hoàn thiện các phần TODO.

cau_hinh.py

"""Cấu hình và hằng số toàn hệ thống."""
 
from decimal import Decimal
from pathlib import Path
 
# Đường dẫn
THU_MUC_GOC = Path(__file__).parent
THU_MUC_DU_LIEU = THU_MUC_GOC / "du_lieu"
DUONG_DAN_DB = THU_MUC_DU_LIEU / "so_thu_chi.db"
THU_MUC_XUAT = THU_MUC_GOC / "xuat"
 
# Đảm bảo thư mục tồn tại
THU_MUC_DU_LIEU.mkdir(exist_ok=True)
THU_MUC_XUAT.mkdir(exist_ok=True)
 
# Hiển thị
DO_RONG_BANG = 80
SO_DONG_MOI_TRANG = 15
 
# Nghiệp vụ
LOAI_THU = "THU"
LOAI_CHI = "CHI"
CAC_LOAI = (LOAI_THU, LOAI_CHI)
 
SO_TIEN_TOI_DA = Decimal("999999999999")
 
DANH_MUC_MAC_DINH = [
    (LOAI_THU, "Luong"),
    (LOAI_THU, "Thuong"),
    (LOAI_THU, "Ban hang"),
    (LOAI_THU, "Khac"),
    (LOAI_CHI, "An uong"),
    (LOAI_CHI, "Di lai"),
    (LOAI_CHI, "Nha o"),
    (LOAI_CHI, "Y te"),
    (LOAI_CHI, "Giao duc"),
    (LOAI_CHI, "Giai tri"),
    (LOAI_CHI, "Khac"),
]
 
TEN_THANG = {
    1: "Thang 01", 2: "Thang 02", 3: "Thang 03", 4: "Thang 04",
    5: "Thang 05", 6: "Thang 06", 7: "Thang 07", 8: "Thang 08",
    9: "Thang 09", 10: "Thang 10", 11: "Thang 11", 12: "Thang 12",
}

models.py

"""Các model dữ liệu."""
 
from dataclasses import dataclass, field
from datetime import date
from decimal import Decimal
 
import cau_hinh
 
 
@dataclass
class GiaoDich:
    """Một giao dịch thu hoặc chi."""
 
    ngay: date
    loai: str
    danh_muc: str
    so_tien: Decimal
    ghi_chu: str = ""
    id: int | None = None
 
    def __post_init__(self):
        """Kiểm tra dữ liệu ngay sau khi khởi tạo."""
        if self.loai not in cau_hinh.CAC_LOAI:
            raise ValueError(
                f"Loai phai la mot trong {cau_hinh.CAC_LOAI}, nhan duoc '{self.loai}'"
            )
        if self.so_tien <= 0:
            raise ValueError(f"So tien phai lon hon 0, nhan duoc {self.so_tien}")
        if self.so_tien > cau_hinh.SO_TIEN_TOI_DA:
            raise ValueError(f"So tien vuot gioi han cho phep")
        if not self.danh_muc or not self.danh_muc.strip():
            raise ValueError("Danh muc khong duoc de trong")
 
    @property
    def la_thu(self):
        """Giao dịch này có phải khoản thu không."""
        return self.loai == cau_hinh.LOAI_THU
 
    @property
    def so_tien_co_dau(self):
        """Số tiền có dấu: dương nếu thu, âm nếu chi."""
        return self.so_tien if self.la_thu else -self.so_tien
 
    def __str__(self):
        dau = "+" if self.la_thu else "-"
        return f"[{self.ngay:%d/%m/%Y}] {dau}{self.so_tien:,.0f} - {self.danh_muc}"
 
 
@dataclass(frozen=True)
class DanhMuc:
    """Danh mục thu/chi."""
 
    loai: str
    ten: str
 
    def __str__(self):
        return f"{self.ten} ({self.loai})"
 
 
@dataclass
class BaoCaoThang:
    """Kết quả báo cáo một tháng."""
 
    nam: int
    thang: int
    tong_thu: Decimal = Decimal("0")
    tong_chi: Decimal = Decimal("0")
    theo_danh_muc: dict = field(default_factory=dict)
    so_giao_dich: int = 0
 
    @property
    def so_du(self):
        """Chênh lệch thu - chi."""
        return self.tong_thu - self.tong_chi
 
    @property
    def ty_le_tiet_kiem(self):
        """Tỷ lệ tiết kiệm trên tổng thu (%)."""
        if self.tong_thu == 0:
            return Decimal("0")
        return self.so_du / self.tong_thu * 100

kho_du_lieu.py (khung — bạn hoàn thiện)

"""Tầng truy cập dữ liệu — mọi thao tác với database nằm ở đây."""
 
import sqlite3
from contextlib import contextmanager
from datetime import date
from decimal import Decimal
 
import cau_hinh
from models import DanhMuc, GiaoDich
 
 
@contextmanager
def ket_noi():
    """Context manager quản lý kết nối SQLite."""
    conn = sqlite3.connect(cau_hinh.DUONG_DAN_DB)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA foreign_keys = ON")
    try:
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()
 
 
def khoi_tao():
    """Tạo bảng và nạp danh mục mặc định."""
    with ket_noi() as conn:
        conn.execute("""
            CREATE TABLE IF NOT EXISTS DanhMuc (
                Loai TEXT NOT NULL,
                Ten  TEXT NOT NULL,
                PRIMARY KEY (Loai, Ten)
            )
        """)
        conn.execute("""
            CREATE TABLE IF NOT EXISTS GiaoDich (
                Id       INTEGER PRIMARY KEY AUTOINCREMENT,
                Ngay     TEXT NOT NULL,
                Loai     TEXT NOT NULL,
                DanhMuc  TEXT NOT NULL,
                SoTien   TEXT NOT NULL,
                GhiChu   TEXT DEFAULT '',
                FOREIGN KEY (Loai, DanhMuc) REFERENCES DanhMuc(Loai, Ten)
            )
        """)
        conn.execute("CREATE INDEX IF NOT EXISTS idx_gd_ngay ON GiaoDich(Ngay)")
        conn.execute("CREATE INDEX IF NOT EXISTS idx_gd_loai ON GiaoDich(Loai)")
 
        # Nạp danh mục mặc định nếu bảng rỗng
        co = conn.execute("SELECT COUNT(*) FROM DanhMuc").fetchone()[0]
        if co == 0:
            conn.executemany(
                "INSERT INTO DanhMuc (Loai, Ten) VALUES (?, ?)",
                cau_hinh.DANH_MUC_MAC_DINH
            )
 
 
def _tu_row(row):
    """Chuyển sqlite3.Row thành GiaoDich."""
    return GiaoDich(
        id=row["Id"],
        ngay=date.fromisoformat(row["Ngay"]),
        loai=row["Loai"],
        danh_muc=row["DanhMuc"],
        so_tien=Decimal(row["SoTien"]),
        ghi_chu=row["GhiChu"] or "",
    )
 
 
# ---------- GIAO DỊCH ----------
 
def them(gd: GiaoDich) -> int:
    """Thêm giao dịch, trả về Id vừa tạo."""
    with ket_noi() as conn:
        cur = conn.execute(
            "INSERT INTO GiaoDich (Ngay, Loai, DanhMuc, SoTien, GhiChu) "
            "VALUES (?, ?, ?, ?, ?)",
            (gd.ngay.isoformat(), gd.loai, gd.danh_muc, str(gd.so_tien), gd.ghi_chu)
        )
        return cur.lastrowid
 
 
def lay_theo_id(id_gd: int) -> GiaoDich | None:
    """Lấy một giao dịch theo Id."""
    with ket_noi() as conn:
        row = conn.execute("SELECT * FROM GiaoDich WHERE Id = ?", (id_gd,)).fetchone()
        return _tu_row(row) if row else None
 
 
def loc(nam=None, thang=None, loai=None, danh_muc=None) -> list[GiaoDich]:
    """
    Lọc giao dịch theo nhiều tiêu chí.
 
    Mọi tham số là tùy chọn — bỏ qua nghĩa là không lọc theo tiêu chí đó.
    """
    sql = "SELECT * FROM GiaoDich WHERE 1=1"
    tham_so = []
 
    if nam is not None:
        sql += " AND strftime('%Y', Ngay) = ?"
        tham_so.append(f"{nam:04d}")
    if thang is not None:
        sql += " AND strftime('%m', Ngay) = ?"
        tham_so.append(f"{thang:02d}")
    if loai is not None:
        sql += " AND Loai = ?"
        tham_so.append(loai)
    if danh_muc is not None:
        sql += " AND DanhMuc = ?"
        tham_so.append(danh_muc)
 
    sql += " ORDER BY Ngay DESC, Id DESC"
 
    with ket_noi() as conn:
        return [_tu_row(r) for r in conn.execute(sql, tham_so).fetchall()]
 
 
def cap_nhat(gd: GiaoDich) -> bool:
    """Cập nhật giao dịch. TODO: bạn tự hoàn thiện."""
    # TODO
    raise NotImplementedError
 
 
def xoa(id_gd: int) -> bool:
    """Xóa giao dịch theo Id. TODO: bạn tự hoàn thiện."""
    # TODO
    raise NotImplementedError
 
 
# ---------- DANH MỤC ----------
 
def lay_danh_muc(loai=None) -> list[DanhMuc]:
    """Lấy danh sách danh mục, lọc theo loại nếu có."""
    sql = "SELECT Loai, Ten FROM DanhMuc"
    tham_so = ()
    if loai:
        sql += " WHERE Loai = ?"
        tham_so = (loai,)
    sql += " ORDER BY Loai, Ten"
 
    with ket_noi() as conn:
        return [DanhMuc(r["Loai"], r["Ten"]) for r in conn.execute(sql, tham_so)]
 
 
def them_danh_muc(dm: DanhMuc):
    """Thêm danh mục mới. TODO: xử lý trùng lặp."""
    # TODO
    raise NotImplementedError

main.py (khung)

"""Sổ thu chi cá nhân — chương trình chính."""
 
import sqlite3
 
import cau_hinh
import giao_dien
import kho_du_lieu
import nghiep_vu
 
 
def menu_chinh():
    """Vòng lặp menu chính."""
    while True:
        giao_dien.in_menu_chinh()
        chon = input("Chon chuc nang: ").strip()
 
        try:
            if chon == "1":
                giao_dien.man_hinh_them_giao_dich()
            elif chon == "2":
                giao_dien.man_hinh_danh_sach()
            elif chon == "3":
                giao_dien.man_hinh_sua()
            elif chon == "4":
                giao_dien.man_hinh_xoa()
            elif chon == "5":
                giao_dien.man_hinh_danh_muc()
            elif chon == "6":
                giao_dien.man_hinh_bao_cao_thang()
            elif chon == "7":
                giao_dien.man_hinh_bao_cao_nam()
            elif chon == "8":
                giao_dien.man_hinh_xuat_csv()
            elif chon == "9":
                giao_dien.man_hinh_sao_luu()
            elif chon == "0":
                print("\nTam biet!")
                break
            else:
                print("Lua chon khong hop le")
 
        except ValueError as e:
            print(f"\n  ! Loi du lieu: {e}")
        except sqlite3.Error as e:
            print(f"\n  ! Loi database: {e}")
        except KeyboardInterrupt:
            print("\n  ! Da huy thao tac")
        except Exception as e:
            print(f"\n  ! Loi khong xac dinh: {type(e).__name__}: {e}")
 
 
def main():
    """Điểm khởi chạy."""
    print("Dang khoi tao...")
    kho_du_lieu.khoi_tao()
    menu_chinh()
 
 
if __name__ == "__main__":
    main()

4. Gợi ý cho các phần khó

4.1. Biểu đồ cột bằng ký tự

def ve_bieu_do_cot(du_lieu, do_rong_toi_da=40):
    """
    Vẽ biểu đồ cột ngang bằng ký tự.
 
    Tham số:
        du_lieu (dict): {nhãn: giá trị}
        do_rong_toi_da (int): Số ký tự tối đa của cột dài nhất.
    """
    if not du_lieu:
        print("  (Khong co du lieu)")
        return
 
    lon_nhat = max(du_lieu.values())
    if lon_nhat == 0:
        print("  (Tat ca gia tri bang 0)")
        return
 
    do_dai_nhan = max(len(str(k)) for k in du_lieu)
 
    for nhan, gia_tri in du_lieu.items():
        do_dai = int(gia_tri / lon_nhat * do_rong_toi_da)
        cot = "█" * do_dai
        print(f"  {str(nhan):<{do_dai_nhan}} │{cot} {gia_tri:,.0f}")
 
 
# Sử dụng
ve_bieu_do_cot({
    "An uong":  Decimal("4500000"),
    "Di lai":   Decimal("1200000"),
    "Nha o":    Decimal("8000000"),
    "Giai tri": Decimal("2000000"),
})
  An uong  │██████████████████████ 4,500,000
  Di lai   │██████ 1,200,000
  Nha o    │████████████████████████████████████████ 8,000,000
  Giai tri │██████████ 2,000,000

4.2. Phân trang

def in_co_phan_trang(danh_sach, so_dong_moi_trang=15, ham_in_dong=None):
    """In danh sách theo trang, chờ người dùng nhấn Enter."""
    tong = len(danh_sach)
    if tong == 0:
        print("  (Khong co du lieu)")
        return
 
    so_trang = (tong + so_dong_moi_trang - 1) // so_dong_moi_trang
 
    for trang in range(so_trang):
        dau = trang * so_dong_moi_trang
        cuoi = min(dau + so_dong_moi_trang, tong)
 
        for muc in danh_sach[dau:cuoi]:
            if ham_in_dong:
                ham_in_dong(muc)
            else:
                print(f"  {muc}")
 
        print(f"\n  --- Trang {trang + 1}/{so_trang} "
              f"(dong {dau + 1}-{cuoi}/{tong}) ---")
 
        if trang < so_trang - 1:
            tiep = input("  Enter de xem tiep, 'q' de thoat: ").strip().lower()
            if tiep == "q":
                break
            print()

4.3. Nhập ngày an toàn

from datetime import date, datetime
 
 
def nhap_ngay(thong_bao, mac_dinh_hom_nay=True):
    """
    Nhập ngày theo định dạng dd/mm/yyyy.
 
    Nhấn Enter để dùng ngày hôm nay (nếu mac_dinh_hom_nay=True).
    """
    goi_y = " (Enter = hom nay)" if mac_dinh_hom_nay else ""
    while True:
        nhap = input(f"{thong_bao} [dd/mm/yyyy]{goi_y}: ").strip()
 
        if not nhap and mac_dinh_hom_nay:
            return date.today()
 
        for mau in ("%d/%m/%Y", "%d-%m-%Y", "%Y-%m-%d", "%d/%m/%y"):
            try:
                return datetime.strptime(nhap, mau).date()
            except ValueError:
                continue
 
        print("  ! Dinh dang khong hop le. Vi du: 08/08/2026")

4.4. Nhập số tiền an toàn

from decimal import Decimal, InvalidOperation
 
 
def nhap_so_tien(thong_bao, toi_thieu=Decimal("0.01")):
    """Nhập số tiền, chấp nhận dấu chấm/phẩy phân cách hàng nghìn."""
    while True:
        nhap = input(f"{thong_bao}: ").strip()
 
        if not nhap:
            print("  ! Khong duoc de trong")
            continue
 
        # Bỏ dấu phân cách hàng nghìn
        sach = nhap.replace(",", "").replace(".", "").replace(" ", "")
 
        try:
            gia_tri = Decimal(sach)
        except InvalidOperation:
            print("  ! Vui long nhap so. Vi du: 1500000 hoac 1.500.000")
            continue
 
        if gia_tri < toi_thieu:
            print(f"  ! So tien phai tu {toi_thieu} tro len")
            continue
 
        return gia_tri

4.5. Chọn từ danh sách

def chon_tu_danh_sach(thong_bao, cac_muc, hien_thi=str):
    """
    Cho người dùng chọn một mục từ danh sách bằng số thứ tự.
 
    Trả về mục được chọn, hoặc None nếu người dùng hủy.
    """
    if not cac_muc:
        print("  ! Danh sach rong")
        return None
 
    print(f"\n{thong_bao}")
    for i, muc in enumerate(cac_muc, start=1):
        print(f"  {i:>2}. {hien_thi(muc)}")
    print("   0. Huy")
 
    while True:
        nhap = input("Chon: ").strip()
        if not nhap.isdigit():
            print("  ! Vui long nhap so")
            continue
 
        chon = int(nhap)
        if chon == 0:
            return None
        if 1 <= chon <= len(cac_muc):
            return cac_muc[chon - 1]
        print(f"  ! Vui long chon tu 0 den {len(cac_muc)}")

5. Lộ trình 8 giờ

GiờViệc
1Dựng cấu trúc thư mục, .venv, cau_hinh.py, models.py
2kho_du_lieu.py — khởi tạo DB, hàm them, loc, lay_theo_id
3kho_du_lieu.py — hoàn thiện cap_nhat, xoa, phần danh mục
4tien_ich.py + giao_dien.py — các hàm nhập liệu an toàn
5main.py + menu + chức năng 1, 2 (thêm, xem)
6Chức năng 3, 4, 5 (sửa, xóa, danh mục)
7nghiep_vu.py — báo cáo tháng, năm, biểu đồ
8Xuất CSV, sao lưu JSON, README.md, kiểm thử toàn diện

6. Checklist nghiệm thu

Chức năng

  • Thêm được giao dịch thu và chi
  • Xem được danh sách, có phân trang
  • Lọc được theo tháng, loại, danh mục
  • Sửa được giao dịch
  • Xóa được (có hỏi xác nhận)
  • Quản lý được danh mục
  • Báo cáo tháng hiển thị đúng tổng thu, chi, số dư
  • Báo cáo năm hiển thị 12 tháng
  • Có biểu đồ cột
  • Xuất CSV mở được bằng Excel, tiếng Việt hiển thị đúng
  • Sao lưu/phục hồi JSON hoạt động

Kỹ thuật

  • Chia thành ít nhất 4 module
  • Có ít nhất 2 class/dataclass
  • Mọi câu SQL dùng parameterized query
  • Mọi số tiền dùng Decimal
  • Mọi hàm có docstring
  • Tên biến/hàm theo snake_case
  • Có requirements.txt, .gitignore, README.md

Kiểm thử phá hoại (BẮT BUỘC làm)

Thử làm hỏng chương trình bằng mọi cách. Nó phải không sập:

  • Nhập chữ vào ô số tiền
  • Nhập số âm
  • Nhập số cực lớn (999999999999999)
  • Nhập ngày 32/13/2026
  • Để trống mọi ô, nhấn Enter liên tục
  • Nhấn Ctrl + C giữa chừng
  • Nhập ID không tồn tại khi sửa/xóa
  • Nhập ký tự đặc biệt '; DROP TABLE GiaoDich; --
  • Xóa file database khi chương trình đang chạy
  • Nhập tiếng Việt có dấu vào mọi ô văn bản

7. Đề bài thay thế

Nếu sổ thu chi không hấp dẫn, chọn một trong các đề sau — yêu cầu kỹ thuật giữ nguyên:

ĐềMô tả
Quản lý kho hàngNhập/xuất kho, tồn kho, cảnh báo hết hàng, báo cáo xuất nhập tồn
Sổ công nợKhách hàng, hóa đơn, thanh toán, báo cáo tuổi nợ
Quản lý tài sản cố địnhTài sản, khấu hao theo đường thẳng, báo cáo giá trị còn lại
Chấm công và tính lươngNhân viên, chấm công, tính lương, bảo hiểm, thuế TNCN
Đối chiếu dữ liệuĐọc 2 file CSV, đối chiếu, báo cáo chênh lệch (dùng set ở 09 - Dict và Set)

8. Sau khi hoàn thành

8.1. Tự đánh giá

Viết vào Nhật ký học tập - Template:

  1. Phần nào khó nhất? Tại sao?
  2. Kiến thức module nào bạn dùng nhiều nhất?
  3. Kiến thức module nào bạn thấy chưa vững, cần ôn lại?
  4. Nếu làm lại từ đầu, bạn sẽ làm khác gì?
  5. Bạn mất bao lâu thực tế so với 8 giờ dự kiến?

8.2. Bước tiếp theo

Bạn đã hoàn thành nền tảng lập trình Python. Giờ chọn một hướng đi:

HướngNội dung cần họcPhù hợp nếu
Xử lý dữ liệupandas, openpyxl, numpyMuốn tự động hóa báo cáo Excel
Tích hợp hệ thốngrequests, REST API, SQLAlchemyMuốn nối ERP với hệ thống khác
Chất lượng codepytest, type hints, ruff, GitMuốn làm phần mềm nghiêm túc
WebFastAPI, HTML/CSS cơ bảnMuốn làm ứng dụng web
Giao diện desktoptkinter, PySide6Muốn làm tool có giao diện

Lời khuyên

Chọn một hướng, không làm nhiều thứ cùng lúc. Với quỹ thời gian 5 giờ/tuần, dàn trải sẽ khiến bạn không sâu ở đâu cả.

Với công việc ERP-VN của bạn, tôi gợi ý thứ tự: Git → pandas/openpyxl → SQLAlchemy → API. Git trước vì nó là công cụ nền, dùng cho mọi thứ về sau.

8.3. Duy trì

Kiến thức lập trình mai một nhanh nếu không dùng. Cách duy trì:

  • Mỗi tuần viết một script nhỏ giải quyết một việc lặp lại trong công việc
  • Đọc lại notebook này mỗi 3 tháng, cập nhật bổ sung những gì học thêm
  • Tham gia cộng đồng: đọc câu hỏi người khác, thử tự trả lời

9. Tài liệu

NguồnNội dungLink
The Python TutorialToàn bộ hướng dẫn chính thứchttps://docs.python.org/3/tutorial/
Python HOWTOsCác hướng dẫn chuyên đềhttps://docs.python.org/3/howto/
Python Standard LibraryThư viện chuẩnhttps://docs.python.org/3/library/
PEP IndexToàn bộ đề xuất cải tiến Pythonhttps://peps.python.org/
Python GlossaryTừ điển thuật ngữ chính thứchttps://docs.python.org/3/glossary.html

Chúc mừng bạn đã hoàn thành lộ trình 26 tuần!

← Quay lại Bắt đầu