Super функция в Python
Довольно частая ситуация в программировании, когда мы хотим переопределить какой-то метод родительского класса. И всё бы хорошо, но иногда требуется сохранить поведение родителя. Вот здесь возникает проблема: "Копировать код из родительского класса или же выносить в другую функцию?" Предположим, что у нас есть следующий класс:
class ParentClass: def __init__(self, arg1, arg2): self.arg1 = arg1 self.arg2 = arg2
Допустим мы хотим сделать его потомка, у которого первые 2 аргумента конструктора такие же, но ещё есть третий.
class ChildClass(ParentClass): def __init__(self, arg1, arg2, arg3): self.arg3 = arg3
Мы обработали новый аргумент arg3. Но что делать с arg1 и arg2? Можно просто скопировать код из ParentClass, но что если мы там что-то потом изменим и эти аргументы надо будет обрабатывать по-другому?
В питоне есть функция super, которая призвана решить эту проблему. В общем виде, она используется так: super(subclass, obj), где obj - объект, а subclass - его класс. Возвращает эта функция промежуточный объект, который является тем же объектом, но в котором все свойства и методы заменены на "родительские". С тем приоритетом, который указан при объявлении класса(выше у того класса, который указан раньше).
Функция-то хорошая, а при чём тут наша задача?
Ответ: мы можем в переопределении метода воспользоваться ей, сохраняя родительское поведение, а потом дописать то, что добавляется. ChildClass из примера выше с применением функции super:
class ChildClass(ParentClass): def __init__(self, arg1, arg2, arg3): super(ChildClass, self).__init__(arg1, arg2) self.arg3 = arg3
Таким образом, мы на нашем объекте ChildClass явно вызываем родительский конструктор, сохраняя поведение ParentClass, а потом дополняем тем функционалом, который требуется.
Можем проверить, что это работает, как требуется:
c = ChildClass(1, 2, 3) print(c.arg1) # 1 print(c.arg2) # 2 print(c.arg3) # 3
Всё именно так, как и должно быть, верно? Напоминаю, что если родительских классов несколько, то будет взят метод того класса, в котором он определён раньше. Ещё с 3 версии питона, можно заменять super(subclass, obj) на просто super(), если действие происходит внутри класса. Наш код примет следующий финальный вид:
class ChildClass(ParentClass): def __init__(self, arg1, arg2, arg3): super().__init__(arg1, arg2) self.arg3 = arg3
Просто и красиво. Надеюсь, что статья была вам полезна.