Class & Object
— Khuôn mẫu & Thực thể
Cách Python tổ chức code theo mô hình "thế giới thực" — mọi thứ đều là đối tượng!
Lập trình Hướng đối tượng — Nhìn code như thế giới thực
Cho đến nay bạn đã viết code theo kiểu tuần tự — từng dòng chạy từ trên xuống. OOP là một cách tư duy khác: bạn mô hình hoá code thành các đối tượng giống như thế giới xung quanh!
- Code chạy từng dòng từ trên xuống
- Dữ liệu và hành động tách rời nhau
- Khó mở rộng khi code lớn dần
- Phù hợp bài toán nhỏ, đơn giản
- Code tổ chức thành các đối tượng độc lập
- Dữ liệu và hành động gói trong một nơi
- Dễ mở rộng, tái sử dụng, bảo trì
- Phù hợp hệ thống lớn, phức tạp
Class — Bản thiết kế (Blueprint)
Một Class là khuôn mẫu, bản thiết kế để tạo ra các đối tượng. Class không phải là đối tượng thật — nó chỉ mô tả đối tượng đó sẽ có gì và làm được gì.
Khai báo Class đầu tiên
Dùng từ khoá class để khai báo. Tên Class luôn viết PascalCase (chữ cái đầu mỗi từ viết hoa):
# Khai báo class đơn giản nhất class HocSinh: """Đây là class mô tả học sinh.""" pass # pass = tạm thời để trống # Tạo object từ class (gọi là instantiation) hoc_sinh_1 = HocSinh() hoc_sinh_2 = HocSinh() # Kiểm tra loại object print(type(hoc_sinh_1)) print(hoc_sinh_1 is hoc_sinh_2) # Cùng class nhưng là 2 object khác nhau!
False
HocSinh ✅ hoc_sinh ❌ hocsinh ❌Biến và hàm dùng snake_case — Class dùng PascalCase để phân biệt!
Phương thức __init__ — "Sinh ra với gì?"
Khi tạo một object, Python tự động gọi hàm đặc biệt __init__. Đây là nơi bạn thiết lập thuộc tính ban đầu cho object.
__init__ cũng vậy — mỗi khi tạo object HocSinh, bạn phải cung cấp đủ thông tin ban đầu!
class HocSinh: def __init__(self, ten, tuoi, lop): # self.thuoc_tinh = gia_tri self.ten = ten self.tuoi = tuoi self.lop = lop # Tạo object — truyền đúng thứ tự tham số nam = HocSinh("Nguyễn Văn Nam", 13, "8A") lan = HocSinh("Trần Thị Lan", 14, "8B") # Truy cập thuộc tính bằng dấu chấm (.) print(nam.ten) print(lan.tuoi) print(nam.lop)
14
8A
self là từ khoá đặc biệt, đại diện cho chính object đó. Khi bạn viết nam.ten, Python dịch thành HocSinh.ten(nam) — self chính là nam lúc này!
Giải phẫu hàm __init__
| Thành phần | Ví dụ | Ý nghĩa |
|---|---|---|
| def __init__ | def __init__(self, ten, tuoi) | Khai báo hàm khởi tạo — tự động gọi khi tạo object |
| self | self | Tham số đầu tiên bắt buộc — đại diện cho object hiện tại |
| ten, tuoi | "Nam", 13 | Tham số bạn truyền vào khi tạo object: HocSinh("Nam", 13) |
| self.ten | self.ten = ten | Thuộc tính của object — lưu lại giá trị để dùng về sau |
# Bạn có thể đặt giá trị mặc định cho tham số class HocSinh: def __init__(self, ten, tuoi, lop="Chưa xếp lớp"): self.ten = ten self.tuoi = tuoi self.lop = lop self.diem = [] # thuộc tính tính toán — luôn bắt đầu rỗng moi = HocSinh("Bình", 12) # không cần truyền lop print(moi.lop) print(moi.diem)
[]
Đọc và ghi thuộc tính bằng dấu chấm (.)
Sau khi tạo object, bạn dùng dấu chấm để truy cập hoặc thay đổi bất kỳ thuộc tính nào:
class XeHoi: def __init__(self, hang_xe, mau, nam_san_xuat): self.hang_xe = hang_xe self.mau = mau self.nam_san_xuat = nam_san_xuat self.toc_do_hien_tai = 0 # luôn khởi đầu bằng 0 xe1 = XeHoi("Toyota", "Đỏ", 2023) # Đọc thuộc tính print(f"Xe: {xe1.hang_xe} — Màu: {xe1.mau}") print(f"Tốc độ hiện tại: {xe1.toc_do_hien_tai} km/h") # Thay đổi thuộc tính xe1.mau = "Xanh" xe1.toc_do_hien_tai = 80 print(f"Màu mới: {xe1.mau}") print(f"Tốc độ mới: {xe1.toc_do_hien_tai} km/h")
Tốc độ hiện tại: 0 km/h
Màu mới: Xanh
Tốc độ mới: 80 km/h
Tạo nhiều objects — Mỗi object độc lập!
Điều kỳ diệu của Class: mỗi object được tạo ra là hoàn toàn độc lập — thay đổi object này không ảnh hưởng object kia:
class HocSinh: def __init__(self, ten, tuoi): self.ten = ten self.tuoi = tuoi self.diem = 0 # Tạo danh sách học sinh lop = [ HocSinh("Nam", 13), HocSinh("Lan", 14), HocSinh("Bình", 13), ] # Gán điểm riêng cho từng học sinh lop[0].diem = 8.5 lop[1].diem = 9.0 lop[2].diem = 7.0 # Duyệt toàn bộ lớp for hs in lop: print(f" {hs.ten:8} | {hs.tuoi} tuổi | Điểm: {hs.diem}")
Lan | 14 tuổi | Điểm: 9.0
Bình | 13 tuổi | Điểm: 7.0
Thực hành — Tạo Class SachGiao Khoa
Hãy tự tay viết Class mô tả một cuốn sách giáo khoa. Kết quả in ra phải đúng như mẫu:
# ── BÀI TẬP ────────────────────────────── # Tạo class SachGiaoKhoa với các thuộc tính: # ten_sach, mon_hoc, lop, nxb, so_trang # ───────────────────────────────────────── class SachGiaoKhoa: def __init__(self, ten_sach, mon_hoc, lop, nxb, so_trang): self.ten_sach = ten_sach self.mon_hoc = mon_hoc self.lop = lop self.nxb = nxb self.so_trang = so_trang self.da_doc = False # mặc định chưa đọc # Tạo các đối tượng sách toan8 = SachGiaoKhoa("Toán 8", "Toán", "8", "NXB GD", 180) van8 = SachGiaoKhoa("Ngữ Văn 8", "Văn", "8", "NXB GD", 210) python3 = SachGiaoKhoa("Python 101","Tin học","8", "NXB TH", 156) # Đánh dấu đã đọc Toán 8 toan8.da_doc = True # In thông tin tất cả sách tu_sach = [toan8, van8, python3] print("📚 TỦ SÁCH CỦA TÔI") print("─" * 38) for sach in tu_sach: trang_thai = "✅ Đã đọc" if sach.da_doc else "📖 Chưa đọc" print(f"{sach.ten_sach:15} | {sach.so_trang} tr | {trang_thai}")
──────────────────────────────────────
Toán 8 | 180 tr | ✅ Đã đọc
Ngữ Văn 8 | 210 tr | 📖 Chưa đọc
Python 101 | 156 tr | 📖 Chưa đọc
gia_tien (float), rồi tính tổng tiền tủ sách. Gợi ý: dùng sum(s.gia_tien for s in tu_sach).
🧩 Kiểm tra nhanh!
Ôn lại kiến thức Chapter 1 OOP — bạn nhớ được bao nhiêu?
→ Class = bản thiết kế, Object = thực thể được tạo ra từ class
→ __init__(self, ...)
self trong hàm __init__ là gì?→ Đại diện cho chính object đang được tạo
→ PascalCase — chữ cái đầu mỗi từ viết hoa