Nạp chồng toán tử trong Python: Một tính năng thú vị và hữu ích

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.

Ví dụ về nạp chồng toán tử Python

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

Làm cách nào để nạp chồng toán tử trong Python?

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.

Nạp chồng toán tử “+” nhị phân trong Python

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).

Quá tải toán tử hoạt động như thế nào?

Ý 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:

  1. Nhân một đối tượng với một số vô hướng
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
  1. Biểu diễn chuỗi
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

Nạp chồng các toán tử so sánh trong Python

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.

Quá tải đẳng thức và ít hơn toán tử

1. Quá tải “<” Nhà điều hành

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.

2. Nạp chồng toán tử đẳng thức

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.

Các phương thức ma thuật của Python hoặc các hàm đặc biệt để nạp chồng toán tử

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:

1) Toán tử nhị phân

Nhà điều hànhTên người vận hànhPhương pháp kỳ diệuSự 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>>C2C1.__rshift__(C2)
<<Dịch chuyển trái theo bit__lshift__(bản thân, người khác)C1<<C2C1.__lshift__(C2)
&Theo bit VÀ__và__(bản thân, người khác)C1&C2C1.__và__(C2)
TÔITheo bit HOẶC__hoặc__(bản thân, người khác)C1IC2C1.__hoặc__(C2)
^XOR theo bit__xor__(bản thân, người khác)C1^C2C1.__xor__(C2)

2) Toán tử gán

Nhà điều hànhTên người vận hànhPhương pháp kỳ diệuSự biểu lộCuộc gọi nội bộ
=Trừ VÀ__isub__(bản thân, người khác)C1-=C2C1.__isub__(C2)
+=Thêm VÀ__iadd__(bản thân, người khác)C1+=C2C1.__tốt__(C2)
*=Nhân VÀ__imul__(bản thân, người khác)C1*=C2C1.__imul__(C2)
/=Chia VÀ__idiv__(bản thân, người khác)C1/=C2C1.__idiv__(C2)
//=Chia(sàn) VÀ__ifloordiv__(bản thân, người khác)C1//=C2C1.__ifloordiv__(C2)
%=mô đun VÀ__chống lại__(bản thân, người khác)C1%=C2C1.__chống lại__(C2)
**=Số mũ VÀ__ipow__(bản thân, người khác)C1**=C2C1.__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>>=C2C1.__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<<=C2C1.__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&=C2C1.__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ácC1I=C2C1.__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^=C2C1.__ixor__(C2)

3) Toán tử đơn nhất

Nhà điều hànhTên người vận hànhPhương pháp kỳ diệuSự biểu lộCuộc gọi nội bộ
Đơn nhất Plus__neg__(bản thân)-C1C1.__neg__()
+Điểm trừ đơn nhất__pos__(tự)+C1C1.__pos__()
~Đảo ngược đơn nhất__đảo ngược__(tự)~C1C1.__ đảo__()

Quá tải toán tử trên các giá trị Boolean

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__.

Thuận lợi

  • Logic tùy chỉnh: Nạp chồng toán tử trong Python cho phép bạn triển khai logic cụ thể cho lớp của mình bằng cách sử dụng toán tử Boolean. Việc tùy chỉnh này có thể giúp tạo ra mã trực quan và biểu cảm hơn.
  • Khả năng đọc: Bằng cách nạp chồng các toán tử Boolean, bạn có thể tạo mã đọc giống ngôn ngữ tự nhiên hơn, giúp bạn dễ hiểu mục đích của các thao tác hơn.
  • Tính nhất quán: Nạp chồng toán tử trong Python giúp duy trì tính nhất quán trong cơ sở mã của bạn, đặc biệt là khi xử lý các lớp tùy chỉnh. Nó đảm bảo rằng các hoạt động logic hoạt động theo cách nhất quán với phần còn lại của ứng dụng của bạn.
  • Tính trừu tượng: Nạp chồng toán tử trong Python cho phép bạn trừu tượng hóa logic phức tạp trong lớp của mình, cung cấp giao diện rõ ràng hơn cho người dùng lớp của bạn.

#python 

Nạp chồng toán tử trong Python: Một tính năng thú vị và hữu ích
1.05 GEEK