✨
Magic Methods
Chapter 6 · OOP Series
Magic Methods
— Phép Thuật Python
Các method đặc biệt với dấu __dunder__ giúp object của bạn hoạt động như một phần của Python!
Phần 1 — Magic Methods là gì?
Dunder Methods — "__tên__"
Magic methods (còn gọi là dunder methods — double underscore) là các method đặc biệt Python tự gọi khi bạn dùng toán tử hoặc hàm built-in với object của mình.
💡 Khi bạn viết
a + b, Python thực ra gọi a.__add__(b). Khi bạn gọi len(x), Python gọi x.__len__()!__str__
str(obj) / print(obj)
Chuỗi đẹp cho người đọc
__repr__
repr(obj)
Chuỗi debug cho lập trình viên
__len__
len(obj)
Trả về độ dài của object
__eq__
obj1 == obj2
So sánh bằng nhau
__add__
obj1 + obj2
Toán tử cộng
__lt__ / __gt__
obj1 < obj2
So sánh nhỏ hơn / lớn hơn
__contains__
item in obj
Kiểm tra phần tử có trong không
__getitem__
obj[key]
Truy cập phần tử theo index/key
Phần 2 — __str__ và __repr__
__str__ — Hiển thị đẹp cho người dùng
class HocSinh: def __init__(self, ten, lop, diem): self.ten = ten self.lop = lop self.diem = diem def __str__(self): ← gọi khi print(obj) return f"👤 {self.ten} | Lớp {self.lop} | Điểm {self.diem}" def __repr__(self): ← gọi khi debug return f"HocSinh('{self.ten}', '{self.lop}', {self.diem})" hs = HocSinh("Nguyễn Nam", "8A", 8.5) print(hs) # dùng __str__ print(repr(hs)) # dùng __repr__ print(f"Học sinh: {hs}") # f-string cũng dùng __str__
👤 Nguyễn Nam | Lớp 8A | Điểm 8.5
HocSinh('Nguyễn Nam', '8A', 8.5)
Học sinh: 👤 Nguyễn Nam | Lớp 8A | Điểm 8.5
HocSinh('Nguyễn Nam', '8A', 8.5)
Học sinh: 👤 Nguyễn Nam | Lớp 8A | Điểm 8.5
Phần 3 — Toán tử & So sánh
Toán tử tự định nghĩa cho Class
+→__add__(self, other)a + b
-→__sub__(self, other)a - b
*→__mul__(self, other)a * b
==→__eq__(self, other)a == b
<→__lt__(self, other)a < b → dùng sorted()
class Vec2D: def __init__(self, x, y): self.x = x; self.y = y def __str__(self): return f"Vec({self.x}, {self.y})" def __add__(self, other): ← v1 + v2 return Vec2D(self.x+other.x, self.y+other.y) def __mul__(self, scalar): ← v * 2 return Vec2D(self.x*scalar, self.y*scalar) def __eq__(self, other): ← v1 == v2 return self.x==other.x and self.y==other.y def __len__(self): ← len(v) return int((self.x**2 + self.y**2)**0.5) v1 = Vec2D(1, 2) v2 = Vec2D(3, 4) print(v1 + v2) # __add__ print(v1 * 3) # __mul__ print(v1 == Vec2D(1,2)) # __eq__ print(len(v2)) # __len__ = √(9+16) = 5
Vec(4, 6)
Vec(3, 6)
True
5
Vec(3, 6)
True
5
Phần 4 — Bài tập tổng hợp
🚀 Dự án nhỏ
Class GioHang với đầy đủ Magic Methods
class SanPham: def __init__(self, ten, gia): self.ten = ten; self.gia = gia def __str__(self): return f"{self.ten} ({self.gia:,}đ)" def __lt__(self, other): return self.gia < other.gia class GioHang: def __init__(self): self.items = [] def __len__(self): ← len(gio) return len(self.items) def __str__(self): lines = [f" - {sp}" for sp in self.items] return "🛒 Giỏ hàng:\n" + "\n".join(lines) def __contains__(self, ten): ← "Táo" in gio return any(sp.ten==ten for sp in self.items) def __add__(self, sp): ← gio + san_pham moi = GioHang() moi.items = self.items + [sp] return moi gio = GioHang() gio = gio + SanPham("Táo", 15_000) gio = gio + SanPham("Xoài", 25_000) gio = gio + SanPham("Ổi", 12_000) print(gio) print(f"Số lượng: {len(gio)} món") print(f"Có Táo? {'Táo' in gio}") print("Rẻ nhất:", min(gio.items)) # dùng __lt__!
🛒 Giỏ hàng:
- Táo (15,000đ)
- Xoài (25,000đ)
- Ổi (12,000đ)
Số lượng: 3 món
Có Táo? True
Rẻ nhất: Ổi (12,000đ)
- Táo (15,000đ)
- Xoài (25,000đ)
- Ổi (12,000đ)
Số lượng: 3 món
Có Táo? True
Rẻ nhất: Ổi (12,000đ)
🧩 Kiểm tra nhanh!
Chapter 6 — Magic Methods
print(obj) gọi magic method nào?
→ __str__
→ __str__
len(obj) gọi magic method nào?
→ __len__
→ __len__
a + b gọi magic method nào?
→ __add__
→ __add__
x in obj gọi magic method nào?
→ __contains__
→ __contains__