Что такое магические методы в Python и как их использовать

Одной из менее известных, но ценных возможностей Python является возможность реализации магических методов для объектов. Используя волшебные методы, мы можем писать более чистый, интуитивно понятный и простой для понимания код.

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

Что такое магические методы?

Магические методы — это методы Python, которые определяют поведение объектов Python при выполнении над ними обычных операций. Эти методы четко определены двойным подчеркиванием до и после имени метода.

В результате их обычно называют методами dunder, например, двойным подчеркиванием. Распространенный метод dunder, с которым вы, возможно, уже сталкивались, — это метод __init__(), который используется для определения конструкторов классов.

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

Почему магические методы полезны?

Магические методы — полезная концепция объектно-ориентированного программирования в Python. Используя их, вы указываете поведение ваших пользовательских типов данных, когда они используются с общими встроенными операциями. Эти операции включают в себя:

🟢 Арифметические операции

🟢 Операции сравнения

🟢 Операции жизненного цикла

🟢 Представительские операции

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

Как определить магические методы

Как упоминалось ранее, магические методы определяют поведение объектов. Таким образом, они определяются как часть класса объекта. Поскольку они являются частью класса объектов, они принимают в качестве первого аргумента self, который является ссылкой на сам объект.

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

Выполнение

Многое из того, что мы до сих пор обсуждали, кажется теоретическим и абстрактным. В этом разделе мы реализуем простой класс Rectangle.

Этот класс будет иметь свойства длины и ширины. Используя метод __init__, вы можете указать эти свойства при создании экземпляра. Кроме того, вы сможете сравнивать разные прямоугольники, чтобы увидеть, равен ли он, меньше или больше другого, используя операторы ==, < и >. Наконец, прямоугольник должен обеспечивать осмысленное строковое представление.

Настройка среды кодирования

Чтобы следовать этому пошаговому руководству, вам потребуется среда выполнения Python. Вы можете использовать локальный или онлайн-компилятор toadmin.ru Python.

Создание класса прямоугольника

Во-первых, давайте начнем с определения класса Rectangle.

class Rectangle:
    pass

Создание метода конструктора

Далее давайте создадим наш первый магический метод, метод конструктора класса. Этот метод принимает высоту и ширину и сохраняет их как атрибуты экземпляра класса.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

Создание магического метода для представления строк

Затем мы хотим создать метод, который позволит нашему классу генерировать удобочитаемую строку для представления объекта. Этот метод будет вызываться всякий раз, когда мы вызываем функцию str(), передавая в качестве аргумента экземпляр класса Rectangle. Этот метод также будет вызываться при вызове функций, ожидающих строковый аргумент, таких как функция печати.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

Метод __str__() должен возвращать строку, которую вы хотели бы представить для объекта. В этом случае мы возвращаем строку формата Rectangle(, ), где высота и ширина — это сохраненные размеры прямоугольника.

Создание магических методов для операций сравнения

Затем мы хотим создать операторы сравнения для операций «равно», «меньше» и «больше». Это называется перегрузкой оператора. Для их создания мы используем магические методы __eq__, __lt__ и __gt__ соответственно. Эти методы возвращают логическое значение после сравнения площадей прямоугольников.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

    def __eq__(self, other):
        """ Checking for equality """
        return self.height * self.width == other.height * other.width

    def __lt__(self, other):
        """ Checking if the rectangle is less than the other one """
        return self.height * self.width < other.height * other.width

    def __gt__(self, other):
        """ Checking if the rectage is greater than the other one """
        return self.height * self.width > other.height * other.width

Как видите, эти методы принимают два параметра. Первый — это текущий прямоугольник, а второй — другое значение, с которым он сравнивается. Это значение может быть другим экземпляром Rectangle или любым другим значением. Логика того, как сравнение и условия, при которых сравнение вернет true, полностью зависят от вас.

Общие магические методы

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

№1. Арифметические операции

Магические арифметические методы вызываются, когда экземпляр вашего класса помещается слева от арифметического знака. Метод будет вызываться с двумя аргументами, первый из которых будет ссылкой на экземпляр. Второе значение — это объект справа от знака. Способы и признаки следующие:

NameMethodSignDescriptionAddition__add__+Реализует добавление. Subtraction__sub__ – реализует вычитание.Multiplication__mul__*Реализует multiplicationDivision__div__/Реализует деление.Floor Division__floordiv__//Реализует деление этажа.

№ 2. Операции сравнения

Подобно магическим арифметическим методам, эти методы вызываются, когда экземпляр класса, для которого они определены, помещается слева от оператора сравнения. Также, как и арифметические магические методы, они вызываются с двумя параметрами; первый является ссылкой на экземпляр объекта. Второй является ссылкой на значение справа от знака.

NameMethodSignDescriptionLess than__lt__<Реализует сравнение меньше, чем больше, чем__gt__>Реализует сравнение, больше, чемEqual to__eq__==Реализует сравнение, равное меньше или равно__le__>=Реализует сравнение, меньше или равно,больше или равно__ge__<=Реализует сравнение, которое больше или равно сравнение

№3. Операции жизненного цикла

Эти методы будут вызываться в ответ на различные методы жизненного цикла объекта, такие как создание экземпляра или удаление. Конструктор __init__ подпадает под эту категорию. Общие методы этой категории перечислены в таблице ниже:

NameMethodDescriptionConstructor__init__Этот метод вызывается всякий раз, когда объект класса, для которого он определен, удаляется. Его можно использовать для выполнения действий по очистке, таких как закрытие любых файлов, которые он открыл. Удаление__del__Этот метод вызывается всякий раз, когда объект класса, для которого он определен, удаляется. Его можно использовать для выполнения действий по очистке, таких как закрытие любых файлов, которые он открыл. New__new__Метод __new__ вызывается первым, когда создается экземпляр объекта указанного класса. Этот метод вызывается перед конструктором и принимает класс, а также любые дополнительные аргументы. Он возвращает экземпляр класса. По большей части это не слишком полезно, но подробно описано здесь.

№ 4. Представительские операции

NameMethodDescriptionStr__str__Возвращает удобочитаемое строковое представление объекта. Этот метод вызывается, когда вы вызываете функцию str(), передавая экземпляр класса в качестве аргумента. Он также вызывается, когда вы передаете экземпляр функциям print() и format(). Он предназначен для предоставления строки, понятной конечному пользователю приложения. Repr__repr__Возвращает строковое представление объекта, используемого разработчиком. В идеале возвращаемая строка должна быть информативной, чтобы вы могли создать идентичный экземпляр объекта только из строки.

Лучшие практики для создания магических методов

Волшебные методы невероятны и упростят ваш код. Однако при их использовании важно помнить о следующих вещах.

  • Используйте их с осторожностью. Использование слишком большого количества магических методов в ваших классах делает ваш код трудным для понимания. Ограничьтесь выполнением только самых необходимых.
  • Убедитесь, что вы понимаете влияние на производительность таких методов, как __setatrr__ и __getattr__, прежде чем использовать их.
  • Документируйте поведение ваших магических методов, чтобы другие разработчики могли точно знать, что они делают. Это упрощает их использование и отладку при необходимости.

Заключительные слова

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

Далее вы можете узнать, как реализовать класс Counter в Python.