Phương pháp Thư Mật Python: Tất cả những gì bạn cần biết - Phần 1

By khoanc, at: 11:20 Ngày 12 tháng 9 năm 2023

Thời gian đọc ước tính: __READING_TIME__ minutes

Python Magic Methods: All you need to know - Part 1
Python Magic Methods: All you need to know - Part 1

Python, nổi tiếng với sự đơn giản và thanh lịch, lại ẩn chứa một bộ tính năng mạnh mẽ cho phép các nhà phát triển kiểm soát chi tiết cách thức các đối tượng hoạt động. Trung tâm của sự kiểm soát này là các "phương thức phép thuật" hoặc "phương thức dunder" của Python, được biểu thị bằng hai dấu gạch dưới (ví dụ: __init__, __str__). Những phương thức đặc biệt này cho phép bạn định nghĩa các hành vi tùy chỉnh cho các đối tượng Python của mình, làm cho chúng trực quan và linh hoạt hơn.

Trong quá trình khám phá các phương thức phép thuật của Python 3 này, chúng ta sẽ lần lượt làm sáng tỏ những bí ẩn của chúng. Các phương thức này đóng vai trò then chốt trong việc định nghĩa việc tạo, biểu diễn và thậm chí là hủy đối tượng. Bằng cách hiểu và khai thác sức mạnh của các phương thức phép thuật, bạn có thể tạo ra các lớp Python đáp ứng chính xác các yêu cầu của mình, nâng cao mã của bạn lên một tầm cao mới về tính biểu cảm và thanh lịch.

 

1. Khởi tạo và xây dựng

 

__new__

 

Mục đích: Phương thức __new__ được gọi khi một đối tượng được tạo. Nó chịu trách nhiệm tạo và trả về một thể hiện mới của lớp. Nó thường được sử dụng trong các trường hợp bạn cần tùy chỉnh quá trình tạo đối tượng trước khi nó được khởi tạo bởi __init__.

Ví dụ

class MySingleton:
    instance = None
    # Thuộc tính lớp để lưu trữ thể hiện duy nhất
    def __new__(cls):
        if cls.instance is None:
            cls.instance = super(MySingleton, cls).__new__(cls)
        return cls.instance

obj1 = MySingleton()
obj2 = MySingleton() # Cả obj1 và obj2 đều là cùng một thể hiện print(obj1 is obj2) # Kết quả: True

 

__init__

 

Mục đích: Phương thức __init__ được gọi sau phương thức __new__ và chịu trách nhiệm khởi tạo các thuộc tính của đối tượng. Nó cho phép bạn thiết lập trạng thái ban đầu của đối tượng.

Ví dụ

class Person: 
    def __init__(self, name): 
        self.name = name 
obj = Person("Alice") 
print(obj.name) # Kết quả: "Alice"

 

__del__

 

Mục đích: Phương thức __del__, còn được gọi là hàm hủy, được gọi khi một đối tượng sắp bị hủy hoặc xóa. Nó có thể được sử dụng để thực hiện các thao tác dọn dẹp hoặc giải phóng tài nguyên liên quan đến đối tượng.

Ví dụ

class Appartment: 
    def __init__(self, name): 
        self.name = name 
    def __del__(self): 
        print(f"Tài nguyên {self.name} đang bị hủy.") 

obj = Appartment("Wonder 7") 
del obj # Kết quả: "Tài nguyên Wonder 7 đang bị hủy."

 

2. Các phương thức phép thuật số

 

__trunc__

 

Mục đích: Thực hiện hành vi cho hàm math.trunc(), làm tròn một số dấu phẩy động về phía không.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __trunc__(self):
        return int(self.value)

num = CustomNumber(4.9)
result = math.trunc(num)
print(result)  # Kết quả: 4

 

__ceil__

 

Mục đích: Thực hiện hành vi cho math.ceil(), làm tròn một số lên số nguyên gần nhất.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __ceil__(self):
        return math.ceil(self.value)

num = CustomNumber(3.2)
result = math.ceil(num)
print(result)  # Kết quả: 4

 

__floor__

 

Mục đích: Thực hiện hành vi cho math.floor(), làm tròn một số xuống số nguyên gần nhất.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __floor__(self):
        return math.floor(self.value)

num = CustomNumber(3.8)
result = math.floor(num)
print(result)  # Kết quả: 3

 

__round__

 

Mục đích: Thực hiện hành vi cho hàm round() tích hợp sẵn, cho phép làm tròn tùy chỉnh với số chữ số thập phân (n) đã chỉ định.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __round__(self, n):
        return round(self.value, n)

num = CustomNumber(3.14159265)
result = round(num, 2)
print(result)  # Kết quả: 3.14

 

__invert__

 

Mục đích: Thực hiện hành vi cho phép đảo ngược sử dụng toán tử ~ (bitwise NOT) khi được áp dụng cho một đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    def __invert__(self):
        return ~self.value

bitwise_obj = MyBitwise(5)
result = ~bitwise_obj
print(result)  # Kết quả: -6 (bitwise NOT của 5)

 

__abs__

 

Mục đích: Thực hiện hành vi cho hàm abs() tích hợp sẵn, trả về giá trị tuyệt đối của một đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __abs__(self):
        return abs(self.value)

num = CustomNumber(-7)
result = abs(num)
print(result)  # Kết quả: 7

 

__neg__

 

Mục đích: Thực hiện hành vi cho phép phủ định (unary -) khi được áp dụng cho một đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value    
    def __neg__(self):
        return -self.value

num = CustomNumber(10)
result = -num
print(result)  # Kết quả: -10

 

__pos__

 

Mục đích: Thực hiện hành vi cho phép dương (unary +) khi được áp dụng cho một đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value    
    def __pos__(self):
        return +self.value

num = CustomNumber(10)
result = +num
print(result)  # Kết quả: 10

 

3. Toán tử số học

Python cho phép bạn định nghĩa các hành vi tùy chỉnh cho các phép toán số học bằng các phương thức phép thuật. Các phương thức này cho phép các đối tượng của bạn tham gia vào các phép tính toán học một cách liền mạch. Dưới đây là các phương thức phép thuật số học cần thiết:

 

__add__

 

Mục đích: Thực hiện hành vi cho toán tử cộng (+) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __add__(self, other):
        return CustomNumber(self.value + other.value)

num1 = CustomNumber(5)
num2 = CustomNumber(3)
result = num1 + num2
print(result.value)  # Kết quả: 8

 

__sub__

 

Mục đích: Thực hiện hành vi cho toán tử trừ (-) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __sub__(self, other):
        return CustomNumber(self.value - other.value)

num1 = CustomNumber(8)
num2 = CustomNumber(3)
result = num1 - num2
print(result.value)  # Kết quả: 5

 

__mul__

 

Mục đích: Thực hiện hành vi cho toán tử nhân (*) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __mul__(self, other):
        return CustomNumber(self.value * other.value)

num1 = CustomNumber(4)
num2 = CustomNumber(7)
result = num1 * num2
print(result.value)  # Kết quả: 28

 

__floordiv__

 

Mục đích: Thực hiện hành vi cho toán tử chia lấy phần nguyên (//) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __floordiv__(self, other):
        return CustomNumber(self.value // other.value)

num1 = CustomNumber(10)
num2 = CustomNumber(3)
result = num1 // num2
print(result.value)  # Kết quả: 3

 

__div__

 

Mục đích: Thực hiện hành vi cho toán tử chia (/) khi được sử dụng giữa các đối tượng (chỉ Python 2).

Ví dụ (Python 2)

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __div__(self, other):
        return CustomNumber(self.value / other.value)

num1 = CustomNumber(8)
num2 = CustomNumber(2)
result = num1 / num2
print(result.value)  # Kết quả: 4.0

 

__truediv__

 

Mục đích: Thực hiện hành vi cho toán tử chia thực sự (/) khi được sử dụng giữa các đối tượng (Python 3+).

Ví dụ (Python 3+)

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __truediv__(self, other):
        return CustomNumber(self.value / other.value)

num1 = CustomNumber(8)
num2 = CustomNumber(2)
result = num1 / num2
print(result.value)  # Kết quả: 4.0

 

__mod__

 

Mục đích: Thực hiện hành vi cho toán tử modulo (%) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __mod__(self, other):
        return CustomNumber(self.value % other.value)

num1 = CustomNumber(10)
num2 = CustomNumber(3)
result = num1 % num2
print(result.value)  # Kết quả: 1

 

__divmod__

 

Mục đích: Thực hiện hành vi cho hàm divmod() tích hợp sẵn khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __divmod__(self, other):
        return divmod(self.value, other.value)

num1 = CustomNumber(10)
num2 = CustomNumber(3)
result = divmod(num1, num2)
print(result)  # Kết quả: (3, 1)

 

__pow__

 

Mục đích: Thực hiện hành vi cho phép mũ (**) khi được sử dụng giữa các đối tượng.

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    
    def __pow__(self, other):
        return CustomNumber(self.value ** other.value)

num1 = CustomNumber(2)
num2 = CustomNumber(3)
result = num1 ** num2
print(result.value)  # Kết quả: 8

 

__lshift__

 

Mục đích: Thực hiện hành vi cho phép dịch trái bit (<<) khi được sử dụng giữa các đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    
    def __lshift__(self, other):
        return MyBitwise(self.value << other.value)

bitwise_obj1 = MyBitwise(8)
bitwise_obj2 = MyBitwise(2)
result = bitwise_obj1 << bitwise_obj2
print(result.value)  # Kết quả: 32 (8 << 2)

 

__rshift__

 

Mục đích: Thực hiện hành vi cho phép dịch phải bit (>>) khi được sử dụng giữa các đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    
    def __rshift__(self, other):
        return MyBitwise(self.value >> other.value)

bitwise_obj1 = MyBitwise(16)
bitwise_obj2 = MyBitwise(2)
result = bitwise_obj1 >> bitwise_obj2
print(result.value)  # Kết quả: 4 (16 >> 2)

 

__and__

 

Mục đích: Thực hiện hành vi cho phép AND bit (&) khi được sử dụng giữa các đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    
    def __and__(self, other):
        return MyBitwise(self.value & other.value)

bitwise_obj1 = MyBitwise(5)
bitwise_obj2 = MyBitwise(3)
result = bitwise_obj1 & bitwise_obj2
print(result.value)  # Kết quả: 1 (5 & 3)

 

__or__

 

Mục đích: Thực hiện hành vi cho phép OR bit (|) khi được sử dụng giữa các đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    
    def __or__(self, other):
        return MyBitwise(self.value | other.value)

bitwise_obj1 = MyBitwise(5)
bitwise_obj2 = MyBitwise(3)
result = bitwise_obj1 | bitwise_obj2
print(result.value)  # Kết quả: 7 (5 | 3)

 

__xor__

 

Mục đích: Thực hiện hành vi cho phép XOR bit (^) khi được sử dụng giữa các đối tượng.

Ví dụ

class MyBitwise:
    def __init__(self, value):
        self.value = value
    
    def __xor__(self, other):
        return MyBitwise(self.value ^ other.value)

bitwise_obj1 = MyBitwise(5)
bitwise_obj2 = MyBitwise(3)
result = bitwise_obj1 ^ bitwise_obj2
print(result.value)  # Kết quả: 6 (5 ^ 3)

 

__bool__

 

Mục đích: định nghĩa hành vi tùy chỉnh của một đối tượng khi nó được đánh giá trong ngữ cảnh boolean bằng hàm bool() hoặc trong các điều kiện như câu lệnh if. Phương thức này nên trả về True (nếu đối tượng được coi là "truthy") hoặc False (nếu đối tượng được coi là "falsy").

Ví dụ

class CustomNumber:
    def __init__(self, value):
        self.value = value
    def __bool__(self):
        # Định nghĩa hành vi boolean tùy chỉnh.
        return self.value != 0

# Tạo các thể hiện của CustomNumber với các giá trị khác nhau.
num1 = CustomNumber(5)  # Thể hiện này được coi là "truthy."
num2 = CustomNumber(0)  # Thể hiện này được coi là "falsy."

# Sử dụng các thể hiện trong ngữ cảnh boolean.
if num1:
    print("num1 được coi là 'truthy'.")
else:
    print("num1 được coi là 'falsy'.")
if num2:
    print("num2 được coi là 'truthy'.")
else:
    print("num2 được coi là 'falsy'.")

 

4. Phương thức phép thuật chuỗi

 

Python cung cấp một tập hợp các phương thức phép thuật cho phép bạn tùy chỉnh hành vi của các đối tượng khi chúng được chuyển đổi thành chuỗi, được biểu diễn hoặc được sử dụng trong các thao tác liên quan đến chuỗi khác nhau. Dưới đây là một số phương thức phép thuật liên quan đến chuỗi cần thiết:

 

__str__

 

Mục đích: Định nghĩa hành vi khi str() được gọi trên một thể hiện của lớp bạn. Nó nên trả về một chuỗi biểu diễn đối tượng có thể đọc được.

Ví dụ

class CustomString:
    def __init__(self, value):
        self.value = value
    
    def __str__(self):
        return f"Thể hiện CustomString với giá trị: {self.value}"

obj = CustomString(42)
print(str(obj))  # Kết quả: "Thể hiện CustomString với giá trị: 42"

 

__repr__

 

Mục đích: Được gọi bởi phương thức repr() tích hợp sẵn để trả về một biểu diễn có thể đọc được của kiểu đối tượng.

Ví dụ

class CustomString:
    def __init__(self, value):
        self.value = value
    
    def __repr__(self):
        return f"CustomString({self.value})"

obj = CustomString(42)
print(repr(obj))  # Kết quả: "CustomString(42)"

 

__unicode__

 

Mục đích: Phương thức này trả về một chuỗi Unicode biểu diễn đối tượng.

Ví dụ

class CustomString:
    def __init__(self, value):
        self.value = value
    
    def __unicode__(self):
        return unicode(self.value)

obj = CustomString(u'Hello')
print(unicode(obj))  # Kết quả:
Tag list:
- Python
- Python methods
- __setattr__
- __getattr__
- python3
- Magic methods examples
- magic methods
- underscore method
- magic functions
- python 3
- __call__
- Dunder methods
- python magic

Theo dõi

Theo dõi bản tin của chúng tôi và không bao giờ bỏ lỡ những tin tức mới nhất.