Как передать список в класс питон
Перейти к содержимому

Как передать список в класс питон

Объектно-ориентированное программирование Python (ООП в Python)

В этой статье мы расскажем об объектно-ориентированном программировании (ООП) в Python и его фундаментальных концепциях.

Введение в ООП в Python

Python — это мультипарадигмальный язык. Это означает, что он поддерживает различные подходы к программированию.

Одной из наиболее популярных парадигм является создание объектов. Она известна как объектно-ориентированное программирование (ООП).

Объект имеет две характеристики:

  • атрибуты;
  • поведение;

Рассмотрим на примере:

Объект – это попугай:

  • имя, возраст, цвет являются атрибутами;
  • пение, танцы — это поведение;

Концепция ООП в Python направлена ​​на создание кода для многократного использования. Эта концепция также известна как DRY (Don’t Repeat Yourself).

В Python концепция ООП реализует несколько принципов:

Наследование Использование элементов из нового класса без изменения существующего класса.
Инкапсуляция Скрытие приватных элементов класса от других объектов.
Полиморфизм Концепция использования объекта с одинаковым интерфейсом без получения информации о его типе и внутренней структуре.

Класс

Мы можем представить класс как эскиз попугая с метками. Он содержит все данные об имени, цвете, размере и т. д. На основе этого описания можно изучить попугая. В данном случае попугай является объектом.

Примером для класса попугая может быть:

Мы используем ключевое слово class для определения пустого класса Parrot . Из класса мы создаем экземпляр – объект определенного класса.

Объект

Объект — это экземпляр класса. В определении класса задается только описание объекта. Пример создания объекта класса Parrot:

В данном случае obj является объектом класса Parrot.

Предположим, что у нас есть информация о попугае. Теперь нужно показать, как построить класс и объекты Parrot.

Пример 1. Создание класса и объекта в Python

Результат работы программы:

Сначала мы создаем класс с именем Parrot. Затем мы определяем атрибуты. Они являются характеристикой объекта.

Затем мы создаем экземпляры класса Parrot. В данном случае blu и woo являются ссылками на новые объекты.

После этого мы получаем доступ к атрибуту класса с помощью __class __.species. Атрибуты класса одинаковы для всех его экземпляров. Точно так же мы получаем доступ к атрибутам экземпляра, используя blu.name и blu.age. Но атрибуты экземпляра уникальны для каждого экземпляра класса.

Методы

Методы — это функции, определенные внутри класса. Они используются для определения поведения объекта.

Пример 2: Создание методов в Python

Результат работы программы:

В приведенном выше примере мы определяем два метода sing() и dance(). Их называют методами экземпляра, так как они вызываются для экземпляра объекта, то есть для blu.

Наследование

Наследование — это способ создания нового класса на основе старого. Новый класс является производным классом (дочерним). Существующий класс является базовым классом (родительским).

Пример 3: Использование наследования в Python

Результат работы программы:

Сначала мы создали два класса: Bird (родительский класс) и Penguin (дочерний класс). Он наследует функции родительского класса. Это прослеживается в методе swim().

Дочерний класс изменил поведение родительского класса – метод whoisThis(). Также мы расширяем родительский класс, создав новый метод run().

Мы используем функцию super() перед методом __init__(), чтобы извлечь содержимое метода __init__() из родительского класса в дочерний.

Инкапсуляция

Используя ООП в Python, мы можем ограничить доступ к методам и переменным. Это предотвращает изменение данных вне класса. Такой подход называется инкапсуляцией. В Python мы устанавливаем приватный модификатор доступа, используя в качестве префикса подчеркивание одинарное «_» или двойное «_ _» подчеркивание.

Пример 4: Инкапсуляция данных в Python

Когда мы запустим эту программу, результат будет следующим:

Сначала мы определили класс Computer . Затем использовали метод __init__() для хранения значения максимальной стоимости продажи компьютера.

Мы попытались изменить цену, но не смогли, потому что Python рассматривает __maxprice, как приватные атрибуты. Чтобы изменить значение, мы использовали функцию сеттера. То есть, setMaxPrice(), которая принимает цену в качестве параметра.

Полиморфизм

Полиморфизм — это способность использовать в ООП общий интерфейс для нескольких форм (типов данных).

Предположим, что нужно раскрасить фигуру. Есть несколько вариантов фигуры (прямоугольник, квадрат, круг). Мы могли бы использовать тот же метод, чтобы закрасить любую форму. Эта концепция называется полиморфизмом.

Пример 5: Использование полиморфизма в Python

Мы определили два класса: Parrot и Penguin . У каждого из них есть общий метод fly(), но они разные.

Чтобы реализовать полиморфизм, мы создали общий интерфейс. То есть, функцию flying_test(), которая может принимать любой объект. Затем мы передали объекты blu и peggy в функцию flying_test().

Преимущества использования ООП

  • Программирование становится простым и эффективным.
  • Класс общий, поэтому код можно использовать повторно.
  • Производительность программистов увеличивается.
  • Благодаря абстракции данные становятся безопасными и надежными.

Пожалуйста, оставляйте ваши отзывы по текущей теме статьи. За комментарии, отклики, подписки, дизлайки, лайки низкий вам поклон!

Дайте знать, что вы думаете по данной теме статьи в комментариях. За комментарии, отклики, дизлайки, лайки, подписки огромное вам спасибо!

Вадим Дворников автор-переводчик статьи « Python Object Oriented Programming »

Как создавать классы в Python со знанием дела: разбираем на примерах

Чтобы создавать классы в Python, нужно использовать ключевое слово class . Ну и еще пара-тройка деталей: прописать инициализацию, создать свойства и методы. Python же простой язык. И, может быть, разглагольствовать на эту тему ни к чему? Для тех, кого не устраивает короткое и «простое» объяснение, мы написали эту статью.

Да, синтаксис изучить достаточно просто. Но сложность кроется в том мире, откуда пришло слово class . Это мир объектно-ориентированного программирования (ООП). Он не является очередной фантазией теоретиков, а наоборот, пытается отобразить реальный мир в виде объектов и связей между ними.

Так что Python — это (n+1)-й язык, в котором была реализована концепция ООП.

Что же такое ООП?

Мы уже упомянули слово class . Это формальная модель или шаблон, задающий структуру объекта. А что такое объект? Между классом и объектом такие же отношения, как между чертежом и изделием. Например, есть чертеж табуретки, по которому ее изготавливают. Но табуретки не существуют в живой природе. Приведем пример оттуда: допустим, мы решили смоделировать утку в компьютерной игре. Тогда получается, что объект уже есть, а класса нет. В этом случае нужно понаблюдать за уткой и создать модель, включив в нее нужные нам характеристики и ее поведение.

В какой-то момент мы поймем, что утка чем-то похожа на других птиц: значит, ее можно отнести к категории (обобщенному, родительскому классу, шаблону) «птицы». С другой стороны, для нашей игры не важно, как устроен организм утки: главное, что она как-то выглядит и как-то крякает. То есть мы абстрагируемся от ненужных для нашей модели нюансов. А кто-то другой добавит эти нюансы в свою модель и реализует, например, утиный анатомический атлас. Но некто третий использует обе модели и на их базе создаст свою. Это в двух словах о том, каким образом формируются модели и каким образом объекты подразделяются на классы.

Утка и Птица — это классы, а утка1, утка2 и птица1, птица2 — объекты (экземпляры классов).

Концепция объектно-ориентированного программирования опирается на три известных утки кита. Давайте познакомимся с ними поближе.

Инкапсуляция

Этим словом обозначают сокрытие нюансов поведения объекта или его характеристик от «посторонних» программистов. Например, над компьютерной игрой работают два программиста. Один из них реализовал класс Утка, а другой просто хочет его использовать и у них случается такой диалог:

— Какой код написать, чтобы твоя утка полетела?

— Ты просто создай объект класса Утка: например, утка1 . А потом вызови у этого объекта функцию утка1.летать() (функции, созданные внутри класса, правильнее называть «методами» — о них поговорим в соответствующем разделе — прим.) .

И второму программисту, который использует этот класс Утка не нужно думать, как реализована функция летать() . Работает, и хорошо!

Наследование

В ООП принято «экономить» код, время и силы, не делая лишних движений. Например, у нас уже реализован класс Птица . Если нам нужно реализовать класс Утка, мы можем максимально использовать код класса Птица и добавить еще (желательно не сильно много) нового кода. Этот процесс и называется наследованием.

В примере выше Утка — наследник класса Птица. В то же время Птица — родительский класс по отношению к Утке. Вот так принято выражаться.

Полиморфизм

Сколько способов есть у утки, чтобы поздороваться с вами голосом? Наверное, она просто скажет что-то вроде «кря». Допустим, у нее есть один способ. Хорошо, сколько способов есть у лебедя? Они вроде как просто шипят. Допустим, тоже один. А если у птиц в целом? Ну не знаю… много. Однако все в целом по-прежнему будет называться словом «поздороваться»:

Действие называется одинаково, но выполнено оно будет по-разному — в зависимости от объекта, который это действие будет выполнять. У объекта утка1 класса Утка и у объекта лебедь1 класса Лебедь это произойдет по-разному. В буквальном переводе греческое слово polýmorphos означает «многообразный». Поняли, да?

Далее перейдем к практике и разберемся, как создавать классы и делать с ними вот это все на Python. Остальную терминологию ООП и специальные термины из Python изучим по ходу дела.

Первый класс

Ключевое слово class мы уже обсудили. Оно ставится перед названием класса, которое пишется с большой буквы. Внутри класса для начала просто выведем сообщение.

Создаем объект (он же экземпляр класса) вот так — в одну строку:

Имя объекта (здесь создан объект по имени b ) пишем с маленькой буквы. В этом случае внутри скобок нет параметров, но позже мы посмотрим, как и зачем их туда вписывать. Для второго объекта — аналогично. И вот такой результат работы этой программы мы получим:

Птица, ты кто?

Пока мы толком ничего не можем сказать о созданном объекте b. Все потому, что мы создали для него пустой класс, который просто занимается самолюбованием. Давайте это исправим. Добавим один атрибут name классу Bird.

Атрибуты — это набор данных, характеризующих объект или его состояние.

Изменим структуру класса, добавив специальную инициализирующую функцию. В ней обычно атрибуты заполняются конкретными значениями, переданными в качестве параметров. В этом случае — параметр name . Тут, правда, есть еще один странный параметр — self . Это специальная переменная, содержащая ссылку на текущий экземпляр класса. Она помогает реализовать механизм ООП в Python. Поговорим о ней в следующем разделе.

Теперь можно дать каждой птице (объекту класса Bird) имя:

Запустив программу, получим:

Чтобы получить значение атрибута, мы обращаемся к нему через имя объекта с точкой (b.name).

Ключевое слово self

Ранее мы уже пытались говорить про ключевое слово self . Давайте разберемся с ним чуть лучше. Это специальная зарезервированная переменная, содержащая ссылку на текущий объект (экземпляр класса). Когда мы пишем код внутри класса, возникает естественное желание использовать его атрибуты и методы. За пределами класса мы делали это так:

По аналогии внутри него мы будем делать это вот как:

Получается, что self заменяет имя любого объекта, когда мы пишем код внутри его класса.

В этом случае self заменяет имя объекта b или b2 внутри класса Bird .

Если внутри Bird использовать объект другого класса, слово self для него не применяется. Например, создадим класс Cird :

Создадим и используем объект класса Cird внутри класса Bird:

Получая значение атрибута ( c.message ) , мы используем имя конкретного объекта (то есть с ) , а не слово self .

Результат выполнения кода:

Конструктор и инициализатор

Теперь стало немного понятнее, зачем нужен self в этом странном методе класса:

Это один из его параметров. Он записывает значение второго параметра ( name ) в соответствующий атрибут текущего объекта. Там может быть и больше параметров. А может быть один только — self . Без него нельзя.

Хорошо… но почему это так? И зачем вообще нужен этот метод?

Это инициализатор. Обычно именно здесь в атрибуты объекта записываются значения. Это могут быть значения по умолчанию (как в классе Cird: self.message = «Я объект c, класса Cird» ) или значения, полученные с использованием параметров функции.

А как же создается сам объект?

В других языках программирования, например, существуют так называемые конструкторы. В Python тоже есть нечто похожее. Это специальный метод, который называется __new__ . Только в Python его код мы обычно не видим и не пишем сами. Такой конструктор существует и работает «за кулисами». В качестве единственного параметра он принимает класс, анализирует его структуру (код) и на базе этой структуры создает пустой объект. Инициализировать его — не царское дело. Пусть этим занимается инициализатор, а не конструктор. Просьба не путать их друг с другом.

Важно, что оба эти метода вызываются автоматически, когда мы создаем объект — сначала __new__ , потом __init__ . Например для b = Bird(“Сережа”) последовательность вызовов будет выглядеть так:

Статические и динамические атрибуты

Вот вы говорите конструктор, инициализатор… А что, если я объявлю и инициализирую атрибут вне метода __init__ ?

И такое тоже практикуют. И такие атрибуты даже имеют свое название и применение:

Атрибут ruClassName называется статическим. А атрибут name — динамическим. Заметьте, что внутри класса к статическим атрибутам мы не обращаемся через self . Вне класса мы обращаемся к статическим атрибутам не через <имя объекта> с точкой , а через <Имя класса> с точкой. То же самое, кстати, требуется делать со статическим атрибутом и внутри методов класса! Иначе работать не будет.

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

Дело в том, что при создании новых объектов создаются копии всех динамических атрибутов со сброшенными к «заводским настройкам» значениями. Статические атрибуты относятся не к объекту, а к классу и имеют только одну копию.

В примере выше статический атрибут ruClassName просто хранит название класса. В примере поинтереснее статический атрибут может служить для подсчета количества созданных объектов класса:

Методы класса

Что, если нам дали задачу расширить пример из предыдущего раздела?

1. Нужно добавить Птице больше атрибутов:

  • идентификационный номер ( id );
  • возраст ( age ).

2. Реализовать возможность выводить атрибут имя ( name ), а также эти два атрибута для каждого объекта класса Птица.

С первым пунктом мы справимся легко, как говорится, по образу и подобию:

Вроде бы и вывод тоже можно сделать аналогично:

Результат работы кода:

Но наш тимлид считает, что такой код некрасивый и не очень читабельный. Да и ООП рекомендует помещать код обработки данных объекта внутрь его класса. Попробуем:

Функция info() внутри класса Bird называется методом. Теперь у каждого созданного объекта этого класса можно вызвать метод:

Код действительно выглядит более лаконично. Получается, что теперь каждый объект сам может сообщить информацию о себе. И теперь, используя объект, сторонний программист может не задумываться о том, как реализован вывод информации о нем. Он работает, и хорошо!

Результат работы такой же, как в предыдущем примере:

Уровни доступа атрибута и метода

Реализация концепции ООП должна предусмотреть возможность запретить прямой доступ к атрибуту (или к методу) со стороны внешнего кода. То есть сделать его скрытым, приватным (термин из англоязычного ООП — private). Прямая модификация некоторых особо важных атрибутов может привести к дефектам в программе. Часто это нужно для того, чтобы оставлять доступ открытым («публичным», public) только к тем атрибутам и методам, которые будут взаимодействовать с внешним кодом. Остальные атрибуты и функции, которые, например, просто (или сложно) обслуживают свой класс, не должны быть доступны извне.

В Python это реализовано с помощью добавления к имени атрибута или метода одинарного или двойного подчеркивания. Первое используется в расчете на более сознательных и внимательных граждан. Второе — более жесткий вариант для всех остальных. Что это означает? Перейдем к конкретике и возьмем из нашего примера атрибут name:

  1. Если мы заменим name на _name, он станет скрытым атрибутом. Но к такому атрибуту еще можно получить доступ как обычно, через <имя объекта>._name. Это делать не рекомендуется, но в исключительных случаях те самые сознательные и внимательные граждане умеют без печальных последствий обращаться к скрытым атрибутам таким образом. Ну а исключения подтверждают правила.
  2. Если мы заменим name на __name, он станет по-настоящему закрытым атрибутом. И к нему уже нельзя будет получить доступ обычным способом. Интерпретатор языка Python выдаст ошибку AttributeError и не выполнит этот код.

По заветам ООП, и в первом, и во втором случае нужно узнать, написаны ли специальные методы для получения значения ( getter ) и/или модификации ( setter ) интересующего вас скрытого атрибута. Если да, то используйте их.

Эти методы обычно выглядят примерно так:

Перепишем весь класс:

Создадим объект и покажем правильный доступ к атрибуту _name (для __name все будет аналогично), который теперь обозначен как скрытый:

Результат работы программы:

Оказывается, мы можем переименовать созданный объект. Здорово. Но что, если нам запрещено называть птиц Иванами?

Тогда мы можем сделать соответствующую проверку прямо в коде метода set_name . Она будет выполняться при каждом вызове метода set_name для любого объекта. Поэтому логично поместить ее именно внутрь класса. Иначе пришлось бы многократно добавлять ее во внешний код при каждой подобной манипуляции с атрибутом. Это нерационально, да и ООП советует делать подобную валидацию данных объекта внутри самого объекта. Так что, вот:

Тогда программа будет работать по-другому:

Свойства

Есть способ упростить внешний код, который обращается вместо атрибута к его методам getter и setter . Начнем опять обращаться к атрибуту по его имени, только без подчеркивания. И пусть методы getter и setter вызываются автоматически, когда это необходимо. Правда, ради такого комфорта в код класса придется внести изменения. Для этого в Python существует специальная конструкция — декоратор @property :

В остальном это обычные методы.

Код вызова извне тоже изменится:

Результат работы программы останется прежним:

Начать и закончить: наследование и полиморфизм

Про наследование и полиморфизм уже шла речь в начале статьи. Но тогда нельзя было приводить полноценные примеры на Python. Теперь, когда мы подтянули матчасть, написали и много раз переписали свой первый класс… как говорится, примеры в студию! Поэтому, если вам требуется время, чтобы вернуться в начало статьи и повторить эту тему — не волнуйтесь, я подожду.

Повторили? Тогда полетели дальше.

Наследование

Оттолкнемся от нашего класса Bird. Вспомним, как он выглядит:

Создадим новый класс Duck (утка), который максимально использует код класса Bird и допишем в него немного своего кода. То есть Duck будет наследником Bird, который является родителем, базовым классом. Это в принципе ожидаемо: чтобы некая сферическая птица в вакууме стала уткой, достаточно добавить пару опознавательных знаков (потому что для примера мы придумали простую модель). Итак, пусть у класса Duck будут такие динамические атрибуты:

  • скорость полета (fly_speed);
  • высота полета (fly_height).

А также статический атрибут «вид» (species). Он всегда имеет значение, равное « Утка» .

Атрибуты «скорость полета» и «высота полета» бессмысленно помещать в базовый класс, потому что не все птицы умеют летать:

В строке class Duck (Bird) мы в скобках указываем имя класса, от которого хотим делать наследование.

В методе def __init__ (self, name, id, age, fly_speed, fly_height) мы, помимо заполнения значений атрибутов текущего объекта класса Duck, вызываем инициализатор объекта базового класса (Bird):

super().__init__(name, id, age)

Только заметьте, что слово Bird мы заменяем на специальное слово super() . Оно обозначает базовый класс. Если не углубляться в дебри, то просто примите, что super() используется для вызова инициализатора и методов родительского класса внутри класса-наследника.

Теперь проверим, как работает это ваше наследование. Как обычно, создаем объект, заполняем его данными и просим рассказать о себе:

Отметим, что внутри метода info() у утки (см. класс Duck) мы, по аналогии с инициализатором и чисто для полноты информации — вызываем свой метод info() у базового класса (то есть у Bird):

Ну вот, у нас получилась утка, которая может рассказать о себе и при этом помнит, что она Птица — не забывает свои корни. Жирным выделены атрибуты базового класса:

Идентификационный номер: 22

Скорость полета: 110

Отлично, с уткой все получилось удачно. Но означает ли это, что можно создавать еще много аналогичных классов-наследников, используя один и тот же код базового класса? А еще интереснее узнать вот что:

  • можно ли в других наследниках создавать свой публичный метод с тем же названием info() , как у базового класса (Bird)?
  • если для метода info() уже написан код внутри базового класса, будет ли этот код замещен собственным новым кодом при вызове метода info() у каждого из наследников?

Возьмем, например, галапагосского баклана, который не умеет летать . Этим он кардинально отличается от утки. Однако из-за этого он не перестает быть птицей. Галапагосский баклан — редкий вид, за ним ведется пристальное наблюдение. Поэтому в качестве его единственного динамического атрибута выберем количество особей (population). А также статический атрибут «вид» (species):

Заметьте, что в строке def __init__ (self, name, id, age, population) присутствуют те же параметры id и age , которые были в инициализаторе внутри класса Duck. И затем также следует вызов:

super().__init__(name, id, age)

Теперь проверим, как это сработает на этот раз. Жирным выделены атрибуты, относящиеся к базовому классу:

Идентификационный номер: 22

Вид: Галапагосский баклан

Теперь сведем воедино работу объектов всех трех классов — родителя и наследников :

Создавать такие объекты можно в любом порядке. Как видите, вообще не обязательно, чтобы объект базового класса создавался первым.

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

Жирным выделены атрибуты, относящиеся к базовому классу:

Идентификационный номер: 22

Вид: Галапагосский баклан

Количество особей: 60

Идентификационный номер: 9

Идентификационный номер: 77

Скорость полета: 110

Мы показали, что метод info() действительно работает по-разному — в зависимости от класса того объекта, который обращается к этому методу.

Мы применили все знания, полученные в статье, и только в конце смогли написать код в соответствии с парадигмой полиморфизма.

Классы в Python

Объектно-ориентированное программирование считается одним из самых эффективных методов создания программ. В объектно-ориентированном программирование создаются классы, описывающие реальные предметы и ситуации, а затем создаете объекты на основе этих описаний. Созданием объекта на основе класса называется созданием экземпляра.

Содержание страницы:
1. Создание класса
1.1. Метод __init__()
1.2. Создание экземпляра класса
1.3. Обращение к атрибутам класса
1.4. Вызов методов класса
2. Работа с классами
2.1. Прямое изменение значения атрибута
2.2. Изменение значения атрибута с использованием метода
2.3. Изменение значения атрибута с приращением
3. Наследование класса
3.1. Переопределение методов класса-родителя

1. Создание класса в Python

Классы в Python могут моделировать практически все что угодно. Создадим простой класс, который будет описывать конкретный автомобиль:

class Car ():
"""Описание автомобиля"""
def __init__ ( self , brand, model):
"""Инициализирует атрибуты brand и model"""
self .brand = brand
self .model = model

Разберем код по порядку. В начале определяется класс с именем Car ( class Car ). По общепринятым соглашение название класса начинается с символа верхнего регистра. Круглые скобки в определение класса пусты, так как класс создается с нуля. Далее идет строка документации с кратким описанием. ( """Описание автомобиля""" ).

1.1. Метод __init__()

Функция, являющаяся частью класса, называется методом. Все свойства функций так же относятся и к методам, единственное отличие это способ вызова метода. Метод __init__() — специальный метод, который автоматически выполняется при создание нового экземпляра. Имя метода начинается и заканчивается двумя символами подчеркивания. Метод __init__() определяется с тремя параметрами: self, brand, model. Параметр self обязателен в определение метода и должен стоять перед всеми остальными параметрами. При создании экземпляра на основе класса Car, необходимо передать только два последних аргумента brand и model.

Каждая из двух переменных self.brand = brand и self.model = model снабжена префиксом self и к ним можно обращаться вызовом self.brand и self.model. Значения берутся из параметров brand и model. Переменные, к которым вы обращаетесь через экземпляры, также называются атрибутами.

В классе Car также есть два метода: sold() и discount() . Этим методам не нужна дополнительная информация и они определяются с единственным параметром self. Экземпляры, которые будут созданы на базе этого класса смогут вызывать данные методы, которые просто выводят информацию.

1.2. Создание экземпляра класса

С помощью класса Car мы можем создавать экземпляры для конкретного автомобиля. Каждый экземпляр описывает конкретный автомобиль и его параметры.

Создадим переменную car_1 и присвоим ей класс с параметрами автомобиля которые нужно обязательно передать (brand, model). При выполнение данного кода Python вызывает метод __init__ , создавая экземпляр, описывающий конкретный автомобиль и присваивает атрибутам brand и model переданные значения. Этот экземпляр сохраняется в переменной car_1.

1.3. Обращение к атрибутам класса

К атрибутам экземпляра класса мы можем обращаться через запись:

В записи используется имя экземпляра класса и после точки имя атрибута (car_1.brand) или (car_1.model). В итоге на экран выведется следующая информация:

Bmw
X5

1.4. Вызов методов класса

После создания экземпляра на основе класса Car можете вызывать любые методы, написанные в классе. Чтобы вызвать метод, укажите экземпляр (car_1) и вызываемый метод после точки:

car_1. sold ()
car_1. discount ()

При вызове данных методов, Python выполнит код, написанный в этом методе.

Автомобиль Bmw X5 продан
На автомобиль Bmw X5 скидка 5%

2. Работа с классами на Python

Большая часть времени работы программиста — это работа с классами и их экземплярами. Изменим наш предыдущий класс Car и добавим дополнительные атрибуты, которые сможем в последующем менять при работе с экземплярами класса.

class Car ():
"""Описание автомобиля"""
def __init__ ( self , brand, model, years):
"""Инициализирует атрибуты"""
self .brand = brand
self .model = model
self .years = years
self .mileage = 0

В описание автомобиля есть три атрибута(параметра) это brand, model, years. Также мы создали новый атрибут mileage (пробег) и присвоили ему начальное значение 0. Так как пробег у всех автомобилей разный, в последующем мы сможем изменять этот атрибут. Метод get_full_name будет возвращать полное описание автомобиля. Метод read_mileage будет выводить пробег автомобиля.

Создадим экземпляр с классом Car и запустим методы:

car_2 = Car('audi', 'a4', 2019)
print(car_2. get_full_name() )
car_2. read_mileage()

В результате в начале Python вызывает метот __init__() для создания нового экземпляра. Сохраняет название, модель, год выпуска и создает новый атрибут с пробегом равным 0. В итоге мы получим такой результат:

Автомобиль Audi A4 2019
Пробег автомобиля 0 км.

2.1. Прямое изменение значения атрибута

Для изменения значения атрибута можно обратиться к нему напрямую и присвоить ему новое значение. Изменим пробег автомобиля car_2:

car_2 = Car('audi', 'a4', 2019)
print(car_2.get_full_name())
car_2.mileage = 38
car_2. read_mileage()

Мы обратились к нашему экземпляру car_2 и связанным с ним атрибутом пробега(mileage) и присвоили новое значение 38. Затем вызвали метод read_mileage() для проверки. В результате мы получим следующие данные.

Автомобиль Audi A4 2019
Пробег автомобиля 38 км.

2.2. Изменение значения атрибута с использованием метода

В Python удобнее писать методы, которые будут изменять атрибуты за вас. Для этого вы просто передаете новое значение методу, который обновит значения. Добавим в наш класс Car метод update_mileage() который будет изменять показания пробега.

class Car ():
"""Описание автомобиля"""
def __init__ ( self , brand, model, years):
"""Инициализирует атрибуты"""
self .brand = brand
self .model = model
self .years = years
self .mileage = 0

def update_mileage ( self , new_mileage):
"""Устанавливает новое значение пробега"""
self .mileage = new_mileage

car_2 = Car('audi', 'a4', 2019)
print(car_2.get_full_name())

car_2. read_mileage()
car_2. update_mileage (17100)
car_2. read_mileage()

Вначале выведем текущие показания пробега ( car_2. read_mileage() ). Затем вызовем метод update_mileage() и передадим ему новое значение пробега ( car_2. update_mileage (17100) ). Этот метод устанавливает пробег 17100. Выведем текущие показания ( car_2. read_mileage() ) и у нас получается:

Автомобиль Audi A4 2019
Пробег автомобиля 0 км.
Пробег автомобиля 17100 км.

2.3. Изменение значения атрибута с приращением

Если вместо того, чтобы присвоить новое значение, требуется изменить с значение с приращением, то в этом случаем мы можем написать еще один метод, который будет просто прибавлять пробег к уже имеющемся показаниям. Для этого добавим метод add_mileage в класс Car :

def add_mileage (self, km):
"""Добавляет пробег"""
self .mileage += km

Новый метод add_mileage() получает пробег в км и добавлет его к self.mileage.

car_2. add_mileage (14687)
car_2. read_mileage ()

Пробег автомобиля 31787 км.

В итоге после вызова метода add_mileage() пробег автомобиля в экземпляре car_2 увеличится на 14687 км и станет равным 31787 км. Данный метод мы можем вызывать каждый раз при изменении пробега и передавать новые значение, на которое будет увеличивать основной пробег.

3. Наследование класса в Python

Создавая новые классы не обязательно их создавать с нуля. Новый класс может наследовать свои атрибуты (переменные) и методы (функции принадлежащие классам) от ранее определенного исходного класса ( суперкласса ). Также исходный класс называют родителем, а новый класс — потомком или подклассом. В класс-потомок можно добавлять собственные атрибуты и методы. Напишем новый класс ElectricCar, который будет создан на базе класса Car:

class Car():
"""Описание автомобиля"""
def __init__(self, brand, model, years):
"""Инициализирует атрибуты brand и model"""
self.brand = brand
self.model = model
self.years = years
self.mileage = 0

def update_mileage(self, new_mileage):
"""Устанавливает новое значение пробега"""
self.mileage = new_mileage

def add_mileage(self, km):
"""Добавляет пробег"""
self.mileage += km

class ElectricCar ( Car ):
"""Описывает электромобиль"""
def __init__ ( self , brand, model, years):
"""Инициализирует атрибуты класса родителя"""
super().__init__ (brand, model, years)
# атрибут класса-потомка
self .battery_size = 100

def battery_power ( self ):
"""Выводит мощность аккумулятора авто"""
print(f"Мощность аккумулятора < self .battery_size>кВт⋅ч")

Мы создали класс ElectriCar на базе класса Car . Имя класса-родителя в этом случае ставится в круглые скобки( class ElectricCar ( Car ) ). Метод __init__ в классе потомка (подклассе) инициализирует атрибуты класса-родителя и создает экземпляр класса Car . Функция super() .- специальная функция, которая приказывает Python вызвать метод __init__() родительского класса Car , в результате чего экземпляр ElectricCar получает доступ ко всем атрибутам класса-родителя. Имя super как раз и происходит из-за того, что класс-родителя называют суперклассом, а класс-потомок — подклассом.

Далее мы добавили новый атрибут self .battery_size и присвоили исходное значение 100. Этот атрибут будет присутствовать во всех экземплярах класса ElectriCar . Добавим новый метод battery_power() , который будет выводить информацию о мощности аккумулятора.

Создадим экземпляр класса ElectriCar и сохраним его в переменную tesla_1

tesla_1 = ElectricCar ('tesla', 'model x', 2021)
print(tesla_1. get_full_name ())
tesla_1. battery_power ( )

При вызове двух методов мы получим:

Автомобиль Tesla Model X 2021
Мощность аккумулятора 100 кВт⋅ч

В новый класс ElectriCar мы можем добавлять любое количество атрибутов и методов связанных и не связанных с классом-родителем Car .

3.1. Переопределение методов класса-родителя

Методы, которые используются в родительском классе можно переопределить в классе-потомке (подклассе). Для этого в классе-потомке определяется метод с тем же именем, что и у класса-родителя. Python игнорирует метод родителя и переходит на метод, написанный в классе-потомке (подклассе). Переопределим метод def get_full_name() чтобы сразу выводилась мощность аккумуляторов.

class ElectricCar ( Car ):
"""Описывает электромобиль"""
def __init__ ( self , brand, model, years):
"""Инициализирует атрибуты класса родителя"""
super().__init__ (brand, model, years)
# атрибут класса-потомка
self .battery_size = 100

def battery_power ( self ):
"""Выводит мощность аккумулятора авто"""
print(f"Мощность аккумулятора < self .battery_size>кВт⋅ч")

В результате при запросе полного названия автомобиля Python проигнорирует метод def get_full_name() в классе-родителя Car и сразу перейдет к методу def get_full_name() написанный в классе ElectricCar.

tesla_1 = ElectricCar ('tesla', 'model x', 2021)
print(tesla_1. get_full_name ())

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *