Trong Python, các phương thức Dunder (viết tắt của Double Under), còn được gọi là phương thức Magic hoặc phương thức Special, là những phương thức có tên được bao quanh bởi hai dấu gạch dưới (ví dụ: __init__, __str__, __add__). Các phương thức này được Python tự động gọi khi một số hoạt động nhất định xảy ra trên đối tượng.
Các phương thức Dunder cho phép các lớp trong Python có thể tương tác tự nhiên với cú pháp và cấu trúc ngôn ngữ Python, giúp các đối tượng hoạt động giống như các kiểu dữ liệu cơ bản.
Dưới đây là một số phương thức Dunder phổ biến và cách chúng hoạt động.
__init__(self, ...) – Phương Thức Khởi TạoPhương thức __init__ là phương thức khởi tạo, được gọi khi một đối tượng của lớp được tạo ra. Nó giúp khởi tạo các thuộc tính của đối tượng khi đối tượng được tạo.
Ví dụ:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
# Tạo đối tượng
person = Person("Anh", 25)
print(person.name)  # Output: Anh
print(person.age)   # Output: 25
Phương thức __init__ không trả về giá trị, mà chỉ khởi tạo các thuộc tính của đối tượng.
__str__(self) – Phương Thức Chuỗi (String Representation)Phương thức __str__ trả về một chuỗi để mô tả đối tượng dưới dạng dễ đọc. Nó được gọi tự động khi bạn sử dụng hàm print() hoặc str() trên một đối tượng.
Ví dụ:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"Person({self.name}, {self.age})"
# Tạo đối tượng
person = Person("Anh", 25)
print(person)  # Output: Person(Anh, 25)
__repr__(self) – Phương Thức Biểu Diễn (Representation)Phương thức __repr__ trả về chuỗi biểu diễn của đối tượng sao cho nó có thể được sử dụng để tái tạo đối tượng. Nó được gọi khi bạn sử dụng hàm repr() hoặc khi kiểm tra đối tượng trong môi trường tương tác.
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        return f"Person({self.name!r}, {self.age!r})"
person = Person("Anh", 25)
print(repr(person))  # Output: Person('Anh', 25)
__len__(self) – Phương Thức Chiều DàiPhương thức __len__ trả về độ dài của đối tượng. Nó được gọi khi sử dụng hàm len().
Ví dụ:
class MyList:
    def __init__(self, elements):
        self.elements = elements
    def __len__(self):
        return len(self.elements)
my_list = MyList([1, 2, 3, 4])
print(len(my_list))  # Output: 4
__getitem__(self, key) – Truy Cập Phần TửPhương thức __getitem__ được gọi khi bạn truy cập một phần tử trong đối tượng bằng cú pháp obj[key].
Ví dụ:
class MyList:
    def __init__(self, elements):
        self.elements = elements
    def __getitem__(self, index):
        return self.elements[index]
my_list = MyList([1, 2, 3, 4])
print(my_list[2])  # Output: 3
__setitem__(self, key, value) – Gán Giá Trị Cho Phần TửPhương thức __setitem__ được gọi khi bạn gán giá trị cho một phần tử trong đối tượng với cú pháp obj[key] = value.
class MyList:
    def __init__(self, elements):
        self.elements = elements
    def __setitem__(self, index, value):
        self.elements[index] = value
my_list = MyList([1, 2, 3, 4])
my_list[2] = 100
print(my_list.elements)  # Output: [1, 2, 100, 4]
__delitem__(self, key) – Xóa Phần TửPhương thức __delitem__ được gọi khi bạn xóa một phần tử trong đối tượng với cú pháp del obj[key].
class MyList:
    def __init__(self, elements):
        self.elements = elements
    def __delitem__(self, index):
        del self.elements[index]
my_list = MyList([1, 2, 3, 4])
del my_list[2]
print(my_list.elements)  # Output: [1, 2, 4]
__add__(self, other) – Phép CộngPhương thức __add__ định nghĩa hành vi của phép cộng (+) giữa hai đối tượng.
Ví dụ:
class Number:
    def __init__(self, value):
        self.value = value
    def __add__(self, other):
        return Number(self.value + other.value)
    def __str__(self):
        return str(self.value)
a = Number(10)
b = Number(5)
c = a + b
print(c)  # Output: 15
__call__(self, ...) – Biến Đối Tượng Thành HàmPhương thức __call__ cho phép một đối tượng hoạt động như một hàm, có nghĩa là bạn có thể “gọi” một đối tượng như gọi một hàm.
class Greeter:
    def __init__(self, name):
        self.name = name
    def __call__(self):
        return f"Hello, {self.name}!"
greeter = Greeter("Anh")
print(greeter())  # Output: Hello, Anh!
__eq__(self, other) – So Sánh Bằng (==)Phương thức __eq__ định nghĩa hành vi của toán tử so sánh == giữa hai đối tượng.
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        return self.name == other.name and self.age == other.age
p1 = Person("Anh", 25)
p2 = Person("Anh", 25)
print(p1 == p2)  # Output: True
__lt__(self, other) – So Sánh Nhỏ Hơn (<)Phương thức __lt__ định nghĩa hành vi của toán tử so sánh nhỏ hơn <.
class Number:
    def __init__(self, value):
        self.value = value
    def __lt__(self, other):
        return self.value < other.value
a = Number(10)
b = Number(5)
print(a < b)  # Output: False
__contains__(self, item) – Kiểm Tra Sự Tồn TạiPhương thức __contains__ được gọi khi bạn kiểm tra xem một đối tượng có tồn tại trong một container với cú pháp item in obj.
class MyList:
    def __init__(self, elements):
        self.elements = elements
    def __contains__(self, item):
        return item in self.elements
my_list = MyList([1, 2, 3, 4])
print(3 in my_list)  # Output: True
__iter__(self) và __next__(self) – Duyệt Qua Các Đối TượngPhương thức __iter__ và __next__ được sử dụng để biến đối tượng thành iterable (có thể duyệt qua các phần tử).
class MyRange:
    def __init__(self, start, end):
        self.current = start
        self.end = end
    def __iter__(self):
        return self
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        self.current += 1
        return self.current - 1
for num in MyRange(1, 5):
    print(num)
# Output: 1, 2, 3, 4
Các phương thức Dunder/Magic/Special trong Python giúp bạn tùy chỉnh hành vi của các đối tượng khi sử dụng các toán tử, phương thức tích hợp, hoặc thao tác với các cấu trúc ngôn ngữ. Việc sử dụng các phương thức này giúp viết mã Python ngắn gọn, dễ hiểu hơn và dễ dàng mở rộng các lớp theo nhu cầu riêng của bạn.