Nạp chồng toán tử Python

Bạn có thể thay đổi ý nghĩa của một toán tử trong Python tùy thuộc vào các toán hạng được sử dụng. Trong hướng dẫn này, bạn sẽ học cách sử dụng nạp chồng toán tử trong Lập trình hướng đối tượng Python.

Nạp chồng toán tử Python

Các toán tử Python hoạt động đối với các lớp dựng sẵn. Nhưng cùng một toán tử hoạt động khác nhau với các kiểu khác nhau. Ví dụ, +toán tử sẽ thực hiện phép cộng số học trên hai số, hợp nhất hai danh sách hoặc nối hai chuỗi.

Tính năng này trong Python cho phép cùng một toán tử có nghĩa khác nhau tùy theo ngữ cảnh được gọi là nạp chồng toán tử.

Vậy điều gì sẽ xảy ra khi chúng ta sử dụng chúng với các đối tượng của một lớp do người dùng định nghĩa? Chúng ta hãy xem xét lớp sau, lớp này cố gắng mô phỏng một điểm trong hệ tọa độ 2-D.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Đầu ra

 Traceback (lần gọi gần đây nhất): Tệp "", dòng 9, in (p1 + p2) TypeError: (các) loại toán hạng không được hỗ trợ cho +: 'Point' và 'Point'

Ở đây, chúng ta có thể thấy rằng a TypeErrorđã được nâng lên, vì Python không biết cách thêm hai Pointđối tượng lại với nhau.

Tuy nhiên, chúng ta có thể đạt được nhiệm vụ này trong Python thông qua việc nạp chồng toán tử. Nhưng trước tiên, chúng ta hãy có một khái niệm về các chức năng đặc biệt.

Các hàm đặc biệt của Python

Các hàm lớp bắt đầu bằng dấu gạch dưới kép __được gọi là các hàm đặc biệt trong Python.

Các hàm này không phải là các hàm điển hình mà chúng ta định nghĩa cho một lớp. Các __init__()chức năng chúng ta định nghĩa ở trên là một trong số họ. Nó được gọi mỗi khi chúng ta tạo một đối tượng mới của lớp đó.

Có rất nhiều hàm đặc biệt khác trong Python. Truy cập Các hàm đặc biệt của Python để tìm hiểu thêm về chúng.

Sử dụng các hàm đặc biệt, chúng ta có thể làm cho lớp của mình tương thích với các hàm tích hợp sẵn.

 >>> p1 = Point(2,3) >>> print(p1) 

Giả sử chúng ta muốn print()hàm in ra tọa độ của Pointđối tượng thay vì những gì chúng ta nhận được. Chúng ta có thể định nghĩa một __str__()phương thức trong lớp của chúng ta để điều khiển cách đối tượng được in. Hãy xem cách chúng ta có thể đạt được điều này:

 class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x,self.y)

Bây giờ chúng ta hãy thử lại print()chức năng.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0), (1))".format(self.x, self.y) p1 = Point(2, 3) print(p1)

Đầu ra

 (2, 3)

Cái đó tốt hơn. Hóa ra, phương thức tương tự này được gọi khi chúng ta sử dụng hàm tích hợp sẵn str()hoặc format().

 >>> str(p1) '(2,3)' >>> format(p1) '(2,3)'

Vì vậy, khi bạn sử dụng str(p1)hoặc format(p1), Python gọi nội bộ p1.__str__()phương thức. Do đó tên, chức năng đặc biệt.

Bây giờ chúng ta hãy quay trở lại quá tải toán tử.

Quá tải + Toán tử

Để nạp chồng +toán tử, chúng ta sẽ cần triển khai __add__()hàm trong lớp. Với sức mạnh lớn đến trách nhiệm lớn. Chúng ta có thể làm bất cứ điều gì chúng ta thích, bên trong chức năng này. Nhưng sẽ hợp lý hơn nếu trả về một Pointđối tượng của tổng tọa độ.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)

Bây giờ hãy thử lại thao tác thêm:

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y) p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Đầu ra

 (3,5)

Điều thực sự xảy ra là khi bạn sử dụng p1 + p2, Python sẽ gọi p1.__add__(p2)lần lượt là như vậy Point.__add__(p1,p2). Sau đó, hoạt động bổ sung được thực hiện theo cách chúng tôi đã chỉ định.

Tương tự, chúng ta cũng có thể quá tải các toán tử khác. Chức năng đặc biệt mà chúng ta cần thực hiện được lập bảng dưới đây.

Nhà điều hành Biểu hiện Nội bộ
Thêm vào p1 + p2 p1.__add__(p2)
Phép trừ p1 - p2 p1.__sub__(p2)
Phép nhân p1 * p2 p1.__mul__(p2)
Quyền lực p1 ** p2 p1.__pow__(p2)
Sư đoàn p1 / p2 p1.__truediv__(p2)
Phân chia tầng p1 // p2 p1.__floordiv__(p2)
Phần còn lại (modulo) p1 % p2 p1.__mod__(p2)
Dịch chuyển sang trái theo chiều bit p1 << p2 p1.__lshift__(p2)
Chuyển sang phải theo chiều bit p1>> p2 p1.__rshift__(p2)
Bitwise VÀ p1 & p2 p1.__and__(p2)
Bitwise HOẶC p1 | p2 p1.__or__(p2)
Bitwise XOR p1 p2 p1.__xor__(p2)
Bitwise KHÔNG ~p1 p1.__invert__()

Quá tải các toán tử so sánh

Python không giới hạn việc nạp chồng toán tử chỉ với các toán tử số học. Chúng ta cũng có thể quá tải các toán tử so sánh.

Giả sử chúng ta muốn triển khai biểu <tượng less than trong Pointlớp của chúng ta .

Hãy để chúng tôi so sánh độ lớn của những điểm này từ điểm gốc và trả về kết quả cho mục đích này. Nó có thể được thực hiện như sau.

 # overloading the less than operator class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __lt__(self, other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag p1 = Point(1,1) p2 = Point(-2,-3) p3 = Point(1,-1) # use less than print(p1 

Output

 True False False

Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.

Operator Expression Internally
Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2)
Not equal to p1 != p2 p1.__ne__(p2)
Greater than p1> p2 p1.__gt__(p2)
Greater than or equal to p1>= p2 p1.__ge__(p2)

thú vị bài viết...