Skip to content

Latest commit

 

History

History
261 lines (181 loc) · 10.4 KB

File metadata and controls

261 lines (181 loc) · 10.4 KB

Магические методы, dunder-методы в Python

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

Магические методы еще называют dunder-методами.

  1. __new__(cls, arg) - Истинный конструктор класса, метод __init__ называют конструктором по привычке.

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

Этот должен возвращать экземпляр класса, то есть должен создавать обьект и возвращать его, именно этот обьект и передается в метод __init__(self) как первый аргумент self

Поскольку метод __init__() ничего не может возвращать получается что обьект создается в методе __new__ а метод __init__ просто инициализирует переменный обьекта.


Основные магические методы

  1. __init__(self) - Метод конструктор(как его обычно называют), используется для инициализации динамических атрибутов класса, запускается автоматически при создании обьекта.

    Этому методу запрещено возвращать что либо кроме None что является стандартным поведением методов и функций, любая функция что-то возвращает, и если это не переопределено то возвращает None

  2. __str(self)__ - Должен возвращать при помощи ключевого слова return строку описывающую класс, этот метод вызывается автоматически когда обьект вызывается при помощи функции print()

  3. __repr(self)__ - Должен возвращать строковое представление класса, при помощи оператора return. Используется автоматически когда на класс используется функция repr() помним что сама по себе функция repr() не выводит строку, а только ее возвращает, так что для этого следует использовать комбинацию print(repr(obj))

  4. __len__(self) - Используется автоматически при использовании метода len() на обьект, этот метод обязан возвращать целочисленное значение типа int при помощи return

Пример использования магических методов __init__, __str__, __repr__, __len__():

        class MyClass():

            def __init__(self, name, my_list):
                self.name = name
                self.my_list = my_list

            def __str__(self):
                return "Метод __str__"

            def __repr__(self):
                return "Метод __repr__"
   
            def __len__(self):
                return len(self.my_list)


        x = MyClass('Антонио', [1,2,3,4])
        print(x)
        print(repr(x))
        print(len(x))

        # Вывод
        # Метод __str__
        # Метод __repr__
        # 4
  1. __del__(self) - Метод не должен ничего возвращать, отрабатывает при уничтожении последней ссылки на обьект.
    def __del__(self):
        """
        __del__ деструктор класса, вызывается при уничтожении
        последней ссылки на обьект этого класса.
        """
        print("Отработал метод __del__ Обьект класса MyClass уничтожен")
  1. __abs__(self) отрабатывает при использовании на объект функции abs() для получения значения по модулю, может возвращать как число, так и список.

Возвращать что-либо необязательно.

  1. __hash(self)__ отрабатывает при использовании функции хеширования на объект. Если использовать функцию hash() на обычное целое число ответом будет самом же это число, но другие данные float или str ... будут преобразованы в целое число.

Поведения объектов при сравнении операторов

Эти методы определяют поведения объектов когда на них используется операторы сравнения.

Для сравнения эти методы принимают 2 параметра, self что представляет сам объект, и other что представляет другой объект.

  1. __eq__(self, other) - поведения при ==

  2. __cmp__(self, other) - этот метод определят поведение для всех операторов, этим объектом можно определить поведение всех объектов и всех их операторов.

  3. __ne__(self, other) - Определяет поведение оператора неравенства !=

  4. __lt__(self, other) - Определяет поведение оператора меньше <

  5. __gt__(self, other) - Определяет поведение оператора больше >

  6. __le__(self, other) - Определяет поведение оператора меньше или равно <=

  7. __ge__(self, other) - Определяет поведение оператора больше или равно >=

Примеры поведения, на этом примере можно увидеть как работает метод для переопределения операторов сравнения, суть такова, метод принимает 2 параметра self и other где есть собственный и дополнительный объект, а далее мы сами можем переопределить поведение, возвращаем либо True, либо False это можно увидеть на след примере:

      class Test():

       def __init__(self, name):
           self.name = name
   
       def __eq__(self, other):
           print(f"self = {len(self.name)}", self)
           print("other = ", other)
           if len(self.name) == other:
               return True
           return False
   
   
      x = Test('Names')
      print(x==5)

      # Вывод
      # self = 5 <__main__.Test object at 0x7f5ad9ddc208>
      # other =  5
      # True

Маг.Методы контроля доступа к атрибутам

  1. __getattr__(self, name) Вызывается при попытке вызова метода которого не существует.

  2. __setattr__(self, name, value) Позволяет установить новое значение для атрибута, существует он или нет.

  3. __delattr__(self, name)

  4. __getattribute__(self, name)


Спец метод __getitem__(self, key)

Метод отрабатывает когда мы обращаемся к объекту как к элементу списка, по индексу, примеру так:

    from string import ascii_letters

    class MyContainer(object):

        def __getitem__(self, key):
            print('key = ', key)
            return ascii_letters[key]

    my_container = MyContainer()
    
    print(my_container[0])  # выведет a
    print(my_container[16])  # выведет q
    print(my_container[:])  # выведет все элементы

    # Вывод
    # key =  0
    # a
    # 
    # key =  16
    # q
    # 
    # key =  slice(None, None, None)
    # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

Переменная из ascii_letters содержит в себе все буквы алфавита.


Атрибут __code__

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

    def func1(a, b):
        print(a * b)

    def testing():
        pass

    print(func1)
    print(func1.__code__)

    testing.__code__ = func1.__code__
    testing(2, 5)

    # Вывод
    # <function func4.<locals>.func1 at 0x7f70513739d8>
    # <code object func1 at 0x7f70513d5e40, file "./1.py", line 71>
    # 10

Магический метод __hash__(self)

При использовании функции hash() на данные мы по сути вызываем метод __hash__() этого объекта, ибо все данные в питоне являются объектами.

У объектов можно определить метод __hash()__ которая будет отрабатывать при использовании функции hash() на этот объект, так образом можно самим определять свои собственные функции для хеширования.