Функции и операторы перегрузки в Python

Что такое перегрузка? Перегрузка в контексте программирования относится к способности функции или оператора вести себя по-разному в зависимости от параметров, которые передаются в функцию, или операндов, на которые действует оператор. В этой статье мы увидим, как мы можем выполнять перегрузку функций и операторов в Python. Перегрузка метода способствует повторному использованию. Например, вместо того, чтобы писать несколько методов, которые незначительно отличаются, мы можем написать один метод и

Что такое перегрузка?

Перегрузка в контексте программирования относится к способности функции или оператора вести себя по-разному в зависимости от параметров, которые передаются в функцию, или операндов, на которые действует оператор. В этой статье мы увидим, как мы можем выполнять перегрузку функций и операторов в Python.

Перегрузка метода способствует повторному использованию. Например, вместо того, чтобы писать несколько методов, которые незначительно отличаются, мы можем написать один метод и перегрузить его. Перегрузка также улучшает ясность кода и устраняет сложность.

Перегрузка - очень полезная концепция. Однако он имеет ряд недостатков. Перегрузка может вызвать путаницу при использовании через границы наследования. При чрезмерном использовании становится неудобно управлять перегруженными функциями.

В оставшейся части этой статьи мы подробно обсудим перегрузку функций и операторов.

Перегрузка функций в Python

В зависимости от того, как была определена функция, мы можем вызывать ее с нулем, одним, двумя или даже многими параметрами. Это называется «перегрузкой функции».

Перегрузка функций далее делится на два типа: перегрузка встроенных функций и перегрузка пользовательских функций. Мы рассмотрим оба типа в следующих разделах.

Перегрузка встроенных функций

Мы можем изменить поведение встроенных функций Python по умолчанию. Нам нужно только определить соответствующий специальный метод в нашем классе.

Давайте продемонстрируем это с помощью функции Python len() в нашем классе Purchase:

 class Purchase: 
 def __init__(self, basket, buyer): 
 self.basket = list(basket) 
 self.buyer = buyer 
 
 def __len__(self): 
 return len(self.basket) 
 
 purchase = Purchase(['pen', 'book', 'pencil'], 'Python') 
 print(len(purchase)) 

Выход:

 3 

Чтобы изменить поведение функции len() , мы определили в нашем классе специальный метод с именем _len_() Каждый раз, когда мы передаем объект нашего класса в len() , результат будет получен путем вызова нашей пользовательской функции, то есть _len_() .

Вывод показывает, что мы можем использовать len() для получения длины корзины.

Если мы вызовем len() для объекта без __len__() , мы получим TypeError, как показано ниже:

 class Purchase: 
 def __init__(self, basket, buyer): 
 self.basket = list(basket) 
 self.buyer = buyer 
 
 purchase = Purchase(['pen', 'book', 'pencil'], 'Python') 
 print(len(purchase)) 

Выход:

 Traceback (most recent call last): 
 File "C:/Users/admin/func.py", line 8, in <module> 
 print(len(purchase)) 
 TypeError: object of type 'Purchase' has no len() 

Примечание. Python ожидает, что len() вернет целое число, поэтому это следует учитывать при перегрузке функции. Если ожидается, что ваша перегруженная функция вернет что-либо еще, кроме целого числа, вы получите ошибку TypeError.

Мы можем изменить поведение метода len() в приведенном выше примере из определения его реализации, то есть __len__() . Вместо того, чтобы возвращать длину корзины, давайте сделаем так, чтобы она возвращала что-то другое:

 class Purchase: 
 def __init__(self, basket, buyer): 
 self.basket = list(basket) 
 self.buyer = buyer 
 
 def __len__(self): 
 return 10; 
 
 purchase = Purchase(['pen', 'book', 'pencil'], 'Python') 
 print(len(purchase)) 

Выход:

 10 

Вместо того, чтобы возвращать длину корзины, теперь возвращается указанное нами значение.

Перегрузка пользовательских функций

Чтобы перегрузить пользовательскую функцию в Python, нам нужно написать логику функции таким образом, чтобы в зависимости от переданных параметров внутри функции выполнялся другой фрагмент кода. Взгляните на следующий пример:

 class Student: 
 def hello(self, name=None): 
 if name is not None: 
 print('Hey ' + name) 
 else: 
 print('Hey ') 
 
 # Creating a class instance 
 std = Student() 
 
 # Call the method 
 std.hello() 
 
 # Call the method and pass a parameter 
 std.hello('Nicholas') 

Выход:

 Hey 
 Hey Nicholas 

Мы создали класс Student с одной функцией hello() . name параметра, для которого установлено значение None . Это означает, что метод можно вызывать с параметром или без него.

Мы создали экземпляр класса, который использовался для вызова функции дважды, сначала с нулевыми параметрами, а затем с одним параметром. Мы реализовали перегрузку функции, поскольку есть два способа вызвать функцию.

Теперь мы знаем, как работает перегрузка функций, следующий раздел посвящен перегрузке операторов.

Перегрузка оператора

Python позволяет нам изменять поведение оператора по умолчанию в зависимости от используемых нами операндов. Эта практика называется «перегрузкой оператора».

Функциональность операторов Python зависит от встроенных классов. Однако один и тот же оператор будет вести себя по-разному при применении к разным типам. Хороший пример - оператор «+». Этот оператор выполняет арифметическую операцию при применении к двум числам, объединяет две строки и объединяет два списка.

Примеры перегрузки оператора

Чтобы увидеть перегрузку оператора Python в действии, запустите терминал Python и выполните следующие команды:

 >>> 4 + 4 
 8 
 >>> "Py" + "thon" 
 'Python' 

В первой команде мы использовали оператор «+», чтобы сложить два числа. Во второй команде мы использовали один и тот же оператор для объединения двух строк.

В этом случае оператор «+» имеет две интерпретации. Когда используется для сложения чисел, он называется «оператором сложения». Когда он используется для добавления строк, он называется «оператором конкатенации». Короче говоря, можно сказать, что оператор «+» был перегружен для классов int и str

Чтобы добиться перегрузки оператора, мы определяем специальный метод в определении класса. Имя метода должно начинаться и заканчиваться двойным подчеркиванием (__). Оператор + перегружается с помощью специального метода __add__() . Этот метод реализуется как классами int и str

Рассмотрим следующее выражение:

 x + y 

Python интерпретирует выражение как x.__add__(y) . Вызываемая версия __add__() будет зависеть от типов x и y . Например:

 >>> x, y = 5, 7 
 
 >>> x + y 
 
 12 
 >>> x.__add__(y) 
 12 
 >>> 

В приведенном выше примере показано, как использовать оператор +, а также его специальный метод.

В следующем примере показано, как перегружать различные операторы в Python:

 import math 
 
 class Point: 
 
 def __init__(self, xCoord=0, yCoord=0): 
 self.__xCoord = xCoord 
 self.__yCoord = yCoord 
 
 # get x coordinate 
 def get_xCoord(self): 
 return self.__xCoord 
 
 # set x coordinate 
 def set_xCoord(self, xCoord): 
 self.__xCoord = xCoord 
 
 # get y coordinate 
 def get_yCoord(self): 
 return self.__yCoord 
 
 # set y coordinate 
 def set_yCoord(self, yCoord): 
 self.__yCoord = yCoord 
 
 # get current position 
 def get_position(self): 
 return self.__xCoord, self.__yCoord 
 
 # change x & y coordinates by p & q 
 def move(self, p, q): 
 self.__xCoord += p 
 self.__yCoord += q 
 
 # overload + operator 
 def __add__(self, point_ov): 
 return Point(self.__xCoord + point_ov.__xCoord, self.__yCoord + point_ov.__yCoord) 
 
 # overload - operator 
 def __sub__(self, point_ov): 
 return Point(self.__xCoord - point_ov.__xCoord, self.__yCoord - point_ov.__yCoord) 
 
 # overload < (less than) operator 
 def __lt__(self, point_ov): 
 return math.sqrt(self.__xCoord ** 2 + self.__yCoord ** 2) < math.sqrt(point_ov.__xCoord ** 2 + point_ov.__yCoord ** 2) 
 
 # overload > (greater than) operator 
 def __gt__(self, point_ov): 
 return math.sqrt(self.__xCoord ** 2 + self.__yCoord ** 2) > math.sqrt(point_ov.__xCoord ** 2 + point_ov.__yCoord ** 2) 
 
 # overload <= (less than or equal to) operator 
 def __le__(self, point_ov): 
 return math.sqrt(self.__xCoord ** 2 + self.__yCoord ** 2) <= math.sqrt(point_ov.__xCoord ** 2 + point_ov.__yCoord ** 2) 
 
 # overload >= (greater than or equal to) operator 
 def __ge__(self, point_ov): 
 return math.sqrt(self.__xCoord ** 2 + self.__yCoord ** 2) >= math.sqrt(point_ov.__xCoord ** 2 + point_ov.__yCoord ** 2) 
 
 # overload == (equal to) operator 
 def __eq__(self, point_ov): 
 return math.sqrt(self.__xCoord ** 2 + self.__yCoord ** 2) == math.sqrt(point_ov.__xCoord ** 2 + point_ov.__yCoord ** 2) 
 
 point1 = Point(2, 4) 
 point2 = Point(12, 8) 
 
 print("point1 < point2:", point1 < point2) 
 print("point1 > point2:", point1 > point2) 
 print("point1 <= point2:", point1 <= point2) 
 print("point1 >= point2:", point1 >= point2) 
 print("point1 == point2:", point1 == point2) 

Выход:

 point1 < point2: True 
 point1 > point2: False 
 point1 <= point2: True 
 point1 >= point2: False 
 point1 == point2: False 

У нас есть два частных атрибута в классе Point, а именно __xCoord и __yCoord представляющие декартовы простые координаты с именами xCoord и yCoord . Мы определили методы установки и получения для этих атрибутов. Метод get_position() помогает нам получить текущую позицию, а метод move() помогает нам изменять координаты.

Рассмотрим следующую строку, извлеченную из кода:

 def __add__(self, point_ov): 

Строка помогает нам перегрузить оператор + для нашего класса. Метод __add__() должен создать новый объект Point, добавив отдельные координаты одного объекта Point к другому объекту Point. Наконец, он возвращает вызывающему объекту вновь созданный объект. Это помогает нам писать такие выражения, как:

 point3 = point1 + point2 

Python интерпретирует вышесказанное как point3 = point1.__add__(point2) . Затем он вызовет метод __add__() для добавления двух объектов Point. Результат будет присвоен «point3».

Обратите внимание, что после вызова метода __add__() point1 будет присвоено self а значение point2 будет присвоено параметру point_ov Все остальные специальные методы работают аналогичным образом.

Операторы к перегрузке

В следующей таблице показаны некоторые из наиболее часто перегружаемых математических операторов и метод класса для перегрузки:

Оператор Методика


+ __add__(self, other) - __sub__(self, other) * __mul__(self, other) / __truediv__(self, other) % __mod__(self, other) < __lt__(self, other) <=< code> __le__(self, other) == __eq__(self, other) != __ne__(self, other) > __gt__(self, other) >= __ge__(self, other)

Заключение

Python поддерживает перегрузку как функций, так и операторов. При перегрузке функций мы можем использовать одно и то же имя для многих функций Python, но с другим количеством или типами параметров. С помощью перегрузки оператора мы можем изменить значение оператора Python в рамках класса.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus