Объектно-ориентированное программирование (ООП) — это метод структурирования программы путем объединения связанных свойств и поведения в отдельные объекты. В этом уроке вы изучите основы объектно-ориентированного программирования на Python.
Концептуально объекты подобны компонентам системы. Подумайте о программе как о своего рода заводской сборочной линии. На каждом этапе сборочной линии компонент системы обрабатывает некоторый материал, в конечном счете превращая сырье в готовый продукт.
Объект содержит данные, такие как необработанные или предварительно обработанные материалы на каждом шаге сборочной линии, и поведение, такое как действие, выполняемое каждым компонентом сборочной линии.
В этом уроке вы узнаете, как:
- Создайте класс, который похож на схему создания объекта
- Используйте классы для создания новых объектов
- Модельные системы с наследованием классов
Примечание: Этот учебник адаптирован из главы “Объектно-ориентированное программирование (ООП)” в разделе Основы Python: Практическое введение в Python 3.
В книге используется встроенный редактор ПРОСТОЯ Python для создания и редактирования файлов Python и взаимодействия с оболочкой Python, поэтому в этом руководстве вы увидите случайные ссылки на IDLE. Однако у вас не должно возникнуть проблем с запуском примера кода из редактора и среды по вашему выбору.
Бесплатный бонус: Нажмите здесь, чтобы получить доступ к бесплатной шпаргалке по Python, которая укажет вам лучшие учебные пособия, видео и книги, чтобы узнать больше об объектно-ориентированном программировании на Python.
Что такое Объектно-ориентированное программирование на Python?
Объектно-ориентированное программирование-это парадигма программирования, которая предоставляет средства структурирования программ таким образом, чтобы свойства и поведение объединялись в отдельные объекты.
Например, объект может представлять человека с такими свойствами, как имя, возраст, адрес и поведение, такое как ходьба, разговор, дыхание и бег. Или это может представлять собой электронное письмо со свойствами, такими как список получателей, тема и тело, а также поведение, такое как добавление вложений и отправка.
Put another way, object-oriented programming is an approach for modeling concrete, real-world things, like cars, as well as relations between things, like companies and employees, students and teachers, and so on. OOP models real-world entities as software objects that have some data associated with them and can perform certain functions.
Другой распространенной парадигмой программирования является процедурное программирование, которое структурирует программу подобно рецепту в том смысле, что оно предоставляет набор шагов в виде функций и блоков кода, которые последовательно выполняются для выполнения задачи.
Ключевым выводом является то, что объекты находятся в центре объектно-ориентированного программирования на Python, представляя не только данные, как в процедурном программировании, но и общую структуру программы.
Определите класс в Python
Примитивные структуры данных, такие как числа, строки и списки, предназначены для представления простых элементов информации, таких как стоимость яблока, название стихотворения или ваши любимые цвета, соответственно. Что делать, если вы хотите представить что-то более сложное?
Например, предположим, вы хотите отслеживать сотрудников в организации. Вам необходимо сохранить некоторую базовую информацию о каждом сотруднике, такую как его имя, возраст, должность и год, когда он начал работать.
Один из способов сделать это-представить каждого сотрудника в виде списка:
kirk = ["James Kirk", 34, "Captain", 2265]
spock = ["Spock", 35, "Science Officer", 2254]
mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266]
С этим подходом связан ряд проблем.
Во-первых, это может затруднить управление большими файлами кода. Если вы ссылаетесь kirk[0]
на несколько строк в стороне от того места, где kirk
объявлен список, будете ли вы помнить, что элемент с индексом 0
-это имя сотрудника?
Во-вторых, это может привести к ошибкам, если не у каждого сотрудника одинаковое количество элементов в списке. В mccoy
приведенном выше списке возраст отсутствует, поэтому mccoy[1]
он вернется "Chief Medical Officer"
вместо возраста доктора Маккоя.
Отличный способ сделать этот тип кода более управляемым и более удобным в обслуживании-использовать классы.
Классы против экземпляров
Классы используются для создания пользовательских структур данных. Классы определяют функции, называемые методами, которые определяют поведение и действия, которые объект, созданный из класса, может выполнять со своими данными.
В этом уроке вы создадите Dog
класс, в котором будет храниться некоторая информация о характеристиках и поведении, которые могут быть у отдельной собаки.
Класс-это схема того, как что-то должно быть определено. На самом деле он не содержит никаких данных. Dog
Класс указывает, что имя и возраст необходимы для определения собаки, но он не содержит имени или возраста какой-либо конкретной собаки.
В то время как класс является чертежом, экземпляр-это объект, созданный на основе класса и содержащий реальные данные. Экземпляр Dog
класса больше не является чертежом. Это настоящая собака с именем, как у Майлза, которой четыре года.
Другими словами, класс похож на анкету или анкету. Экземпляр похож на форму, которая была заполнена информацией. Точно так же, как многие люди могут заполнить одну и ту же форму своей собственной уникальной информацией, многие экземпляры могут быть созданы из одного класса.
Как определить класс
Все определения классов начинаются с class
ключевого слова, за которым следует имя класса и двоеточие. Любой код, расположенный с отступом ниже определения класса, считается частью тела класса.
Вот пример Dog
класса:
class Dog:
pass
Тело Dog
класса состоит из одного оператора: pass
ключевого слова. pass
часто используется в качестве заполнителя, указывающего, куда в конечном итоге пойдет код. Это позволяет запускать этот код без того, чтобы Python выдавал ошибку.
Примечание: Имена классов Python записываются в условных обозначениях с заглавной буквы. Например, класс для определенной породы собак, таких как Джек-Рассел-терьер, будет записан как JackRussellTerrier
.
Dog
Класс сейчас не очень интересен, поэтому давайте немного его улучшим, определив некоторые свойства, которыми должны обладать все объекты. Dog
Существует ряд свойств, из которых мы можем выбрать, включая имя, возраст, окрас шерсти и породу. Чтобы все было просто, мы просто будем использовать имя и возраст.
Свойства, которыми Dog
должны обладать все объекты, определяются в вызываемом методе .__init__()
. Каждый раз, когда создается новый Dog
объект, .__init__()
задает начальное состояние объекта, присваивая значения свойствам объекта. То есть .__init__()
инициализирует каждый новый экземпляр класса.
Вы можете задать .__init__()
любое количество параметров, но первым параметром всегда будет называемая переменная self
. При создании нового экземпляра класса экземпляр автоматически передается self
параметру in .__init__()
, чтобы можно было определить новые атрибуты для объекта.
Давайте обновим Dog
класс .__init__()
методом, который создает .name
и .age
атрибуты:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
Обратите внимание, что .__init__()
подпись метода имеет отступ в четыре пробела. Текст метода разделен отступом в восемь пробелов. Этот отступ жизненно важен. Он сообщает Python, что .__init__()
метод принадлежит Dog
классу.
В теле .__init__()
есть два оператора , использующие self
переменную:
self.name = name
создает вызываемый атрибутname
и присваивает ему значениеname
параметра.self.age = age
создает вызываемый атрибутage
и присваивает ему значениеage
параметра.
Атрибуты, созданные в .__init__()
, называются атрибутами экземпляра. Значение атрибута экземпляра зависит от конкретного экземпляра класса. Все Dog
объекты имеют имя и возраст, но значения атрибутов name
и age
будут варьироваться в зависимости от Dog
экземпляра.
С другой стороны, атрибуты класса-это атрибуты, которые имеют одинаковое значение для всех экземпляров класса. Вы можете определить атрибут класса, присвоив значение имени переменной за пределами .__init__()
.
Например, следующий Dog
класс имеет атрибут класса, вызываемый species
со значением"Canis familiaris"
:
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__(self, name, age):
self.name = name
self.age = age
Атрибуты класса определяются непосредственно под первой строкой имени класса и разделяются четырьмя пробелами. Им всегда должно быть присвоено начальное значение. При создании экземпляра класса атрибуты класса автоматически создаются и присваиваются их начальным значениям.
Используйте атрибуты класса для определения свойств, которые должны иметь одинаковое значение для каждого экземпляра класса. Используйте атрибуты экземпляра для свойств, которые варьируются от одного экземпляра к другому.
Теперь, когда у нас есть Dog
класс, давайте создадим несколько собак!
Создание экземпляра объекта в Python
Откройте интерактивное окно IDLE и введите следующее:
>>> class Dog:
... pass
Это создает новый Dog
класс без атрибутов или методов.
Создание нового объекта из класса называется созданием экземпляра объекта. Вы можете создать экземпляр нового Dog
объекта, введя имя класса, за которым следуют открывающие и закрывающие скобки:
>>> Dog()
<__main__.Dog object at 0x106702d30>
Теперь у вас есть новый Dog
объект 0x106702d30
. Эта забавно выглядящая строка букв и цифр является адресом памяти, который указывает, где Dog
объект хранится в памяти вашего компьютера. Обратите внимание, что адрес, который вы видите на своем экране, будет другим.
Теперь создайте экземпляр второго Dog
объекта:
>>> Dog()
<__main__.Dog object at 0x0004ccc90>
Новый Dog
экземпляр находится по другому адресу памяти. Это потому, что это совершенно новый экземпляр и совершенно уникален по сравнению с первым Dog
объектом, который вы создали.
Чтобы увидеть это по-другому, введите следующее:
>>> a = Dog()
>>> b = Dog()
>>> a == b
False
В этом коде вы создаете два новых Dog
объекта и назначаете их переменным a
и b
. При сравнении a
и b
использовании ==
оператора результат таков False
. Несмотря a
на то, что и b
оба являются экземплярами Dog
класса, они представляют два различных объекта в памяти.
Атрибуты класса и экземпляра
Теперь создайте новый Dog
класс с именем атрибута .species
класса и двумя атрибутами экземпляра .name
и .age
:>>>
>>> class Dog:
... species = "Canis familiaris"
... def __init__(self, name, age):
... self.name = name
... self.age = age
Чтобы создать экземпляр объектов этого Dog
класса, необходимо указать значения для name
и age
. Если вы этого не сделаете, то Python поднимет TypeError
:>>>
>>> Dog()
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
Dog()
TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
Чтобы передать аргументы параметрам name
и age
, поместите значения в круглые скобки после имени класса:>>>
>>> buddy = Dog("Buddy", 9)
>>> miles = Dog("Miles", 4)
Это создает два новых Dog
экземпляра—один для девятилетней собаки по кличке Бадди и один для четырехлетней собаки по кличке Майлз.
Метод Dog
класса .__init__()
имеет три параметра, так почему же в примере ему передаются только два аргумента?
Когда вы создаете экземпляр Dog
объекта, Python создает новый экземпляр и передает его первому параметру .__init__()
. Это, по сути, удаляет self
параметр, поэтому вам нужно беспокоиться только о параметрах name
и .age
После создания Dog
экземпляров вы можете получить доступ к их атрибутам экземпляра, используя точечную нотацию:>>>
>>> buddy.name
'Buddy'
>>> buddy.age
9
>>> miles.name
'Miles'
>>> miles.age
4
Вы можете получить доступ к атрибутам класса таким же образом:>>>
>>> buddy.species
'Canis familiaris'
Одним из самых больших преимуществ использования классов для организации данных является то, что экземпляры гарантированно имеют ожидаемые атрибуты. Все Dog
экземпляры имеют .species.name.age
атрибуты , , и, поэтому вы можете использовать эти атрибуты с уверенностью, зная, что они всегда будут возвращать значение.
Хотя атрибуты гарантированно существуют, их значения могут динамически изменяться:>>>
>>> buddy.age = 10
>>> buddy.age
10
>>> miles.species = "Felis silvestris"
>>> miles.species
'Felis silvestris'
В этом примере вы изменяете .age
атрибут buddy
объекта на 10
. Затем вы меняете .species
атрибут miles
объекта на "Felis silvestris"
, который является видом кошки. Это делает Майлза довольно странной собакой, но это действительно Питон!
Ключевым моментом здесь является то, что пользовательские объекты по умолчанию изменяемы. Объект является изменяемым, если его можно динамически изменять. Например, списки и словари изменчивы, но строки и кортежи неизменяемы.
Методы экземпляра
Методы экземпляра-это функции, которые определены внутри класса и могут быть вызваны только из экземпляра этого класса. Точно так .__init__()
же , как первый параметр метода экземпляра всегда self
равен .
Откройте новое окно редактора в режиме ожидания и введите следующий Dog
класс:
class Dog:
species = "Canis familiaris"
def __init__(self, name, age):
self.name = name
self.age = age
# Instance method
def description(self):
return f"{self.name} is {self.age} years old"
# Another instance method
def speak(self, sound):
return f"{self.name} says {sound}"
Этот Dog
класс имеет два метода экземпляра:
.description()
возвращает строку, отображающую имя и возраст собаки..speak()
имеет один вызываемый параметрsound
и возвращает строку, содержащую имя собаки и звук, который издает собака.
Сохраните измененный Dog
класс в файл с именем dog.py
и нажмите F5, чтобы запустить программу. Затем откройте интерактивное окно и введите следующее, чтобы увидеть методы вашего экземпляра в действии:>>>
>>> miles = Dog("Miles", 4)
>>> miles.description()
'Miles is 4 years old'
>>> miles.speak("Woof Woof")
'Miles says Woof Woof'
>>> miles.speak("Bow Wow")
'Miles says Bow Wow'
В приведенном выше Dog
классе .description()
возвращает строку, содержащую информацию об Dog
экземпляре miles
. При написании собственных классов рекомендуется иметь метод, который возвращает строку, содержащую полезную информацию об экземпляре класса. Однако .description()
это не самый питонический способ сделать это.
При создании list
объекта вы можете использовать print()
для отображения строку, которая выглядит как список:>>>
>>> names = ["Fletcher", "David", "Dan"]
>>> print(names)
['Fletcher', 'David', 'Dan']
Давайте посмотрим, что произойдет, когда вы print()miles
станете объектом:>>>
>>> print(miles)
<__main__.Dog object at 0x00aeff70>
Когда вы print(miles)
, вы получаете загадочное сообщение, сообщающее вам, что miles
это Dog
объект по адресу памяти 0x00aeff70
. Это сообщение не очень полезно. Вы можете изменить то, что печатается, определив специальный метод экземпляра, называемый .__str__()
.
В окне редактора измените имя метода Dog
класса .description()
на.__str__()
:
class Dog:
# Leave other parts of Dog class as-is
# Replace .description() with __str__()
def __str__(self):
return f"{self.name} is {self.age} years old"
Сохраните файл и нажмите F5. Теперь, когда вы print(miles)
, вы получаете гораздо более дружелюбный результат:>>>
>>> miles = Dog("Miles", 4)
>>> print(miles)
'Miles is 4 years old'
Методы, такие как .__init__()
и .__str__()
называются методами dunder, потому что они начинаются и заканчиваются двойным подчеркиванием. Существует множество более простых методов, которые вы можете использовать для настройки классов в Python. Хотя это слишком сложная тема для начинающей книги по Python, понимание методов dunder является важной частью овладения объектно-ориентированным программированием на Python.
В следующем разделе вы увидите, как продвинуть свои знания еще на один шаг вперед и создавать классы из других классов.
Проверьте свое понимание
Разверните блок ниже, чтобы проверить свое понимание:
Упражнение: Создайте класс автомобиля, Покажите/Спрячьте
Вы можете развернуть блок ниже, чтобы увидеть решение:
Решение: Создайте класс автомобиля, чтобы Показать/Скрыть
Когда вы будете готовы, вы можете перейти к следующему разделу.
Наследование от других классов в Python
Наследование — это процесс, посредством которого один класс принимает атрибуты и методы другого. Вновь созданные классы называются дочерними классами, а классы, из которых происходят дочерние классы, называются родительскими классами.
Примечание: Этот учебник адаптирован из главы “Объектно-ориентированное программирование (ООП)” в разделе Основы Python: Практическое введение в Python 3. Если вам нравится то, что вы читаете, обязательно ознакомьтесь с остальной частью книги.
Дочерние классы могут переопределять или расширять атрибуты и методы родительских классов. Другими словами, дочерние классы наследуют все атрибуты и методы родителя, но также могут указывать атрибуты и методы, уникальные для них самих.
Хотя аналогия не идеальна, вы можете думать о наследовании объектов как о генетическом наследовании.
Возможно, вы унаследовали свой цвет волос от своей матери. Это свойство, с которым ты родился. Допустим, вы решили покрасить волосы в фиолетовый цвет. Предполагая, что у вашей матери нет фиолетовых волос, вы просто переопределили атрибут цвета волос, который вы унаследовали от своей мамы.
Вы также в некотором смысле наследуете свой язык от своих родителей. Если ваши родители говорят по-английски, то и вы будете говорить по-английски. Теперь представьте, что вы решили выучить второй язык, например немецкий. В этом случае вы расширили свои атрибуты, потому что добавили атрибут, которого нет у ваших родителей.
Пример парка для собак
Представь на мгновение, что ты в собачьем парке. В парке много собак разных пород, и все они ведут себя по-разному.
Предположим теперь, что вы хотите смоделировать собачий парк с помощью классов Python. Dog
Класс, о котором вы писали в предыдущем разделе, может различать собак по имени и возрасту, но не по породе.
Вы можете изменить Dog
класс в окне редактора, добавив .breed
атрибут:
class Dog:
species = "Canis familiaris"
def __init__(self, name, age, breed):
self.name = name
self.age = age
self.breed = breed
Методы экземпляра, определенные ранее, здесь опущены, поскольку они не важны для данного обсуждения.
Нажмите F5, чтобы сохранить файл. Теперь вы можете смоделировать собачий парк, создав несколько экземпляров разных собак в интерактивном окне:>>>
>>> miles = Dog("Miles", 4, "Jack Russell Terrier")
>>> buddy = Dog("Buddy", 9, "Dachshund")
>>> jack = Dog("Jack", 3, "Bulldog")
>>> jim = Dog("Jim", 5, "Bulldog")
У каждой породы собак немного разное поведение. Например, у бульдогов низкий лай, который звучит как гав, но у такс более высокий лай, который больше похож на тявканье.
Используя только Dog
класс, вы должны указывать строку для sound
аргумента .speak()
каждого вызова его в Dog
экземпляре:>>>
>>> buddy.speak("Yap")
'Buddy says Yap'
>>> jim.speak("Woof")
'Jim says Woof'
>>> jack.speak("Woof")
'Jack says Woof'
Передача строки для каждого вызова .speak()
является повторяющейся и неудобной. Более того, строка, представляющая звук, который издает каждый Dog
экземпляр, должна определяться его .breed
атрибутом, но здесь вам нужно вручную передавать правильную строку при .speak()
каждом ее вызове.
Вы можете упростить работу с Dog
классом, создав дочерний класс для каждой породы собак. Это позволяет расширить функциональные возможности, которые наследует каждый дочерний класс, включая указание аргумента по умолчанию .speak()
.
Родительские классы против Дочерних классов
Давайте создадим класс детей для каждой из трех пород, упомянутых выше: Джек-рассел-терьер, Такса и бульдог.
Для справки, вот полное определение Dog
класса:
class Dog:
species = "Canis familiaris"
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
def speak(self, sound):
return f"{self.name} says {sound}"
Помните, что для создания дочернего класса вы создаете новый класс с его собственным именем, а затем помещаете имя родительского класса в круглые скобки. Добавьте в dog.py
файл следующее, чтобы создать три новых дочерних класса Dog
класса:
class JackRussellTerrier(Dog):
pass
class Dachshund(Dog):
pass
class Bulldog(Dog):
pass
НажмитеF5, чтобы сохранить и запустить файл. Теперь, когда определены дочерние классы, вы можете создавать экземпляры некоторых собак определенных пород в интерактивном окне:>>>
>>> miles = JackRussellTerrier("Miles", 4)
>>> buddy = Dachshund("Buddy", 9)
>>> jack = Bulldog("Jack", 3)
>>> jim = Bulldog("Jim", 5)
Экземпляры дочерних классов наследуют все атрибуты и методы родительского класса:>>>
>>> miles.species
'Canis familiaris'
>>> buddy.name
'Buddy'
>>> print(jack)
Jack is 3 years old
>>> jim.speak("Woof")
'Jim says Woof'
Чтобы определить, к какому классу относится данный объект, вы можете использовать встроенный type()
:>>>
>>> type(miles)
<class '__main__.JackRussellTerrier'>
Что делать, если вы хотите определить, является ли miles
он также экземпляром Dog
класса? Вы можете сделать это с помощью встроенного isinstance()
:>>>
>>> isinstance(miles, Dog)
True
Обратите внимание, что для этого isinstance()
требуется два аргумента: объект и класс. В приведенном выше примере isinstance()
проверяет, является ли miles
экземпляр Dog
класса, и возвращает True
.
miles
, buddy
, jack
, и jim
объекты являются Dog
экземплярами, но miles
не являются Bulldog
экземпляром и jack
не являются Dachshund
экземпляром:>>>
>>> isinstance(miles, Bulldog)
False
>>> isinstance(jack, Dachshund)
False
В более общем плане все объекты, созданные из дочернего класса, являются экземплярами родительского класса, хотя они могут и не быть экземплярами других дочерних классов.
Теперь, когда вы создали классы для детей для некоторых разных пород собак, давайте дадим каждой породе свой собственный звук.
Расширьте функциональность родительского класса
Поскольку у разных пород собак лай немного отличается, вы хотите указать значение по умолчанию для sound
аргумента их соответствующих .speak()
методов. Для этого вам нужно переопределить .speak()
определение класса для каждой породы.
Чтобы переопределить метод, определенный в родительском классе, вы определяете метод с тем же именем в дочернем классе. Вот как это выглядит для JackRussellTerrier
класса:
class JackRussellTerrier(Dog):
def speak(self, sound="Arf"):
return f"{self.name} says {sound}"
Теперь .speak()
определяется в JackRussellTerrier
классе с аргументом по умолчанию для sound
set to "Arf"
.
Обновите dog.py
с помощью нового JackRussellTerrier
класса и нажмите F5, чтобы сохранить и запустить файл. Теперь вы можете вызывать .speak()JackRussellTerrier
экземпляр без передачи аргумента sound
:>>>
>>> miles = JackRussellTerrier("Miles", 4)
>>> miles.speak()
'Miles says Arf'
Иногда собаки лают по-другому, поэтому, если Майлз разозлится и зарычит, вы все равно можете позвонить другим .speak()
звуком:>>>
>>> miles.speak("Grrr")
'Miles says Grrr'
Одна вещь, которую следует иметь в виду при наследовании классов, заключается в том, что изменения в родительском классе автоматически распространяются на дочерние классы. Это происходит до тех пор, пока изменяемый атрибут или метод не переопределяется в дочернем классе.
Например, в окне редактора измените строку, возвращаемую .speak()
в Dog
классе:
class Dog:
# Leave other attributes and methods as they are
# Change the string returned by .speak()
def speak(self, sound):
return f"{self.name} barks: {sound}"
Сохраните файл и нажмите F5. Теперь, когда вы создаете новый Bulldog
экземпляр с именем jim
, jim.speak()
возвращает новую строку:>>>
>>> jim = Bulldog("Jim", 5)
>>> jim.speak("Woof")
'Jim barks: Woof'
Однако вызов .speak()JackRussellTerrier
экземпляра не покажет новый стиль вывода:>>>
>>> miles = JackRussellTerrier("Miles", 4)
>>> miles.speak()
'Miles says Arf'
Иногда имеет смысл полностью переопределить метод из родительского класса. Но в данном случае мы не хотим JackRussellTerrier
, чтобы класс потерял какие-либо изменения, которые могут быть внесены в форматирование выходной строки Dog.speak()
.
Для этого вам все равно нужно определить .speak()
метод в дочернем JackRussellTerrier
классе. Но вместо явного определения выходной строки вам нужно вызвать Dog
класс .speak()
внутри дочернего класса .speak()
, используя те же аргументы, которые вы передали JackRussellTerrier.speak()
.
Вы можете получить доступ к родительскому классу изнутри метода дочернего класса с помощью super()
:
class JackRussellTerrier(Dog):
def speak(self, sound="Arf"):
return super().speak(sound)
При вызове super().speak(sound)
внутри JackRussellTerrier
Python выполняет поиск метода в родительском классе, Dog
, .speak()
и вызывает его с переменной sound
.
Обновите dog.py
с помощью нового JackRussellTerrier
класса. Сохраните файл и нажмите F5, чтобы вы могли протестировать его в интерактивном окне:>>>
>>> miles = JackRussellTerrier("Miles", 4)
>>> miles.speak()
'Miles barks: Arf'
Теперь , когда вы звоните miles.speak()
, вы увидите вывод, отражающий новое форматирование в Dog
классе.
Примечание: В приведенных выше примерах иерархия классов очень проста. JackRussellTerrier
Класс имеет один родительский класс, Dog
. В реальных примерах иерархия классов может быть довольно сложной.
super()
делает гораздо больше, чем просто поиск метода или атрибута в родительском классе. Он пересекает всю иерархию классов в поисках соответствующего метода или атрибута. Если вы не будете осторожны, super()
это может привести к удивительным результатам.
Проверьте Свое Понимание
Разверните блок ниже, чтобы проверить свое понимание:
Упражнение: Показать/Скрыть Наследование классов
Вы можете развернуть блок ниже, чтобы увидеть решение:
Решение: Показать/Скрыть Наследование классов
Вывод
В этом уроке вы узнали об объектно-ориентированном программировании (ООП) на Python. Большинство современных языков программирования, таких как Java, C# и C++, следуют принципам ООП, поэтому знания, полученные здесь, будут применимы независимо от того, куда приведет вас ваша карьера программиста.
В этом уроке вы узнали, как:
- Определите класс, который является своего рода чертежом объекта
- Создание экземпляра объекта из класса
- Используйте атрибуты и методы для определения свойств и поведения объекта
- Используйте наследование для создания дочерних классов из родительского класса
- Ссылка на метод родительского класса с использованием
super()
- Проверьте, наследуется ли объект от другого класса с помощью
isinstance()