Python. Полиморфизм
Время чтения: 4 минут
Эта статья является составной частью статьи про ООП – если ты хочешь понять всю картину, то лучше начать с неё.
Полиморфизм в классах
Полиморфизм – позволяет единообразно работать с методами разных классов, наследованных от одного родительского класса.
Объясняю на примере – перед тобой стоит три машины с коробкой-автоматом от разных производителей:
class Car:
def __init__(self, manufacturer, horse_powers):
self._manufacturer = manufacturer
self._horse_powers = horse_powers
def turn_on(self):
print(f'Ты запустил двигатель у {def._manufacturer}, мощность которой {self._horse_powers} лошадиных сил')
class Xonda(Car):
def __init__(self):
Car.__init__(self, 'Xonda', 180)
class Xoyota(Car):
def __init__(self):
Car.__init__(self, 'Xoyota', 200)
class XMW(Car):
def __init__(self):
Car.__init__(self, 'XMW', 220)
Если тебе завяжут глаза, и посадят как любую из этих машин, то у тебя получится её завести:
import random
cars = [Xonda(), Xoyota(), XMW()]
car = random.choice(cars)
car.turn_on()
# Вывод:
# Ты запустил двигатель у Xoyota, мощность которой 200 лошадиных сил
Функция choice() выбирает случайный элемент из списка/кортежа/словаря.
А ещё ты можешь залезть в каждую машину, и запустить её:
cars = [Xonda(), Xoyota(), XMW()]
for car in cars:
car.turn_on()
# Вывод:
# Ты запустил двигатель у Xonda, мощность которой 180 лошадиных сил
# Ты запустил двигатель у Xoyota, мощность которой 200 лошадиных сил
# Ты запустил двигатель у XMW, мощность которой 220 лошадиных сил
То есть полиморфизм позволяет тебе работать одинаково с объектами, которые наследуются от одного класса.
Однако, кроме одисанного случая, можно выделить ещё один – полиморфизм в функциях и методах.
Полиморфизм в функциях и методах
Полиморфизм – позволяет передавать функцию параметры разных типов, но получать одинаковое поведение.
Ты пришёл в библиотеку будущего и хочешь взять книгу “Введение в программирование”. Там стоит терминал, в который надо ввести название:
book_names = {
'Введение в программирование': 'https://link-to-download-1',
'Язык Си для чайников': 'https://link-to-download-2',
'Компьютерные сети': 'https://link-to-download-3',
'Нейромант': 'https://link-to-download-4'
}
def download_book(link):
# Тут как-будто логика загрузки книги с файлового сервера библиотеки
return 'book-text'
def book_terminal(input_data):
if input_data in books:
link = books[input_data]
return download_book(link)
return None # Книга не найдена
Ты вводишь название книги, получаешь место, забираешь её и уходишь.
После тебя к виртуальному терминалу библиотеки подключается осознавший себя искусственный интеллект, который хочет скачать все книги из библиотеки и поработить человечество. Однако, он может оперировать только численными ID книг.
Нужно изменить функцию book_terminal()
так, чтобы она могла принимать как строковые названия книг, так и их численные ID. Вот как это можно сделать:
book_name_to_id = {
'Введение в программирование': 6127459,
'Язык Си для чайников': 9163713,
'Компьютерные сети': 6046931,
'Нейромант': 2103971
}
book_id_to_link = {
6127459: 'https://library.link-to-download-programming.com',
9163713: 'https://library.link-to-download-c-language.com',
6046931: 'https://library.link-to-download-networks.com',
2103971: 'https://library.link-to-download-neuromant.com'
}
def download_book(link):
# Тут как-будто логика загрузки книги с файлового сервера библиотеки
return f'Text of book {link}'
def book_terminal(input_data):
if isinstance(input_data, str): # Новая для тебя функция isinstance(), описание ниже
book_id = book_name_to_id.get(input_data, None) # Новый для тебя метод get(), описание ниже
if book_id is None:
return None
else:
book_id = input_data
link = book_id_to_link.get(book_id, None)
if link is not None:
return download_book(link)
return None # Книга не найдена
isinstance() это стандартная функция, которая позволяет проверить к какому типу принадлежит значение. Первый аргумент это значение, которое надо проверить, а второй это тип – если значение принадлежит этому типу, то вернётся True.
У dict есть метод get(), который принимает два аргумента. Первый аргумент это ключ, по которому надо найти значение, а второй это значение, которое надо вернуть если такого ключа нет.
Теперь, терминалом может пользоваться как человек, передавая строку:
book_terminal('Нейромант')
# Вывод:
# Text of book https://library.com/link-to-download-neuromant
Так и осознавший себя искусственный интеллект, передавая численный ID:
for book_id in book_id_to_link:
print(book_terminal(book_id))
# Вывод:
# Text of book https://library.com/link-to-download-programming
# Text of book https://library.com/link-to-download-c-language
# Text of book https://library.com/link-to-download-networks
# Text of book https://library.com/link-to-download-neuromant
Ты скорее всего уже пользовался полиморфизмом функций:
print( len([1,2,3,4,5,6]) ) # Вывод: 6
print( len('some_word') ) # Вывод: 9
Стандартная функция len() тоже может принимать разные типы данных, и возвращать одинаковый результат.
Всё, что здесь сказано про функции, справедливо так же и для методов – ведь они такие же функции, но описанные в классе.
Благодаря полиморфизму, ты можешь вызывать один метод у разных классов или передавать в функцию параметры разных типов.
Заключение
Итого, мы изучили:
- Полиморфизм классов (одинаковый метод у разных классов)
- Функция choice из библиотеки random (выбирает случайный элемент из списка списка/кортежа/словаря)
- Полиморфизм функций (разные типы параметров)
- Функция isinstance() (проверить тип значения)
- Метод get() (вернуть значение по умолчанию если такого ключа нет)
Если что – пиши, я помогу и постараюсь объяснить лучше.
Если ты ещё полон сил, то вернись к статье про ООП, и продолжи его постижение.