Bài 12: Lập trình hướng đối tượng cơ bản (class) trong Python

Bài 11 bạn đã dùng module để tổ chức code. Bài này bước sang một cách tư duy mới: lập trình hướng đối tượng (OOP) — gói dữ liệu và hành vi liên quan vào cùng một chỗ gọi là class. Nghe học thuật nhưng ý tưởng rất đời thường: mô tả một “sự vật” (tài khoản, sản phẩm, chiếc xe) bằng những gì nó có và những gì nó làm được. Đây là nền tảng của hầu hết phần mềm lớn.
⏱️ Cách học bài này (~30 phút): đọc khái niệm class/đối tượng (12’), tự gõ và chạy ví dụ + bài tập (13’), tự kiểm + lưu code mang về (5’).
Mục tiêu bài học
Sau bài này bạn sẽ:
- Hiểu class (khuôn mẫu) và đối tượng (bản thể cụ thể).
- Viết
__init__để gán thuộc tính ban đầu. - Thêm phương thức (hành vi) cho class.
- Tạo và dùng nhiều đối tượng từ một class.
Nội dung: class và đối tượng
1. Class là “khuôn”, đối tượng là “bản thể”
Hình dung: class TaiKhoan là khuôn mẫu mô tả một tài khoản gồm tên chủ và số dư. Từ khuôn đó, mỗi người dùng thật là một đối tượng riêng.
class TaiKhoan:
def __init__(self, ten, so_du):
self.ten = ten # thuộc tính: dữ liệu của đối tượng
self.so_du = so_du
tk1 = TaiKhoan("Lan", 100) # tạo một đối tượng
print(tk1.ten, tk1.so_du) # Lan 100
__init__tự chạy khi tạo đối tượng, gán dữ liệu ban đầu.selflà chính đối tượng đang thao tác — nhờ nó mỗi đối tượng giữ dữ liệu riêng.
2. Thêm phương thức (hành vi)
Phương thức là hàm nằm trong class, mô tả việc đối tượng làm được:
class TaiKhoan:
def __init__(self, ten, so_du):
self.ten = ten
self.so_du = so_du
def nap(self, tien):
self.so_du += tien # đổi dữ liệu của chính đối tượng
def xem(self):
print(f"{self.ten}: {self.so_du}đ")
tk1 = TaiKhoan("Lan", 100)
tk1.nap(50) # gọi phương thức
tk1.xem() # Lan: 150đ
Mọi phương thức đều nhận self làm tham số đầu tiên để biết đang làm việc với đối tượng nào.
3. Một class, nhiều đối tượng
tk1 = TaiKhoan("Lan", 100)
tk2 = TaiKhoan("Nam", 0)
tk1.nap(50)
tk2.nap(200)
tk1.xem() # Lan: 150đ
tk2.xem() # Nam: 200đ
Hai đối tượng dùng chung hành vi (nap, xem) nhưng dữ liệu riêng — đó là sức mạnh của class.
Code mẫu có chú thích: quản lý sản phẩm
class SanPham:
def __init__(self, ten, gia, so_luong):
self.ten = ten
self.gia = gia
self.so_luong = so_luong
def tong_tien(self): # phương thức tính toán
return self.gia * self.so_luong
def mo_ta(self):
print(f"{self.ten}: {self.so_luong} cái, tổng {self.tong_tien()}đ")
sp = SanPham("Bút bi", 5000, 10)
sp.mo_ta() # Bút bi: 10 cái, tổng 50000đ
Mấu chốt: gói dữ liệu (ten, gia, so_luong) và hành vi (tong_tien, mo_ta) vào một chỗ — gọn và rõ.
Bài thực hành code (tự gõ)
Bài 1 — Class đơn giản: tạo class HocSinh với thuộc tính ten và diem; in ra bằng câu lệnh print.
Bài 2 — Thêm phương thức: thêm phương thức xep_loai() trả về “Giỏi” nếu diem >= 8, ngược lại “Khá”.
Bài 3 — Nhiều đối tượng: tạo 2 học sinh, gọi xep_loai() cho từng người và in kết quả.
Lỗi thường gặp & cách sửa
- Quên
selftrong định nghĩa phương thức (def nap(tien):) → lỗi khi gọi. Luôn đểselflà tham số đầu tiên. - Quên
self.khi truy cập thuộc tính (so_du += tienthay vìself.so_du += tien) → Python báo biến chưa định nghĩa. - Nhầm class với đối tượng →
TaiKhoan.xem()(gọi trên class) sai; phải tạo đối tượngtk1 = TaiKhoan(...)rồitk1.xem(). - Quên
__init__có hai dấu gạch dưới mỗi bên (__init__, không phải_init_).
💾 Mang về — mẫu class cơ bản
# class_mau.py
class NhanVat:
def __init__(self, ten, mau):
self.ten = ten
self.mau = mau # máu (HP)
def bi_danh(self, sat_thuong):
self.mau -= sat_thuong
if self.mau < 0:
self.mau = 0
def con_song(self):
return self.mau > 0
hero = NhanVat("Anh Hùng", 100)
hero.bi_danh(30)
print(hero.mau, "-", "còn sống" if hero.con_song() else "đã ngã") # 70 - còn sống
Thuật ngữ chốt
| Thuật ngữ | Giải thích ngắn |
|---|---|
| class | Khuôn mẫu mô tả một loại sự vật |
| đối tượng (object) | Bản thể cụ thể tạo từ class |
| thuộc tính (attribute) | Dữ liệu của đối tượng (self.ten) |
| phương thức (method) | Hàm nằm trong class (hành vi) |
__init__ |
Phương thức khởi tạo, chạy khi tạo đối tượng |
| self | Chính đối tượng đang thao tác |
Tự kiểm tra & lời giải
__init__chạy khi nào? (Đáp án: tự chạy khi tạo một đối tượng mới)selfđại diện cho gì? (Đáp án: chính đối tượng đang được thao tác)- Từ một class tạo được mấy đối tượng? (Đáp án: bao nhiêu tuỳ ý, mỗi cái dữ liệu riêng)
Lời giải Bài thực hành:
class HocSinh:
def __init__(self, ten, diem):
self.ten = ten
self.diem = diem
def xep_loai(self):
return "Giỏi" if self.diem >= 8 else "Khá"
hs1 = HocSinh("Lan", 9)
hs2 = HocSinh("Nam", 6)
print(hs1.ten, hs1.xep_loai()) # Lan Giỏi
print(hs2.ten, hs2.xep_loai()) # Nam Khá
Ghi nhớ nhanh
- class = khuôn, đối tượng = bản thể; một class tạo nhiều đối tượng.
__init__(self, ...)gán thuộc tính ban đầu;selfgiữ dữ liệu riêng.- Phương thức = hàm trong class, luôn có
selfđầu tiên; gọi bằngdoi_tuong.phuong_thuc().
👉 Bài tập về nhà: tạo class TaiKhoan có thêm phương thức rut(tien) — chỉ cho rút khi đủ số dư, thiếu thì báo “Không đủ số dư” (gợi ý: if tien > self.so_du: thì báo lỗi, ngược lại self.so_du -= tien). Bài tiếp theo trong series: Bài 13 — Cài và dùng thư viện ngoài (pip) (sắp đăng).
Câu hỏi thường gặp
Class và đối tượng (object) trong Python là gì?
Class là ‘khuôn mẫu’ mô tả một loại sự vật gồm dữ liệu (thuộc tính) và hành vi (phương thức); còn đối tượng là một ‘bản thể’ cụ thể tạo ra từ khuôn đó. Ví dụ class ‘ChiecXe’ là khuôn, còn chiếc xe cụ thể của bạn là một đối tượng. Từ một class bạn tạo được nhiều đối tượng, mỗi cái có dữ liệu riêng nhưng dùng chung các hành vi.
Hàm __init__ và self trong class dùng để làm gì?
init là phương thức khởi tạo, tự chạy khi bạn tạo một đối tượng mới, dùng để gán dữ liệu ban đầu. ‘self’ đại diện cho chính đối tượng đang được thao tác, giúp mỗi đối tượng giữ dữ liệu riêng của nó. Mọi phương thức trong class đều nhận self làm tham số đầu tiên để biết nó đang làm việc với đối tượng nào.
Khi nào nên dùng class thay vì hàm thường?
Dùng class khi bạn có những ‘sự vật’ gắn liền dữ liệu với hành vi, và cần tạo nhiều bản giống nhau — ví dụ tài khoản người dùng, sản phẩm, nhân vật game. Với các tác vụ đơn giản, rời rạc thì hàm thường là đủ và gọn hơn. Class giúp code lớn có tổ chức, dễ tái dùng và mở rộng, nhưng không phải lúc nào cũng cần.
Thợ code chính hiệu, thích dắt người mới qua mấy đoạn 'khó nhằn' bằng giọng nhẹ tênh. Châm ngôn: cứ làm dự án thật, sai thì sửa, vui là chính.
Bài liên quan

10 lỗi người mới học lập trình hay mắc và cách tránh
Học lập trình mãi không tiến, dễ nản và bỏ cuộc? Phần lớn do 10 sai lầm rất phổ biến của người mới. Bài này chỉ từng lỗi và cách sửa cụ thể — để bạn học nhanh hơn và không bỏ giữa chừng.

Bài 10: Dự án — hoàn thiện trang cá nhân (HTML + CSS + JS)
Bài 10 series Web cơ bản (bài học 30 phút): dự án tổng hợp — ghép HTML, CSS responsive và JavaScript thành một trang cá nhân hoàn chỉnh có nút đổi giao diện sáng/tối; kèm code đầy đủ và gợi ý mở rộng.

Git và GitHub cho người mới: đưa dự án đầu tiên lên GitHub
Biết Git là gì rồi nhưng chưa biết đưa code lên GitHub? Bài này dẫn bạn từ cài đặt, tạo repo, đến các lệnh init → add → commit → push để đưa dự án đầu tiên lên GitHub, kèm giải thích từng khái niệm.