Quá tải toán tử trong Python cho phép bạn xác định lại cách các toán tử hoạt động với các lớp tùy chỉnh của bạn. Bài viết này sẽ chỉ cho bạn cách thực hiện với các ví dụ và mẹo.
Dưới đây là một ví dụ về Nạp chồng toán tử trong Python. Trong ví dụ này, chúng ta sẽ tạo một lớp biểu thị số phức và sau đó nạp chồng các toán tử + và *.
class ComplexNumber:
def __init__(self, real, imag):
self.real = real
self.imag = imag
# Overloading the addition operator '+'
def __add__(self, other):
real_sum = self.real + other.real
imag_sum = self.imag + other.imag
return ComplexNumber(real_sum, imag_sum)
# Overloading the multiplication operator '*'
def __mul__(self, other):
real_product = (self.real * other.real) - (self.imag * other.imag)
imag_product = (self.real * other.imag) + (self.imag * other.real)
return ComplexNumber(real_product, imag_product)
# Overloading the equality operator '=='
def __eq__(self, other):
return self.real == other.real and self.imag == other.imag
# Overloading the string representation for better display
def __str__(self):
return f"{self.real} + {self.imag}j"
# Example usage of the ComplexNumber class with operator overloading
c1 = ComplexNumber(2, 3)
c2 = ComplexNumber(1, 4)
result_sum = c1 + c2
print(f"Sum: {result_sum}")
result_product = c1 * c2
print(f"Product: {result_product}")
are_equal = c1 == c2
print(f"Are equal: {are_equal}")
Đầu ra của đoạn mã trên là:
Sum: 3 + 7j
Product: -10 + 11j
Are equal: False
Hãy xem một ví dụ về hành vi khác nhau của toán tử “+” trong Nạp chồng toán tử trong Python. Chúng tôi sẽ trực tiếp thực hiện một số lệnh để xem kết quả.
Hãy xem kết quả của việc sử dụng toán tử “+” trên hai số nguyên:
>>> a = 10
>>> b = 5
>>> a + b
15
Như chúng ta có thể thấy, toán tử “+” thực hiện cộng hai số. Bây giờ, hãy thử sử dụng toán tử “+” trên hai chuỗi:
>>> hello = "Hello "
>>> name = "John"
>>> hello + name
'Hello John'
Ở đây, chúng ta có thể thấy rằng đầu ra nối hai chuỗi. Bây giờ chúng ta sẽ xem điều gì xảy ra khi chúng ta sử dụng toán tử “+” trên hai danh sách:
>>> list1 = [1, 2, 3]
>>> list2 = [4, 5, 6]
>>> list1 + list2
[1, 2, 3, 4, 5, 6]
Chúng ta có thể thấy đầu ra là danh sách được hợp nhất của hai danh sách. Chúng ta có thể thấy rằng các toán tử Python hoạt động khác nhau đối với các loại toán hạng khác nhau.
Bây giờ, hãy nạp chồng toán tử “+” trong lớp ComplexNumber trong đoạn mã bên dưới:
class ComplexNumber():
def __init__(self,real,imaginary):
self.real = real
self.imaginary = imaginary
def __add__(self,other_complex_number):
real_result = self.real + other_complex_number.real
imaginary_result = self.imaginary + other_complex_number.imaginary
return ComplexNumber(real_result,imaginary_result)
def __str__(self):
return str(self.real) + ' + ' + str(self.imaginary) + 'i'
complex_number1 = ComplexNumber(1,2)
complex_number2 = ComplexNumber(3,4)
print("The sum of complex numbers is: ", complex_number1 + complex_number2)
Trong đoạn mã trên, chúng tôi đã triển khai hàm cụ thể __add__() để nạp chồng toán tử “+”.
Đầu ra của đoạn mã trên là:
The sum of complex numbers is: 4 + 6i
Ở kết quả trên, chúng ta có thể thấy phép cộng của chúng ta là kết quả của phép cộng số thực (1 và 3) và số ảo (2i và 4i).
Ý tưởng cơ bản đằng sau Nạp chồng toán tử trong Python là xác định các phương thức đặc biệt trong lớp tương ứng với các toán tử mà bạn muốn nạp chồng. Hãy cùng hiểu nó qua những ví dụ sau:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
# Usage
v = Vector(2, 3)
result = v * 2
print(result.x, result.y)
Đầu ra của đoạn mã trên là:
4 6
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"{self.title} by {self.author}"
# Usage
book = Book("Python Programming", "John Doe")
print(book)
Đầu ra của đoạn mã trên là:
Python Programming by John Doe
Hãy xem một ví dụ trong đó chúng ta sẽ nạp chồng tất cả các toán tử so sánh (như >, !, <=, >=, v.v.):
class ComplexNumber():
def __init__(self,real,imaginary):
self.real = real
self.imaginary = imaginary
def __str__(self):
return str(self.real) + ' + ' + str(self.imaginary) + 'i'
def __gt__(self,other_complex_number):
if self.real > other_complex_number.real:
return True
elif self.real == other_complex_number.real:
if self.imaginary > other_complex_number.imaginary:
return True
else:
return False
else:
return False
def __ne__(self,other_complex_number):
if self.real != other_complex_number.real:
return True
elif self.real == other_complex_number.real:
if self.imaginary != other_complex_number.imaginary:
return True
else:
return False
else:
return False
def __le__(self,other_complex_number):
if self.real <= other_complex_number.real:
return True
elif self.real == other_complex_number.real:
if self.imaginary <= other_complex_number.imaginary:
return True
else:
return False
else:
return False
def __ge__(self,other_complex_number):
if self.real >= other_complex_number.real:
return True
elif self.real == other_complex_number.real:
if self.imaginary >= other_complex_number.imaginary:
return True
else:
return False
else:
return False
complex_number1 = ComplexNumber(1,2)
complex_number2 = ComplexNumber(3,4)
if(complex_number1 > complex_number2):
print(f"Complex number: ({complex_number1}) is greater than the complex number: ({complex_number2})")
if(complex_number1 != complex_number2):
print(f"Complex number: ({complex_number1}) is not equal to the complex number: ({complex_number2})")
if(complex_number1 <= complex_number2):
print(f"Complex number: ({complex_number1}) is less than or equal to the complex number: ({complex_number2})")
if(complex_number1 >= complex_number2):
print(f"Complex number: ({complex_number1}) is greater than or equal to the complex number: ({complex_number2})")
Đầu ra của đoạn mã trên là:
Complex number: (1 + 2i) is not equal to the complex number: (3 + 4i)
Complex number: (1 + 2i) is less than or equal to the complex number: (3 + 4i)
Trong đoạn mã trên, chúng ta đã nạp chồng sáu phép so sánh hoặc toán tử quan hệ bằng cách so sánh các toán tử thực và phần ảo của hai số phức.
Hãy xem cách chúng ta có thể nạp chồng toán tử nhỏ hơn (<). Để làm điều này, chúng ta cần triển khai hàm đặc biệt __lt__() trong lớp số phức:
class ComplexNumber():
def __init__(self,real,imaginary):
self.real = real
self.imaginary = imaginary
def __lt__(self,complex_number_2):
if self.real < other_complex_number.real:
return True
elif self.real == other_complex_number.real:
if self.imaginary < other_complex_number.imaginary:
return True
else:
return False
else:
return False
def __str__(self):
return str(self.real) + ' + ' + str(self.imaginary) + 'i'
complex_number1 = ComplexNumber(1,2)
complex_number2 = ComplexNumber(3,4)
if complex_number1 < complex_number2:
print(f"Complex number: ({complex_number1}) is less than the complex number: ({complex_number2})")
else :
print(f"Complex number: ({complex_number1}) is not less than the complex number: ({complex_number2})")
Đầu ra của đoạn mã trên là:
Complex number: (1 + 2i) is less than the complex number: (3 + 4i)
Trong kết quả nhận được, chúng ta có thể thấy rằng vì 1 + 2i nhỏ hơn 3 + 4i là phần thực 1 nhỏ hơn phần thực 33 + 4i. nhỏ hơn 1 + 2i, chúng ta nhận được kết quả
Như bạn có thể thấy, chúng tôi đã thêm phần triển khai cho phương thức __lt__(). Nó so sánh phần thực của self-object với phần thực của đối tượng được truyền khác, nếu bằng nhau thì ta so sánh phần ảo để ra kết quả.
Chúng tôi cũng đã thêm việc triển khai hàm cụ thể __str__() để cung cấp đối tượng ở định dạng có thể in được mà print()
Điều xảy ra đằng sau hậu trường là khi chúng tôi thực hiện complex_number1 < complex_number2, Python lần lượt gọi số phức1.__lt__(complexnumber2) mà thực ra là ComplexNumber.__lt__( complexnumber1,complexnumber2). Việc so sánh nhỏ hơn sau đó sẽ diễn ra như chúng tôi đã chỉ định trong hàm đặc biệt.
Bây giờ, hãy nạp chồng toán tử đẳng thức(==) để kiểm tra xem hai đối tượng ComplexNumber có bằng nhau hay không. Dưới đây là đoạn mã để nạp chồng toán tử “==”:
class ComplexNumber():
def __init__(self,real,imaginary):
self.real = real
self.imaginary = imaginary
def __eq__(self,other_complex_number):
if self.real < other_complex_number.real and self.imaginary == other_complex_number.imaginary:
return True
else:
return False
def __str__(self):
return str(self.real) + ' + ' + str(self.imaginary) + 'i'
complex_number1 = ComplexNumber(1,2)
complex_number2 = ComplexNumber(3,4)
if complex_number1 == complex_number2:
print(f"Complex number: ({complex_number1}) is equal to the complex number: ({complex_number2})")
else :
print(f"Complex number: ({complex_number1}) is not equal to the complex number: ({complex_number2})")
Để nạp chồng toán tử “==”, chúng ta cần nạp chồng hàm đặc biệt __eq__(). Khi triển khai phương thức__eq__(), chúng ta kiểm tra xem phần thực của hai số phức có bằng nhau hay không; nếu không, chúng tôi sẽ kiểm tra sự bằng nhau của các phần ảo và trả về phản hồi theo đó.
Đầu ra của đoạn mã trên là:
Complex number: (1 + 2i) is not equal to the complex number: (3 + 4i)
Ở kết quả đầu ra, chúng ta có thể thấy rằng vì phần thực của số phức (1 và 3) không bằng nhau nên chúng ta nhận được kết quả là số phức không bằng nhau.
Bây giờ chúng ta sẽ xem xét các phương thức ma thuật được xác định trước khác nhau trong Nạp chồng toán tử cho các toán tử khác nhau.
Chúng tôi đang lấy hai đối tượng demo C1 và C2 thuộc loại ComplexNumber cho mục đích giải thích:
Nhà điều hành | Tên người vận hành | Phương pháp kỳ diệu | Sự biểu lộ | Cuộc gọi nội bộ |
---|---|---|---|---|
>> | Dịch chuyển phải theo bit | __rshift__(bản thân, người khác) | C1>>C2 | C1.__rshift__(C2) |
<< | Dịch chuyển trái theo bit | __lshift__(bản thân, người khác) | C1<<C2 | C1.__lshift__(C2) |
& | Theo bit VÀ | __và__(bản thân, người khác) | C1&C2 | C1.__và__(C2) |
TÔI | Theo bit HOẶC | __hoặc__(bản thân, người khác) | C1IC2 | C1.__hoặc__(C2) |
^ | XOR theo bit | __xor__(bản thân, người khác) | C1^C2 | C1.__xor__(C2) |
Nhà điều hành | Tên người vận hành | Phương pháp kỳ diệu | Sự biểu lộ | Cuộc gọi nội bộ |
---|---|---|---|---|
= | Trừ VÀ | __isub__(bản thân, người khác) | C1-=C2 | C1.__isub__(C2) |
+= | Thêm VÀ | __iadd__(bản thân, người khác) | C1+=C2 | C1.__tốt__(C2) |
*= | Nhân VÀ | __imul__(bản thân, người khác) | C1*=C2 | C1.__imul__(C2) |
/= | Chia VÀ | __idiv__(bản thân, người khác) | C1/=C2 | C1.__idiv__(C2) |
//= | Chia(sàn) VÀ | __ifloordiv__(bản thân, người khác) | C1//=C2 | C1.__ifloordiv__(C2) |
%= | mô đun VÀ | __chống lại__(bản thân, người khác) | C1%=C2 | C1.__chống lại__(C2) |
**= | Số mũ VÀ | __ipow__(bản thân, người khác) | C1**=C2 | C1.__ipow__(C2) |
>>= | Thực hiện dịch chuyển sang phải theo bit và gán giá trị cho toán hạng bên trái | __irshift__(bản thân, người khác) | C1>>=C2 | C1.__irshift__(C2) |
<<= | Thực hiện dịch chuyển trái theo bit và gán giá trị cho toán hạng trái | __ilshift__(bản thân, người khác) | C1<<=C2 | C1.__ilshift__(C2) |
&= | Thực hiện Bitwise AND và gán giá trị cho toán hạng bên trái | __iand__(bản thân, người khác) | C1&=C2 | C1.__iand__(C2) |
tôi= | Thực hiện Bitwise OR và gán giá trị cho toán hạng bên trái | __ior__(bản thân, người khác | C1I=C2 | C1.__ior__(C2) |
^= | Thực hiện Bitwise XOR và gán giá trị cho toán hạng bên trái | __ixor__(bản thân, người khác) | C1^=C2 | C1.__ixor__(C2) |
Nhà điều hành | Tên người vận hành | Phương pháp kỳ diệu | Sự biểu lộ | Cuộc gọi nội bộ |
---|---|---|---|---|
– | Đơn nhất Plus | __neg__(bản thân) | -C1 | C1.__neg__() |
+ | Điểm trừ đơn nhất | __pos__(tự) | +C1 | C1.__pos__() |
~ | Đảo ngược đơn nhất | __đảo ngược__(tự) | ~C1 | C1.__ đảo__() |
Trong Python, có thể tùy chỉnh hành vi của các toán tử Boolean __and__, __or__ và __not__ bằng cách xác định các phương thức cụ thể trong lớp của bạn.
Hãy lấy một ví dụ về nạp chồng hoặc toán tử:
Khi làm việc với các lớp tùy chỉnh, bạn có thể muốn xác định một hành vi cụ thể cho toán tử __or__ dựa trên các đặc điểm của đối tượng của bạn. Đây là lúc quá tải toán tử phát huy tác dụng.
class CustomBoolean:
def __init__(self, value):
self.value = value
def __or__(self, other):
return CustomBoolean(self.value or other.value)
# Example usage:
obj1 = CustomBoolean(True)
obj2 = CustomBoolean(False)
result = obj1 or obj2
print(result.value)
Đầu ra của đoạn mã trên là:
True
Ở đây, đối tượng kết quả biểu thị phép toán OR logic giữa obj1 và obj2. Câu lệnh print(result.value) xuất ra True, cho biết rằng ít nhất một trong các giá trị boolean là True theo logic tùy chỉnh được xác định trong phương thức __or__.