Làm Chủ Dunder Methods (Magic Methods) Trong Python: Nâng Tầm Kỹ Năng Lập Trình OOP

lúc 12:45 26 tháng 8, 2026
12 views
Làm Chủ Dunder Methods (Magic Methods) Trong Python: Nâng Tầm Kỹ Năng Lập Trình OOP

Khi học Lập trình hướng đối tượng (OOP) trong Python, chắc hẳn bạn đã từng thấy những phương thức có cú pháp đặc biệt bắt đầu và kết thúc bằng hai dấu gạch dưới như __init__, __str__, hay __len__. Chúng được gọi là Dunder Methods (viết tắt của Double Underscore Methods) hay Magic Methods (Phương thức ma thuật).

Những phương thức này cho phép bạn "móc nối" lớp tự định nghĩa của mình với các cơ chế cốt lõi và hàm có sẵn (built-in functions) của Python. Bài viết này sẽ dẫn dắt bạn đi từ vòng đời đối tượng cho đến các kỹ thuật tùy biến toán tử và tập hợp cực kỳ mạnh mẽ.

🧬 PHẦN 1: LIFECYCLE & REPRESENTATION (VÒNG ĐỜI & HIỂN THỊ)

1. Hàm khởi tạo __init__ và __new__

  • __init__(self, ...): Hàm khởi tạo quen thuộc dùng để thiết lập các giá trị trạng thái ban đầu cho đối tượng sau khi nó đã được tạo ra.
  • __new__(self, ...): Đây là hàm thực sự tạo ra thực thể (chạy trước __init__). Thường được ứng dụng nâng cao khi viết Design Pattern Singleton hoặc tùy biến việc khởi tạo lớp bất biến (immutable).
Code
class DatabaseConnection:
    _instance = None

    def __new__(cls, *args, **kwargs):
        # Ứng dụng Singleton: Chỉ cho phép tạo duy nhất 1 thực thể kết nối
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, host: str):
        self.host = host

2. Hiển thị đối tượng: __str__ vs __repr__

  • __str__(self): Định nghĩa chuỗi hiển thị gọn gàng, thân thiện cho người dùng cuối khi gọi print() hoặc str().
  • __repr__(self): Định nghĩa chuỗi hiển thị chi tiết, rõ ràng cho lập trình viên khi debug hoặc gọi repr().
Code
class Product:
    def __init__(self, name: str, price: float):
        self.name = name
        self.price = price

    def __str__(self) -> str:
        return f"Sản phẩm: {self.name} (Giá: {self.price} VNĐ)"

    def __repr__(self) -> str:
        return f"Product(name='{self.name}', price={self.price})"

3. Hàm hủy __del__

  • __del__(self): Được gọi tự động (Destructor) khi đối tượng bị xóa khỏi bộ nhớ bởi cơ chế thu gom rác (Garbage Collector) hoặc khi chương trình kết thúc.

🟨 PHẦN 2: COMPARISON OPERATORS (TOÁN TỬ SO SÁNH)

Để các đối tượng tự định nghĩa có thể so sánh lớn hơn, nhỏ hơn hoặc bằng nhau, bạn cần override các dunder methods tương ứng. Đồng thời, nên trả về NotImplemented nếu kiểu dữ liệu so sánh không hợp lệ.

  • __eq__(self, other): Xử lý toán tử ==
  • __ne__(self, other): Xử lý toán tử !=
  • __lt__(self, other): Xử lý toán tử <
  • __le__(self, other): Xử lý toán tử <=
  • __gt__(self, other): Xử lý toán tử >
  • __ge__(self, other): Xử lý toán tử >=
Code
class Score:
    def __init__(self, value: int):
        self.value = value

    def __eq__(self, other) -> bool:
        if not isinstance(other, Score):
            return NotImplemented
        return self.value == other.value

    def __lt__(self, other) -> bool:
        if not isinstance(other, Score):
            return NotImplemented
        return self.value < other.value

🟪 PHẦN 3: MATHEMATICAL OPERATORS (TOÁN TỬ TOÁN HỌC)

1. Toán tử tiêu chuẩn & Đảo ngược (Reflected Operators)

Giúp đối tượng của bạn tham gia vào các phép tính toán học mượt như dữ liệu nguyên thủy:

  • __add__(self, other): Phép cộng +
  • __sub__(self, other): Phép trừ -
  • __mul__(self, other): Phép nhân *
  • __truediv__(self, other): Phép chia thập phân /
  • __floordiv__(self, other): Chia lấy phần nguyên //
  • __mod__(self, other): Chia lấy dư %

Reflected Operators (Tiền tố r): Khi bạn thực hiện phép tính mà đối tượng của bạn đứng bên phải (Ví dụ: 10 + custom_object), Python sẽ gọi hàm __radd__ của đối tượng.

  • __radd__, __rsub__, __rmul__, v.v.

2. Toán tử gán (In-place Operators)

Giúp tối ưu hiệu suất với các toán tử kết hợp như +=, -=:

  • __iadd__(self, other): Xử lý +=
  • __isub__(self, other): Xử lý -=

🟧 PHẦN 4: CUSTOM COLLECTIONS (TÙY BIẾN TẬP HỢP)

Biến lớp của bạn thành một cấu trúc dữ liệu tùy chỉnh hoạt động giống hệt list hoặc dict thu nhỏ:

  • __len__(self): Trả về số nguyên dương khi gọi hàm len(my_object).
  • __getitem__(self, key): Cho phép truy cập phần tử qua ngoặc vuông my_object[key].
  • __setitem__(self, key, value): Cho phép gán/cập nhật giá trị my_object[key] = value.
  • __delitem__(self, key): Cho phép xóa phần tử bằng từ khóa del my_object[key].
  • __contains__(self, item): Định nghĩa hành vi kiểm tra tồn tại với toán tử in (if item in my_object:).
  • __iter__(self): Biến đối tượng thành một Iterable, hỗ trợ vòng lặp for item in my_object:.
Code
class ShoppingCart:
    def __init__(self):
        self.items = []

    def __len__(self) -> int:
        return len(self.items)

    def __getitem__(self, index: int):
        return self.items[index]

    def __setitem__(self, index: int, value):
        self.items[index] = value

    def __iter__(self):
        return iter(self.items)

🟫 PHẦN 5: ADVANCED CAPABILITIES (TÍNH NÂNG CAO)

1. Biến đối tượng thành hàm (__call__)

Cho phép bạn gọi một thực thể đối tượng trực tiếp như một hàm thông thường (my_object(arg1, arg2)):

Code
class PowerCalculator:
    def __init__(self, exponent: int):
        self.exponent = exponent

    def __call__(self, base: int) -> int:
        return base ** self.exponent

# Sử dụng:
square = PowerCalculator(2)
print(square(5))  # Kết quả: 25 (Gọi trực tiếp thực thể như hàm)

2. Hàm Hash (__hash__) và Set/Dict Key

Để đối tượng có thể được đưa vào set hoặc làm khóa (key) trong dict, bạn phải định nghĩa __hash__ đi kèm bắt buộc với __eq__.

3. Context Manager (__enter__ & __exit__)

Cho phép đối tượng hoạt động mượt mà với từ khóa with, rất hữu ích cho việc tự động mở và đóng tài nguyên (kết nối database, mở file):

Code
class ManagedFile:
    def __init__(self, filename: str):
        self.filename = filename

    def __enter__(self):
        print(f"Đang mở file: {self.filename}")
        self.file = open(self.filename, "w")
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()
        print(f"Đã đóng file an toàn: {self.filename}")

# Sử dụng:
# with ManagedFile("test.txt") as f:
#     f.write("Xin chào Python!")

📌 Lời Kết

Việc thành thạo các Dunder Methods (Magic Methods) sẽ giúp bạn khai phá trọn vẹn sức mạnh của Python, viết code ngắn gọn, uyển chuyển và mang phong cách "Pythonic" thực thụ. Hãy chọn áp dụng ngay một vài phương thức vào dự án tiếp theo của bạn nhé!

Từ khóa tìm hiểu thêm: Python Dunder Methods, Magic Methods Python, Python __init__ __new__, Context Manager Python.

Bình luận

Đăng nhập để để lại bình luận.
Chưa có bình luận nào cho bài viết này.

Bài viết liên quan