Синтаксис
Расширение функционала стандартного списка:
Множественное наследование
Если мы явно не наследуем класс от какого-либо другого класса, то класс наследуется от Object.
Для того чтобы понять для двух конкретных классов кто является предком, а кто является наследником кого-то, проще всего использовать функцию issubclass:
Функция isinstance позволяет узнать ведет ли себя объект как экземпляр какого-либо класса:
Функция isinstance проверяет является ли тип type(первый_аргумент) наследником второго аргумента. |
Когда мы вызываем функцию isinstance с каким-то объектом и с каким-то типом, мы спрашиваем у интерпретатора, можем ли мы использовать данный объект в качестве объекта данного типа.
Порядок разрешения методов
Когда мы не использовали множественное наследование всё было достаточно просто. Сначала мы пытаемся найти метод, как атрибут экземпляра. Затем пытаемся найти функцию в соответствующем классе. Если не нашли, то бежим вверх по иерархии класса, до тех пор пока не найдем. А если не найдем, то завершаем исполнение с ошибкой.
При вызове у x метода extend, мы сначала бы посмотрели бы является ли метод extend атрибутом самого экземпляра x - нет не является. Потом мы бы посмотрели в классе MyList - нет, не является, потому что в MyList одна функция even_length. А затем мы пошли проверили класс list и нашли бы его там, потому что extend определенный метод у list. А вот если бы мы в list его не нашли, то на самом деле мы бы пошли дальше посмотрели в object - не нашли бы его в object и тогда бы сказали, что мы вызвали плохой метод и у x нет такого метода.
Стоит заметить, что мы воспользовались методами списка сильно раньше. Прежде всего, когда мы запустили для нашего экземпляра x конструктор MyList. Каждый раз когда интерпретатор видит конструктор, он пытается найти внутри этого класса найти метод __init__, чтобы проинициализировать тот экземпляр, который создается. Т.к. метод __init__ не находится в классе MyList потому что мы его здесь не определили, то он находится выше в нашем классе list.
Когда мы вызываем print для какого-нибудь экземпляра, то интерпретатор пытается найти внутри этого экземпляра метод __repr__(self), который возвращает строковое представление объекта, которое мы будем выводить. И когда мы не находим этот метод в MyList, мы идем в list и находим его там.
Очень важно понимать порядок в котором мы перебираем классы, когда ищем функцию чтобы связать её с методом. Особенно сильно это важно в том случае, когда мы используем множественное наследование.
Пускай наш класс MyList наследуется не только от list, но еще и от какого-нибудь класса. Тогда становится нетривиальным вопрос, если мы вызываем x.method_name(), то в каком порядке мы должны перебрать классы, когда ищем функцию чтобы сопоставить ее нашему методу. Сначала мы перебрали x, затем мы должны перебрать object или другой класс?
Для разрешения подобных конфликтов в языке Python есть порядок разрешения методов. Порядок разрешения методов определяется в момент создания класса. В языке Python мы можем вывести его с помощью метода method resolution order - mro, который есть у любого класса. Он выводит список классов, в том порядке в котором мы бы искали метод.
Порядок разрешения методов гарантирует, что каждый предок нашего класса будет в этом порядке всего лишь в единственном числе. Также если мы наследовали класс от A и B, то в нашем порядке сначала будет A и потом B, необязательно, что сразу.
Реализация MyList с множественным наследованием:
Использование примеси (mixin) позволяет в качестве класса к которому мы добавляем функциональность подойдет любой класс у которого есть длина. Например вместо списка мы можем использовать словарь или строку.
Языки Программирования: Наследование Классов В Языке Python >>>>> Download Now
ОтветитьУдалить>>>>> Download Full
Языки Программирования: Наследование Классов В Языке Python >>>>> Download LINK
>>>>> Download Now
Языки Программирования: Наследование Классов В Языке Python >>>>> Download Full
>>>>> Download LINK VX