Ооп в python: Объектно-ориентированное программирование. Классы и объекты

Содержание

Объектно-ориентированное программирование. Классы и объекты

Сегодня мы поговорим об объектно-ориентированном программировании и о его применении в python.

Объектно-ориентированное программирование (ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов.

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

Python соответствует принципам объектно-ориентированного программирования. В python всё является объектами — и строки, и списки, и словари, и всё остальное.

Но возможности ООП в python этим не ограничены. Программист может написать свой тип данных (класс), определить в нём свои методы.

Это не является обязательным — мы можем пользоваться только встроенными объектами. Однако ООП полезно при долгосрочной разработке программы несколькими людьми, так как упрощает понимание кода.

Приступим теперь собственно к написанию своих классов на python. Попробуем определить собственный класс:

>>> # Пример простейшего класса, который ничего не делает
... class A:
...     pass

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

>>> a = A()
>>> b = A()
>>> a.arg = 1  # у экземпляра a появился атрибут arg, равный 1
>>> b.arg = 2  # а у экземпляра b - атрибут arg, равный 2
>>> print(a.arg)
1
>>> print(b.arg)
2
>>> c = A()
>>> print(c.arg)  # а у этого экземпляра нет arg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'arg'

Классу возможно задать собственные методы:

>>> class A:
...     def g(self): # self - обязательный аргумент, содержащий в себе экземпляр
...                  # класса, передающийся при вызове метода,
...                  # поэтому этот аргумент должен присутствовать
...                  # во всех методах класса.
...         return 'hello world'
...
>>> a = A()
>>> a.g()
'hello world'

И напоследок еще один пример:

>>> class B:
...     arg = 'Python' # Все экземпляры этого класса будут иметь атрибут arg,
...                    # равный "Python"
...                    # Но впоследствии мы его можем изменить
...     def g(self):
...         return self.arg
...
>>> b = B()
>>> b.g()
'Python'
>>> B.g(b)
'Python'
>>> b.arg = 'spam'
>>> b.g()
'spam'

Объектно-ориентированное программирование на Python. Курс

Курс «Объектно-ориентированное программирование на Python» знакомит с особенностями ООП в общем и его реализацией в языке Python. Предполагается, что вы знакомы с Python на уровне структурного программирования (основные типы данных, ветвления, циклы, функции).

Ключевыми понятиями объектно-ориентированного программирования являются «класс» и «объект». Это реально существующие в программном коде единицы, а не только обобщающие понятия. Объекты порождаются от своих классов. В языке программирования Python такие объекты принято называть экземплярами.

Наследование, полиморфизм и инкапсуляция – основные принципы, столпы объектно-ориентированного программирования. Наследование предполагает возможность определения дочерних классов, полиморфизм – разный способ реализации одного и того же, инкапсуляция – сокрытие и объединение данных и методов. Композиция реализуется реже, означает возможность создания объектов, составными частями которых являются объекты других классов.

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

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

Курс включает 12 основных уроков + 3 дополнительных:

  1. Что такое объектно-ориентированное программирование

  2. Создание классов и объектов

  3. Конструктор класса – метод __init__()

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

  5. Полиморфизм

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

  7. Композиция

  8. Перегрузка операторов

  9. Модули и пакеты

  10. Документирование кода

  11. Пример объектно-ориентированной программы на Python

  12. Особенности объектно-ориентированного программирования

  13. Статические методы

  14. Итераторы

  15. Генераторы

Курс с примерами решений практических работ и всеми уроками:
android-приложение, pdf-версия

Версия курса: октябрь 2020.

ООП в Python – принципы, классы, объекты, аттрибуты

Содержание:развернуть

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

Главным понятием ООП является понятие программного объекта. Вообще говоря, большинство сущностей на планете Земля – это некие объекты. И с частью из них мы взаимодействуем при помощи программирования. Банковский счёт, персонаж компьютерной игры или анимированный виджет сайта – всё это легко представить в виде объектов. Можно сказать, что объектно-ориентированное программирование позволяет смоделировать реальный объект в виде программного.

Множество объектов со схожими свойствами формируются в классы. Идея класса также является одной из основополагающих концепций ООП. Со стороны программы, класс – это всего лишь тип данных, но для программиста это куда более глубокая абстрактная структура. Но перейдём уже к конкретике.

💁‍♂️ Итак, мы – разработчики игр. Наша студия трудится над новым автосимулятором. В игре будут представлены разные виды транспорта: легковые автомобили, гоночные, грузовые и пассажирские. Все их можно описать одним словом – автотранспорт. Сделав это, мы абстрагировались от деталей и, таким образом, определили класс. Объектом этого класса может быть, как Бьюик 1968-го года, так и грузовой Freightliner Columbia желтого цвета.

У класса есть свойства и функции (в ООП их называют методами).

  • Свойства — это характеристики, присущие данному конкретному множеству объектов.
  • Методы — те действия, которые они могут совершать.

Свойствами класса «автотранспорт» могут быть, например: год выпуска, вид и цвет. На уровне объектов это будет выглядеть так: Бьюик Электра – это объект класса «Автотранспорт» со следующими свойствами:

  • вид – легковой автомобиль;
  • цвет – чёрный;
  • год выпуска – 1968.

Можно сказать, что объект – это вполне конкретный экземпляр класса

Помимо физических атрибутов, которые описывают внешний вид и характеристики транспортного средства, автомобили обладают между собой и другими фундаментальными сходствами. Например, все они могут ехать, тормозить, переключать скорости, поворачивать и сигналить. В нашем случае, всё это — методы класса «Автотранспорт». То есть действия, которые любые объекты данного класса могут выполнять.

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

В Питоне класс «Автотранспорт» может выглядеть так:

# класс автотранспорт
class MotorTransport(object):
def __init__(self, color, year, auto_type):
self.color = color
self.year = year
self.auto_type = auto_type

# тормозить
def stop(self):
print("Pressing the brake pedal")

# ехать
def drive(self):
print('WRRRRRUM!')

Теперь никто не помешает нам получить собственную красную феррари. Пусть и в симуляторе.

# создадим объект класса Автотранспорт
ferrari_testarossa = MotorTransport('Red', 1987, 'passenger car')
# жмём на газ и вперёд!
ferrari_testarossa.drive()

> WRRRRRUM!

Принципы ООП

Абстракция

Абстракция – это выделение основных, наиболее значимых характеристик объекта и игнорирование второстепенных.

Любой составной объект реального мира – это абстракция. Говоря «ноутбук», вам не требуется дальнейших пояснений, вроде того, что это организованный набор пластика, металла, жидкокристаллического дисплея и микросхем. Абстракция позволяет игнорировать нерелевантные детали, поэтому для нашего сознания это один из главных способов справляться со сложностью реального мира. Если б, подходя к холодильнику, вы должны были иметь дело с отдельно металлом корпуса, пластиковыми фрагментами, лакокрасочным слоем и мотором, вы вряд ли смогли бы достать из морозилки замороженную клубнику.

Полиморфизм

Полиморфизм подразумевает возможность нескольких реализаций одной идеи. Простой пример: у вас есть класс «Персонаж», а у него есть метод «Атаковать». Для воина это будет означать удар мечом, для рейнджера – выстрел из лука, а для волшебника – чтение заклинания «Огненный Шар». В сущности, все эти три действия – атака, но в программном коде они будут реализованы совершенно по-разному.

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

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

Мы могли бы сделать отдельный класс «Грузовик», который является наследником «Автотранспорта». Объекты этого класса могли бы определять все прошлые атрибуты (цвет, год выпуска), но и получить новые. Для грузовиков это могли быть грузоподъёмность, снаряженная масса и наличие жилого отсека в кабине. А методом, который есть только у грузовиков, могла быть функция сцепления и отцепления прицепа.

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

Инкапсуляция – это ещё один принцип, который нужен для безопасности и управления сложностью кода. Инкапсуляция блокирует доступ к деталям сложной концепции. Абстракция подразумевает возможность рассмотреть объект с общей точки зрения, а инкапсуляция не позволяет рассматривать этот объект с какой-либо другой.

Вы разработали для муниципальных служб класс «Квартира». У неё есть свойства вроде адреса, метража и высоты потолков. И методы, такие как получение информации о каждом из этих свойств и, главное, метод, реализующий постановку на учёт в Росреестре. Это готовая концепция, и вам не нужно чтобы кто-то мог добавлять методы «открыть дверь» и «получить место хранения денег». Это А) Небезопасно и Б) Избыточно, а также, в рамках выбранной реализации, не нужно. Работникам Росреестра не требуется заходить к вам домой, чтобы узнать высоту потолков – они пользуются только теми документами, которые вы сами им предоставили.

Класс

— У тебя есть ключ?
— Лучше! У меня есть рисунок ключа!

Классы, в некотором смысле, подобны чертежам: это не объекты сами по себе, а их схемы. Класс «банковских счетов» имеет строго определенные и одинаковые для всех атрибуты, но объекты в нём – сами счета – уникальны.

Как в Python создать класс

В Python классы и объекты по смыслу не отличаются от других языков. Нюансы в реализации. Для создания класса в Питоне необходимо написать инструкцию class, а затем выбрать имя. В простейшем случае, класс выглядит так:

class SimpleClass:
pass

Для именования классов в Python обычно используют стиль «camel case», где первая буква – заглавная.

LikeThis

Конструктор

Метод, который вызывается при создании объектов, в ООП зовётся конструктором. Он нужен для объектов, которые изначально должны иметь какие-то значение. Например, пустые экземпляры класса «Студент» бессмысленны, и желательно иметь хотя бы минимальный обозначенный набор вроде имени, фамилии и группы.

В качестве Питоновского конструктора выступает метод __init__():

class Student:
def __init__(self, name, surname, group):
self.name = name
self.surname = surname
self.group = group

alex = Student("Alex", "Ivanov", "admin")

Атрибуты класса

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

Поля могут быть статическими и динамическими:

  • Статические поля (поля класса) можно использовать без создания объекта. А значит, конструктор вам не нужен.
  • Динамические поля (поля объекта) задаются с помощью конструктора, и тут уже, как вы видели, экземпляр нужно создать, а полям присвоить значения.

class MightiestWeapon:
# статический атрибут
name = "Default name"

def __init__(self, weapon_type):
# динамический атрибут
self.weapon_type = weapon_type

☝️ Обратите внимание – статический и динамический атрибут может иметь одно и то же имя:

class MightiestWeapon:
# статический атрибут
name = "Default name"

def __init__(self, name):
# динамический атрибут
self.name = name

weapon = MightiestWeapon("sword")

print(MightiestWeapon.name)
print(weapon.name)

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

Метод – это функция класса.

Например, у всех научно-фантастических космических кораблей есть бортовое оружие. И оно может стрелять.

class SpaceShip:
def atack(self):
print('Пиу!')

star_destroyer = SpaceShip()
star_destroyer.atack()

> Пиу!

Что такое self?

Аналог этого ключевого слова в других языках – слово this. self – это всего лишь ссылка на текущий экземпляр класса.

🐈 Отличный пример с котофеями:

  1. Все котики умеют мурлыкать;
  2. Эта способность реализована в классе Кот, как метод Мурчать;
  3. Вы хотите, чтобы ваш кот по имени Пушок помурчал;
  4. Если сделать так: Кот.Мурчать, то мурлыкать начнут все коты во Вселенной;
  5. Но так как вам нужен один конкретный кот, то нужно вызвать метод иначе: self.Мурчать;
  6. Сделано. Пушок мурлыкает.

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

В Питоне не существует квалификаторов доступа к полям класса. Отсутствие аналогов связки public/private/protected можно рассматривать как упущение со стороны принципа инкапсуляции.

Декораторы

Декоратор – это функция-обёртка. В неё можно завернуть другой метод, и, тем самым, изменить его функциональность, не меняя код.

Объекты или экземпляры класса

Чем объекты отличаются от классов

Как уже было сказано, объект – это конкретный экземпляр класса. Все мы относимся к классу людей, но каждый из нас – уникальный объект этого класса.

Как создать объект класса в Python

Если у нас есть реализация класса, то его экземпляр создать очень просто:

class AirConditioner:
def __init__(self, model, capacity):
self.model = model
self.capacity = capacity
def turn_on(self):
print('Now in the room will be cool')

# создадим объект класса Кондиционер
ballu = AirConditioner('BPAC-07', 785)
ballu.turn_on()

> Now in the room will be cool

Атрибуты объекта

Атрибуты класса могут быть динамическими и статическими. На уровне объекта они инициализируются так:

class MightiestWeapon:
name = "Default name"
def __init__(self, weapon_type):
self.weapon_type = weapon_type

# атрибут name можно переопределить и не создавая объекта
MightiestWeapon.name = 'Steel Sword'
print(MightiestWeapon.name)
> Steal Sword

# создаём объект и сразу же инициализируем динамический атрибут с помощью конструктора
hero_sword = MightiestWeapon('sword')
# и теперь, уже для конкретного объекта, можно задать имя
hero_sword.name = 'Excalibur'
# новое статическое имя по умолчанию для всего класса не изменится
print(MightiestWeapon.name)
> Steal Sword

print(hero_sword.name)
> Excalibur

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

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

# класс "Животное". Это достаточно абстрактный класс всего с одним методом "Издать звук".
class Animal:
def make_a_sound(self):
print("Издаёт животный звук")

Мы все прекрасно знаем, что котики, к примеру, любят всё ронять, а собакены – рыть землю. Создадим два соответствующих класса-наследника:

# факт наследования в Python указывается при объявлении класса-наследника.
# в скобках, после имени класса, указывается класс-родитель
class Cat(Animal):
def drop_everything(self):
print('Вставай скорее, я всё уронил!')

class Dog(Animal):
def dig_the_ground(self):
print('Однажды я докопаюсь до ядра планеты!')

Теперь объекты этих двух классов могут не только издавать животные звуки, но и выполнять собственные уникальные действия:

Tom = Cat()
Tom.make_a_sound()
> Издаёт животный звук

Tom.drop_everything()
> Вставай скорее, я всё уронил!

Переопределение

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

class Dog(Animal):
def dig_the_ground(self):
print('Однажды я докопаюсь до ядра планеты!')
# отныне для объектов класса "Собака" будет выполняться именно эта реализация метода
def make_a_sound(self):
print('Гав-гав!')

Balto = Dog()
Balto.make_a_sound()
> Гав-гав!

Документирование классов

Весь код нужно комментировать и документировать. Классы – не исключение. Стоит помнить, что код вы пишите не для себя, и вполне вероятно, что написанное вами придётся поддерживать другим людям. Комментарии повышают читаемость и увеличивают легкость восприятие кода в разы, тем самым экономя время и деньги.

Подробнее о Python-документации:


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

#17 — Основы ООП Python

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

На начальном этапе ООП – это тёмный лес, в котором многое непонятно и слишком усложнено. На самом деле всё вовсе не так. Предлагаем абстрагироваться от специфических (непонятных) определений и познакомиться с ООП простыми словами. 

ООП простыми словами

Поскольку на примере все усвоить гораздо проще, то давайте за пример возьмем робота, которого постараемся описать за счёт классов в ООП.

Класс в случае с роботом – это его чертёж. Экземпляром класса (объектом) называет целый робот, который создан точно по чертежу.

Наследование – это добавление полезных опций к чертежу робота. К примеру, берем стандартный чертёж робота и дорисуем к нему лазеры, крылья и броню. Все эти дорисовки мы сделаем в классе наследнике, основной функционал которого взят из родительского класса.

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

А инкапсуляция является для нас бронёй, защищающей робота. Под пластырем брони находятся уязвимые элементы, вроде проводов и микросхем. После прикрытия брешей с помощью брони (protected или private), робот полностью защищён от внешних вмешательств. По сути, мы делаем доступ ко всем полям лишь за счёт методов, тем самым прямой доступ к полю будет закрыт.

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

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

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

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

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

Пример простого класса приведен ниже:

class Book:
	pass # Класс может ничего не возвращать

На основе такого класса мы можем создать множество объектов. Каждый объект в данном случае будет представлять из себя конкретную книжку. Для каждого объекта мы можем указать уникальные данные.

Чтобы создать объект нам потребуется следующий код:

obj_new = Some() # Создание объекта
obj_second = Some() # Создание 2 объекта

Pythonicway — ООП в Python

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

Терминология объектно-ориентированного программирования:

  • Класс (Class): Определенный программистом прототип программируемого объекта с набором атрибутов (переменных и методов), которые описывают данный объект. Доступ к аттрибутам и методам осуществляется через точку
  • Переменная класса (Class variable): Переменная, доступная для всех экземпляров данного класса. Определяется внутри класса, но вне любых методов класса.
  • Экземпляр класса (Instance): Отдельный объект-представитель определенного класса.
  • Переменная экземпляра класса (Instance variable): Переменная определенная внутри медота класса, принадлежащая только к этому классу.
  • Метод (Method): Особая функция, определенная внутри класса.
  • Наследование (Inheritance): Передача аттрибутов и методов родительского класса дочерним классам.
  • Перегрузка функций (Function overloading): Изменение работы метода, унаследованного дочерним классом от родительского класса.
  • Перегрузка операторов (Operator overloading): Определение работы операторов с экземплярами данного класса.

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

Определение класса начинается с ключевого слова class, после него следует имя класса и двоеточие. Теперь с отступом можно описывать сам класс.

class Elevator:
    """ Simple elevator class """
    # Переменная класса. Сколько людей было перевезено ВСЕМИ лифтами
    people_lifted = 0

    # Конструктор класса. Вызывается при создании экземпляра класса
    def __init__(self,name):
        self.name = name
        # переменная экземпляра класса. Количество людей перевезенных КОНКРЕТНЫМ лифтом
        self.people_lifted = 0

    # Метод перевозки людей
    def lift(self):
        print ("{} lifted someone".format(self.name))
        # Увеличиваем количество людей перевезенных ЭТИМ лифтом
        self.people_lifted += 1
        # Увеличиваем количество людей перевезенных ВСЕМИ лифтами
        Elevator.people_lifted += 1

    # Метод печатающий информацию о конкретном лифте
    def info(self):
        print (self.name, "lifted", self.people_lifted, "people out of", Elevator.people_lifted)

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

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

elevator_1 = Elevator("OTIS")
elevator_2 = Elevator("PHILLIPS")

Получение доступа к атрибутам и методам класса:

Чтобы получить доступ к атрибутам класса в Python следует после объекта поставить точку и написать имя переменной или метода, которые вы хотите использовать:

# Везем человека в лифте под именем OTIS
elevator_1.lift()
# Везем двоих человек в лифте под именем PHILLIPS
elevator_2.lift()
elevator_2.lift()
# Получаем информацию по лифту под именем OTIS
elevator_1.info()
# Получаем информацию по лифту под именем PHILLIPS
elevator_2.info()

Соединив все это в одном файле, получим следующее:

Углубленные темы объектно-ориентированного программирования, которые мы еще рассмотрим:

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

Множественное наследование в Python.

Перегрузка операторов в Python.

Сокрытие данных класса в Python.

Принципы ООП.

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



В данной статье даются основы ООП в питоне

В python всё — объекты.

*Аудитория в шоке, особо нервные дамочки падают в обморок*

  • Числа — объекты
  • Строки — объекты
  • Списки — объекты
  • Классы — объекты

Если говорить просто, то «объекты» — это некая структура.


И было слово…

Чтобы создавать объекты, используются «конструкторы» или классы.

  • Класс — это схема, описывающая нашу структуру, возможные внутри неё данные и присущие ей методы.
  • Метод — это функция. Т.е. метод объекта — это функция, описанная внутри объекта, и присущая этому объекту. Метод — это функция, которая действует на объекты данного вида. Для удобства у разных видов объектов могут быть методы с одинаковыми именами, работающие по разному, но схожим образом.
  • Экземпляр — это конкретный объект, созданный из класса.

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

Список:

L = [1, 2, 3, 4]

  • Список (List) — это класс объекта
  • Переменная L содержит экземпляр объекта (конкретно список [1, 2, 3, 4])
  • append(), sort() — методы объекта, т.е. функции, которые можно применить к его экземплярам.

Пока звучит не очень сложно.
Но по прежнему не понятно зачем это нужно. =)

1 что приходит на ум — абстракция. Мы не думаем о том как устроен объект, а думаем о том что мы можем с ним сделать.

Например, возьмём функцию dir() и передадим экземпляр объекта список в неё как аргумент:

dir(L)

На выходе получим большой список. Большой список методов для списка.
У нас есть 2 пути:

  • опробовать некоторые из них (возможно, пытаясь передать какие-то атрибуты)
  • найти их описание в google по имени

Но в любом случае мы узнаем о том, «что можно делать со списком», не изучая то как он устроен.

При этом если мы создадим свою структуру данных, свой класс со своими объектами, то у них могут быть одноимённые методы (например, если они ведут себя аналогично).

Например, у строк есть несколько методов, одноимённых методом списков:


Метод index() является одним из них.

Рассмотрим как он работает для наших примеров:

Легко заметить, что некоторые методы в списке имели по 2 подчёркивания с обеих сторон, например:

__len__

Это «стандартный» метод. Фактически, когда мы используем функцию len(), например:

то на самом деле вызывается метод __len__ соответствующего объекта.

Почему?

Всё потому же — если мы будем внутри функции языка len описывать как вычислять длину любого объекта, то это будет очень много кода. Да и для новых классов объектов (например, numpy.array) эта функция не будет работать.

А так у каждого класса внутри будет краткое описание того как это работает.

Так же это позволяет переопределить поведение некоторых операторов.

Например, что будет, если мы напишем:


Фактически будет вызван метод add — s.__add__(L)

В нашем примере мы получим ошибку:

Но некоторые классы объектов вполне могут принимать на вход «чужака» (не всякого конечно):

А ещё когда мы пишем

print L

, то на самом деле вызывается метод __str__, чтобы преобразовать список L в строку для печати.

Итак, 

  • класс — это инструкция, по которой собирается конкретный объект
  • экземпляр — это конкретный объект
  • а метод — это функция, присущая конкретному классу объектов.

И это всё?

Нет. =)

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

то очевидно, что они содержат разные данные.
Т.е. внутри объектов помимо методов есть данные, и хранятся они в атрибутах.

Примером атрибута может быть shape для numpy:


Мы просто создали вектор, передав в него данные. И при этом вычислился его размер.

Логично, для больших матриц в векторов проще хранить внутри 1 переменную с натуральным числом, чем каждый раз проходить по всем данным и тратить время для вычислений.

Давайте попрактикуемся

Создадим пустой класс, который ничего не делает и ничего не хранит:

Теперь создадим 1й метод у нашего класса.

Для этого создадим функцию, внутри метода. Она должна принимать по крайней мере 1 аргумент — self — это экземпляр того объекта, методов которого функция будет.

Если мы хотим передавать в метод какие-то параметры, то просто зададим их после self, как и обычные параметры функции:

Это всё здорово, но пока особой разницы между методом и функцией нет.

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

Но обычно всё же класс подразумевает ещё и хранение данных в атрибутах.

Синтаксис для атрибутов аналогичен синтаксису методов (только после атрибута не надо ставить круглые скобки):

Давайте создадим атрибут у экземпляра объекта:

Вполне очевидно, что если я создам 2й экземпляр этого же класса, и присвою уже в нём атрибуту с таким же именем какое-то значение, то у разных экземпляров в одноимённом атрибуте будут разные значения:

Так же я могу определить переменную внутри класса и она станет атрибутов всех экземпляров этого класса.

Естественно, это не отменит возможность принудительного переопределения соответствующего атрибута у какого-то экземпляра:


Для экземпляров B и C значение атрибута равно значению по-умолчанию (списку), а для экземпляров E и A переопределено (на число и строку).

Пока пользоваться классами не очень удобно:

  • надо определить класс
  • создать объект
  • обратиться к каждому из атрибутов, записав туда кастомные данные
  • обратиться к каждому объекту, передав туда кастомные аргументы

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

Для этого служит метод __init__().

Перепишем наш класс и убедимся, что его работа не изменилась:

Важно:

  • метод __init__(), как и другие методы класса должен принимать как минимум 1 аргумент self
  • к аргументам объекта можно обращаться из метода как аргументам self (например, self.arg)
  • Если аргумент создаётся конструктором __init__, то его не нужно описывать в классе как отдельную переменную

Если для конструктора __init__ мы зададим какие-то аргументы кроме self, то их можно будет передать в конструктор при создании экземпляра объекта, и сразу записать в аргументы, если необходимо.

Давайте создадим чуть более осмысленный класс.

Пусть это будет класс «Точка». Точка у нас будет характеризоваться 2 координатами (x, y).

И сразу зададим метод для нашей точки, вычисляющий расстояние от неё до другой точки (для этого воспользуемся теоремой Пифагора):

Здесь метод dist принимает 2 аргумента: экземпляр текущего объекта и ещё одного, между которыми необходимо найти расстояние.

Поскольку метод применяется к текущему экземпляру, то при вызове метода в скобках я указываю только 2ю точку).

Если я хочу передавать в мой метод аргументы привычным образом (как аргументы в скобках по порядку), то мне необходимо указать полный путь до метода. Он начнётся с имени класса:


Обратите внимание, что 2й способ обращения позволяет использовать классы как хранилище функций даже для стандартных типов данных.

Вот пример такого «хранилища»:

Заметим, что если мы попытаемся напечатать экземпляр объекта (а не его атрибуты, как раньше), то ничего хорошего не получим:

Мы можем понять экземпляром какого класса объект является и на какую область памяти смотрит указатель, но в работе это довольно бесполезно.

Согласитесь, печатая экземпляр списка мы получаем список — это удобно.

Воспользуемся стандартным методом __str__, который вызывается при его печати с помощью print:

Интересный эффект, который можно заметить — после пересоздания класса ранее созданные объекты не меняют своего поведения.

Дело в том, что класс — это тоже объект.

С точки зрения python мы создали 2 объекта. И на базе 1-ого создали несколько экземпляров.

Поэтому чтобы новые методы добавились у объектов, объекты придётся пересоздать.

Давайте заведём ещё 1 экземпляр объекта с точно такими же координатами, что и первый.

В бытовом понимании 2 такие точки «равны». Но что будет, если мы их сравним?


С точки зрения python это 2 разных объекта, а потому они НЕ равны.

Чтобы это исправить можно написать стандартный метод __eq__:


Замечу, что если мы заведём по новому атрибуту у наших точек (например, цвету), то операция сравнения их учитывать не будет:

Геттеры и Сеттеры

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

Но иногда при добавлении атрибута имеет смысл провести валидацию. Или иметь метод который не перезатирает значение, а добавляет (примером такого метода является append для списков).

Добавим в наш класс 2 новых метода:

  • сеттер — setColor — проверяет, что передаётся строка и записывает её в атрибут color экземпляра. Если передан другой тип данных, возвращает ошибку.
  • геттер — getColor — возвращает значение атрибута color текущего экземпляра

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

=)

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

Идея в том, чтобы хранить в классе только необходимые для него объекты и атрибуты.
И структурировать, объединить в иерархию объекты.
Обычно это иллюстрируется на примерах животных: кошечки, собачки, кролики и т.п.
Есть класс животные, он имеет

  • атрибуты: число ног, имя, возраст.
  • методы: геттеры и сеттеры

Теперь создадим класс кошки. Кошки — тоже животные. Поэтому все атрибуты и методы класса животные им тоже присущи. Но кроме этого, у них могут быть свои:

  • атрибуты: имя и т.п.
  • методы: «говорение» (мяу) и т.п.

Чтобы не дублировать код, класс кошки наследуется от класса животные.

Наследник получает все методы и атрибуты родителя, а так же может некоторые из них переопределить (например, если мы сделаем класс «птицы» наследником класса «животные», то, вероятно, ограничение на число ног изменится с 4 до 2), а так же задать собственные атрибуты и методы.

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

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

Новый класс будет наследником обычной точки, но мы чуть расширим конструктор, чтобы иметь больше атрибутов:


Как видим, наш класс получил возможность использовать сеттер родительского класса, да и стандартная функция __str__ тоже наследуется.

Давайте зададим нашему классу новый метод __str__, чтобы при выводе на печать понимать что это не просто точка, именно маркер. И внутри будем использовать метод __str__ родительского класса:


Т.е. вы всегда можете обратиться к родительским методам у экземпляров дочерних классов, если это необходимо.

Давайте создадим ещё пару классов.

1 будет идентичен предыдущим — это будет класс иконок с геттером и сеттером:

Такие классы ещё иногда называются «примесью», дальше станет понятно почему.

А вот 2 будет интереснее. Это будет класс организации. И мы не станем записывать для него ни атрибутов, ни классов. Но унаследуем его от 2 родителей:

Удивительно, но это работает.

При этом:

  • наследник получает все методы и атрибуты обоих родителей.
  • если у нескольких родителей есть одноимённые методы, то автоматически наследник получит методы того, кто раньше в списке (в нашем случае раньше был гео маркер, поэтому конструктор был унаследован от него, а не от организации).

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

Переменные класса

Мы уже говорили про атрибуты в качестве хранилища данных (мы даже создавали их внутри класса в самом начале).
Есть ещё одно интересное применение для них — переменная класса. Т.е переменные, которые хранятся в классе, а не в экземпляре.

Модифицируем конструктор организации (добавим заодно поддержку url). В классе создадим переменную tag с первоначальным значением равным 0. В конструкторе же запишем в переменную ID создаваемого экземпляра значение из tag, а tag после этого увеличим на 1:


Таким образом мы получили:

  • в атрибуте ID каждого объекта хранится его уникальный порядковый номер
  • в переменной tag класса хранится число созданных объектов (тут надо быть осторожнее, так как возможно мы захотим уменьшать это число при удалении объекта).

Ну и не забываем, что каждый экземпляр имеет доступ к атрибутам класса помимо собственных, т.е. tag:

Переиспользование методов

Мы уже говорили про наследование методов, мы даже использовали методы родительского класса.
Но можно наследовать часть родительского метода (и собирать из нескольких родительских 1 свой). Сократим наш код организации, унаследовав конструкторы гео маркера и иконки:

Мы совместили 2 наследуемых метода и свой код.
И всё это работает.
=)


Полезные ссылки:

Элегантное ООП на Python. Безболезненное преобразование словарей… | by Iuliia Averianova | NOP::Nuances of Programming

Сила Python в его гибкости. Это один из самых простых языков для объектно-ориентированного программирования. Иногда его даже критикуют за чрезмерную гибкость. Я покажу самый элегантный на мой взгляд способ объектно-ориентированного программирования в Python. Ключ к элегантности — библиотека marshmallow. Она устанавливается командой pip install marshmallow.

Для демонстрации давайте начнём с объявления простого класса User:

class User(object):
def __init__(self, name, age):
self.name = name
self.age = agedef __repr__(self):
return f'I am {self.name} and my age is {self.age}'

OK. У User только два атрибута: name и age. Обратите внимание, что я также реализовал метод __repr__, чтобы мы легко могли вывести экземпляр для проверки. Затем импортируем некоторые модули и методы из библиотеки marshmallow:

from marshmallow import Schema, fields, post_load
from pprint import pprint

Я импортировал pprint, потому что собираюсь отобразить множество словарей и списков. Так они будут выглядеть лучше. Так как же использовать marshmallow? Предельно просто: определите Schema для класса User:

class UserSchema(Schema):
name = fields.String()
age = fields.Integer()@post_load
def make(self, data, **kwargs):
return User(**data)

Для каждого атрибута необходимо объявить поля — fields, а затем тип. Аннотация @post_load опциональная. Она нужна для загрузки схемы в качестве экземпляра какого-либо класса. Следовательно, в нашем случае она нужна для генерации экземпляров User. Метод make реализует экземпляр с помощью атрибутов.

Если у нас есть словарь (объект JSON) и нам нужен экземпляр, пишем такой код:

data = {
'name': 'Chris',
'age': 32
}schema = UserSchema()
user = schema.load(data)

Всё просто! Вызываем метод схемы load() и десериализуем объект JSON в экземпляр класса.

Что, если мы работаем с массивом JSON, содержащим множество объектов для десериализации? Не нужно писать for, просто укажите many=True:

data = [{
'name': 'Alice',
'age': 20
}, {
'name': 'Bob',
'age': 25
}, {
'name': 'Chris',
'age': 32
}]schema = UserSchema()
users = schema.load(data, many=True)

OK. Теперь мы знаем, что можем вызвать метод load() для преобразования словарей в экземпляры. Как насчёт обратного действия? Используем метод dump():

dict = schema.dump(users, many=True)

Здесь users — список экземпляров из предыдущего примера. Мы видим, как список пользователей преобразуется в массив JSON одной строкой кода!

Думаете, marshmallow умеет только сериализовывать и десериализовывать экземпляры? Если бы это было так, я бы вряд ли взялся за эту статью. Самая мощная функция этой библиотеки — валидация. Начнём с простого примера. Сначала импортируем ValidationError, исключение из marshmallow:

from marshmallow import ValidationError

Помните, мы объявили UserSchema выше с полем age как Integer? Что, если мы передадим недопустимое значение?

data = [{
'name': 'Alice',
'age': 20
}, {
'name': 'Bob',
'age': 25
}, {
'name': 'Chris',
'age': 'thirty two'
}]

Пожалуйста, обратите внимание, что третий объект — Chris — в массиве JSON имеет недопустимый формат, из-за которого его нельзя преобразовать в целое число. Теперь вызовем метод load(), чтобы десериализовать массив.

try:
schema = UserSchema()
users = schema.load(data, many=True)
except ValidationError as e:
print(f'Error Msg: {e.messages}')
print(f'Valid Data: {e.valid_data}')

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

Кроме того, в этом примере только у третьего объекта возникла проблема валидации. Сообщение говорит нам о том, что ошибка произошла в индексе 2, и допустимые объекты всё ещё могут быть выведены.

Конечно, проверки только по типам данных недостаточно. Библиотека поддерживает куда больше методов валидации. Добавим в класс User атрибут gender.

class User(object):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = genderdef __repr__(self):
return f'I am {self.name}, my age is {self.age} and my gender is {self.gender}'

Затем определим схему с валидациями. И, конечно, импортируем из библиотеки функцию validate.

from marshmallow import validateclass UserSchema(Schema):
name = fields.String(validate=validate.Length(min=1))
age = fields.Integer(validate=validate.Range(min=18, max=None))
gender = fields.String(validate=validate.OneOf(['F', 'M', 'Other']))

Мы добавили валидации ко всем трём полям.

  • У name длина должна быть хотя бы в 1 символ. Иными словами, поле не может быть пустым.
  • У age значение должно быть больше или равно 18.
  • Поле gender должно принимать одно из трёх значений.

Давайте определим объект JSON с недопустимыми значениями всех полей:

data = {
'name': '',
'age': 16,
'gender': 'X'
}

И попробуем загрузить его:

try:
UserSchema().load(data)
except ValidationError as e:
pprint(e.messages)

Неудивительно, что обнаружены исключения, но, когда я увидел этот вывод впервые, меня поразило, что сообщения об ошибках встроены по умолчанию. Я сэкономил кучу времени!

Вы можете спросить, ограничены ли мы встроенными методами валидации, такими как диапазон, длина или выбор одного из значений, как в примере выше. Что, если мы захотим написать собственный метод валидации? Конечно, это возможно:

def validate_age(age):
if age < 18:
raise ValidationError('You must be an adult to buy our products!')class UserSchema(Schema):
name = fields.String(validate=validate.Length(min=1))
age = fields.Integer(validate=validate_age)
gender = fields.String(validate=validate.OneOf(['F', 'M', 'Other']))

Здесь мы определили метод validate_age с пользовательскими логикой и сообщением. Теперь определим объект JSON, чтобы протестировать этот метод. В следующем примере age меньше 18.

data = {
'name': 'Chris',
'age': 17,
'gender': 'M'
}try:
user = UserSchema().load(data)
except ValidationError as e:
pprint(e.messages)

Теперь validate_age применяет пользовательские логику и сообщение об ошибке. Ниже элегантная реализация:

class UserSchema(Schema):
name = fields.String()
age = fields.Integer()
gender = fields.String()@validates('age')
def validate_age(self, age):
if age < 18:
raise ValidationError('You must be an adult to buy our products!')

Через аннотацию мы определяем валидацию внутри класса.

Конечно, можно определить поля, требующие заполнения:

class UserSchema(Schema):
name = fields.String(required=True, error_messages={'required': 'Please enter your name.'})
age = fields.Integer(required=True, error_messages={'required': 'Age is required.'})
email = fields.Email()

В этом примере обязательны поля name и age. Теперь давайте проверим валидацию объектом без электронной почты:

data_no_email = {
'name': 'Chris',
'age': 32
}try:
user = UserSchema().load(data_no_email)
except ValidationError as e:
pprint(e.messages)

OK. Проблем не возникло. Что, если в объекте не указаны ни имя, ни возраст?

data_no_name_age = {
'email': '[email protected]'
}try:
user = UserSchema().load(data_no_name_age)
except ValidationError as e:
print(f'Error Msg: {e.messages}')
print(f'Valid Data: {e.valid_data}')

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

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

class UserSchema(Schema):
name = fields.String(missing='Unknown', default='Unknown')print(UserSchema().load({})) # Принять значение "missing"
print(UserSchema().dump({})) # Принять значение "default"

В marshmallow существует два способа определить значения по умолчанию:

  • Ключевое слово missing определяет значение по умолчанию, которое используется при десериализации экземпляра с помощью load().
  • Ключевое слово default определяет значение по умолчанию, которое используется при сериализации экземпляра с помощью dump().

В примере выше мы применили оба ключевых слова и поэкспериментировали над пустым объектом и с методом load(), и с методом dump(). В обоих случаях было добавлено поле name со значением по умолчанию.

Это ещё не конец, продолжаем 🙂

Иногда возникает расхождение в реализации классов и фактических данных в JSON, то есть расхождение имён ключей или атрибутов. Например, в User мы определили атрибут name, однако в объекте JSON используется другое имя для этого поля — username. В нашем случае не нужно ни повторно реализовывать классы, ни преобразовывать ключи в объекте JSON. Можно написать такой код:

class User(object):
def __init__(self, name, age):
self.name = name
self.age = agedef __repr__(self):
return f'I am {self.name} and my age is {self.age}'class UserSchema(Schema):
username = fields.String(attribute='name')
age = fields.Integer()@post_load
def make(self, data, **kwargs):
return User(**data)

Обратите внимание, что в User есть поле name, тогда как в UserSchema есть поле username. Но для username определено, что его attribute должен называться name. Выведем экземпляр класса User:

user = User('Chris', 32)
UserSchema().dump(user)

dump корректно сериализовал экземпляр с именем поля username. И наоборот:

data = {
'username': 'Chris',
'age': 32
}
UserSchema().load(data)

Даже если мы передадим JSON объект с ключом username, он без проблем десериализуется в экземпляр User.

И последнее, но не менее важное, чем всё остальное: marshmallow поддерживает вложенные атрибуты.

class Address(object):
def __init__(self, street, suburb, postcode):
self.street = street
self.suburb = suburb
self.postcode = postcodedef __repr__(self):
return f'{self.street}, {self.suburb} {self.postcode}'class User(object):
def __init__(self, name, address):
self.name = name
self.address = address

def __repr__(self):
return f'My name is {self.name} and I live at {self.address}'

Мы определили два класса: Address и User. У User есть атрибут address, имеющий тип Address. Давайте проверим классы, реализовав объект:

address = Address('1, This St', 'That Suburb', '1234')
user = User('Chris', address)
print(user)

И определим схему:

class AddressSchema(Schema):
street = fields.String()
suburb = fields.String()
postcode = fields.String()@post_load
def make(self, data, **kwargs):
return Address(**data)class UserSchema(Schema):
name = fields.String()
address = fields.Nested(AddressSchema())@post_load
def make(self, data, **kwargs):
return User(**data)

Хитрость здесь в том, чтобы использовать fields.Nested() для определения поля по другой схеме. У нас уже есть экземпляр User. Давайте сделаем его дамп в JSON:

pprint(UserSchema().dump(user))

Как видите, экземпляр сериализован во вложенный объект JSON Конечно, обратный вариант тоже работает:

data = {
'name': 'Chris',
'address': {
'postcode': '1234',
'street': '1, This St',
'suburb': 'That Suburb'
}
}
pprint(UserSchema().load(data))

На сегодня всё. Спасибо, что прочитали! Код из статьи вы найдёте на Google Colab.

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен

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

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

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

Объект содержит данные, такие как необработанные или предварительно обработанные материалы на каждом этапе сборочной линии, и поведение, такое как действие, которое выполняет каждый компонент сборочной линии.

Из этого руководства вы узнаете, как:

  • Создайте класс , который похож на чертеж для создания объекта
  • Используйте классы для создания новых объектов
  • Модельные системы с наследованием классов

Примечание: Это руководство адаптировано из главы «Объектно-ориентированное программирование (ООП)» в книге Основы Python: Практическое введение в Python 3 .

В книге используется встроенный редактор IDLE Python для создания и редактирования файлов Python и взаимодействия с оболочкой Python, поэтому вы будете время от времени видеть ссылки на IDLE в этом руководстве. Однако у вас не должно возникнуть проблем с запуском примера кода из редактора и среды по вашему выбору.

Что такое объектно-ориентированное программирование в Python?

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

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

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

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

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

Определите класс в Python

Примитивные структуры данных, такие как числа, строки и списки, предназначены для представления простых частей информации, таких как стоимость яблока, название стихотворения или ваши любимые цвета, соответственно. Что, если вы хотите изобразить что-то более сложное?

Например, предположим, вы хотите отслеживать сотрудников в организации. Вам необходимо сохранить некоторую основную информацию о каждом сотруднике, такую ​​как их имя, возраст, должность и год, в котором они начали работать.

Один из способов сделать это — представить каждого сотрудника в виде списка:

  kirk = ["Джеймс Кирк", 34, "Капитан", 2265]
spock = ["Спок", 35, "Научный сотрудник", 2254]
mccoy = ["Леонард Маккой", "Главный врач", 2266]
  

У этого подхода есть ряд проблем.

Во-первых, это может затруднить управление большими файлами кода. Если вы укажете kirk [0] на несколько строк от того места, где объявлен список kirk , запомните ли вы, что элемент с индексом 0 — это имя сотрудника?

Во-вторых, это может привести к ошибкам, если не у всех сотрудников одинаковое количество элементов в списке.В приведенном выше списке mccoy возраст отсутствует, поэтому mccoy [1] вернет «Главный врач» вместо возраста доктора Маккой.

Отличный способ сделать этот тип кода более управляемым и более удобным в обслуживании — это использовать классы .

Классы и экземпляры

Классы используются для создания пользовательских структур данных. Классы определяют функции, называемые методами , которые определяют поведение и действия, которые объект, созданный из класса, может выполнять со своими данными.

В этом руководстве вы создадите класс Dog , в котором будет храниться некоторая информация о характеристиках и поведении отдельной собаки.

Класс — это образец того, как что-то должно быть определено. На самом деле он не содержит никаких данных. Класс Dog указывает, что имя и возраст необходимы для определения собаки, но не содержит имени или возраста какой-либо конкретной собаки.

В то время как класс является схемой, экземпляр — это объект, созданный из класса и содержащий реальные данные.Экземпляр класса Dog больше не является планом. Это настоящая собака с таким именем, как Майлз, которому четыре года.

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

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

Все определения классов начинаются с ключевого слова class , за которым следует имя класса и двоеточие.Любой код с отступом под определением класса считается частью тела класса.

Вот пример класса Dog :

Тело класса Dog состоит из одного оператора: ключевого слова pass . pass часто используется как заполнитель, указывающий, куда в конечном итоге пойдет код. Это позволяет запускать этот код, не вызывая ошибки Python.

Примечание. Имена классов Python записываются в нотации CapitalizedWords по соглашению.Например, класс для определенной породы собак, такой как джек-рассел-терьер, будет записан как JackRussellTerrier .

Класс Dog сейчас не очень интересен, поэтому давайте немного его украсим, определив некоторые свойства, которые должны иметь все объекты Dog . Мы можем выбирать из ряда свойств, включая имя, возраст, цвет шерсти и породу. Для простоты мы будем использовать имя и возраст.

Свойства, которые должны иметь все объекты Dog , определены в методе .__init __ () . Каждый раз, когда создается новый объект Dog , .__ init __ () устанавливает начальное состояние объекта, присваивая значения свойствам объекта. То есть .__ init __ () инициализирует каждый новый экземпляр класса.

Вы можете указать .__ init __ () любое количество параметров, но первым параметром всегда будет переменная с именем self . Когда создается новый экземпляр класса, он автоматически передается в параметр self в .__init __ () , чтобы для объекта можно было определить новые атрибуты .

Давайте обновим класс Dog с помощью метода .__ init __ () , который создает атрибуты .name и .age :

  класс Собака:
    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст
  

Обратите внимание, что подпись метода .__ init __ () имеет отступ в четыре пробела. В теле метода есть восемь пробелов.Этот отступ жизненно важен. Он сообщает Python, что метод .__ init __ () принадлежит классу Dog .

В теле .__ init __ () есть два оператора, использующие переменную self :

  1. self.name = name создает атрибут с именем name и присваивает ему значение параметра name .
  2. self.age = age создает атрибут с именем age и присваивает ему значение параметра age .

Атрибуты, созданные в .__ init __ () , называются атрибутами экземпляра . Значение атрибута экземпляра зависит от конкретного экземпляра класса. Все объекты Dog имеют имя и возраст, но значения атрибутов name и age будут различаться в зависимости от экземпляра Dog .

С другой стороны, атрибутов класса — это атрибуты, которые имеют одинаковое значение для всех экземпляров класса.Вы можете определить атрибут класса, присвоив значение имени переменной вне .__ init __ () .

Например, следующий класс Dog имеет атрибут класса под названием разновидностей со значением "Canis knownis" :

  класс Собака:
    # Атрибут класса
    разновидности = "Canis knownis"

    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст
  

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

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

Теперь, когда у нас есть класс Dog , давайте создадим несколько собак!

Создание экземпляра объекта в Python

Откройте интерактивное окно IDLE и введите следующее:

>>>

  >>> класс Собака:
...     проходить
  

Это создает новый класс Dog без атрибутов или методов.

Создание нового объекта из класса называется созданием экземпляра объекта. Вы можете создать новый объект Dog , введя имя класса, а затем открывающие и закрывающие круглые скобки:

>>>

  >>> Собака ()
<__ main__.Dog объект в 0x106702d30>
  

Теперь у вас есть новый объект Dog по адресу 0x106702d30 .Эта забавно выглядящая строка букв и цифр представляет собой адрес памяти , который указывает, где в памяти вашего компьютера хранится объект Dog . Обратите внимание, что адрес, который вы видите на экране, будет другим.

Теперь создайте второй объект Dog :

>>>

  >>> Собака ()
<__ main__.Dog объект по адресу 0x0004ccc90>
  

Новый экземпляр Dog расположен по другому адресу памяти. Это потому, что это совершенно новый экземпляр, который полностью отличается от первого созданного вами объекта Dog .

Чтобы увидеть это по-другому, введите следующее:

>>>

  >>> a = Собака ()
>>> b = Собака ()
>>> а == б
Ложь
  

В этом коде вы создаете два новых объекта Dog и назначаете их переменным a и b . Когда вы сравниваете a и b с помощью оператора == , результатом будет False . Несмотря на то, что a и b являются экземплярами класса Dog , они представляют два различных объекта в памяти.

Атрибуты класса и экземпляра

Теперь создайте новый класс Dog с атрибутом класса .species и двумя атрибутами экземпляра с именем .name и .age :

.
>>>

  >>> класс Собака:
... разновидности = "Canisiliaris"
... def __init __ (я, имя, возраст):
... self.name = имя
... self.age = возраст
  

Чтобы создать экземпляры объектов этого класса Dog , вам необходимо предоставить значения для name и age .Если вы этого не сделаете, Python выдаст TypeError :

.
>>>

  >>> Собака ()
Отслеживание (последний вызов последний):
  Файл "", строка 1, в 
    Собака()
TypeError: __init __ () отсутствует 2 обязательных позиционных аргумента: 'name' и 'age'
  

Чтобы передать аргументы параметрам name и age , поместите значения в круглые скобки после имени класса:

>>>

  >>> buddy = Dog ("Приятель", 9)
>>> miles = Dog ("Мили", 4)
  

Это создает два новых экземпляра Dog — один для девятилетней собаки по имени Бадди и один для четырехлетней собаки по имени Майлз.

Метод .__ init __ () класса Dog имеет три параметра, так почему в этом примере ему передаются только два аргумента?

Когда вы создаете экземпляр объекта Dog , Python создает новый экземпляр и передает его первому параметру .__ init __ () . Это по существу удаляет параметр self , поэтому вам нужно беспокоиться только о параметрах name и age .

После создания экземпляров Dog вы можете получить доступ к их атрибутам экземпляра, используя точечную нотацию :

>>>

  >>> дружище.имя
'Приятель'
>>> buddy.age
9

>>> miles.name
'Майлз'
>>> miles.age
4
  

Таким же образом можно получить доступ к атрибутам класса:

>>>

  >>> buddy.species
'Canis familis'
  

Одним из самых больших преимуществ использования классов для организации данных является то, что экземпляры гарантированно будут иметь ожидаемые атрибуты. Все экземпляры 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" , который является разновидностью кошки.Это делает Майлза довольно странной собакой, но это настоящий Python!

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

Методы экземпляра

Методы экземпляра — это функции, которые определены внутри класса и могут быть вызваны только из экземпляра этого класса. Как и .__ init __ () , первым параметром метода экземпляра всегда является self .

Откройте новое окно редактора в IDLE и введите следующий класс Dog :

  класс Собака:
    разновидности = "Canis knownis"

    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст

    # Метод экземпляра
    def описание (self):
        return f "{self.name} {self.age} лет"

    # Другой метод экземпляра
    def говорить (сам, звук):
        return f "{self.name} говорит {звук}"
  

Этот класс Dog имеет два метода экземпляра:

  1. .description () возвращает строку, отображающую имя и возраст собаки.
  2. .speak () имеет один параметр с именем sound и возвращает строку, содержащую имя собаки и звук, который издает собака.

Сохраните измененный класс Dog в файл с именем dog.py и нажмите F5 , чтобы запустить программу. Затем откройте интерактивное окно и введите следующее, чтобы увидеть методы вашего экземпляра в действии:

>>>

  >>> miles = Dog ("Мили", 4)

>>> миль.описание()
"Майлзу 4 года"

>>> miles.speak ("Гав-гав")
'Майлз говорит Гав-Гав'

>>> miles.speak ("Bow Wow")
"Майлз говорит:" Вау! "
  

В приведенном выше классе Dog .description () возвращает строку, содержащую информацию об экземпляре Dog miles . При написании собственных классов рекомендуется иметь метод, возвращающий строку, содержащую полезную информацию об экземпляре класса. Однако .description () — не самый питонский способ сделать это.

Когда вы создаете объект list , вы можете использовать print () для отображения строки, которая выглядит как список:

>>>

  >>> names = ["Флетчер", "Дэвид", "Дэн"]
>>> печать (имена)
["Флетчер", "Дэвид", "Дэн"]
  

Давайте посмотрим, что произойдет, когда вы напечатаете () объект миль :

>>>

  >>> печать (мили)
<__ main__.Объект "Собака" по адресу 0x00aeff70>
  

Когда вы печатаете (миль) , вы получаете загадочное сообщение о том, что миль — это объект Dog по адресу памяти 0x00aeff70 . Это сообщение бесполезно. Вы можете изменить то, что печатается, определив специальный метод экземпляра с именем .__ str __ () .

В окне редактора измените имя метода .description () класса Dog на .__str __ () :

  класс Собака:
    # Остальные части класса Dog оставьте как есть

    # Замените .description () на __str __ ()
    def __str __ (сам):
        return f "{self.name} {self.age} лет"
  

Сохраните файл и нажмите F5 . Теперь, когда вы печатаете (миль) , вы получаете гораздо более удобный результат:

>>>

  >>> miles = Dog ("Мили", 4)
>>> печать (мили)
"Майлзу 4 года"
  

Методы, подобные .__init __ () и .__ str __ () называются методами dunder , потому что они начинаются и заканчиваются двойным подчеркиванием. Есть много ужасных методов, которые вы можете использовать для настройки классов в Python. Хотя это слишком сложная тема для начинающей книги по Python, понимание dunder-методов является важной частью освоения объектно-ориентированного программирования на Python.

В следующем разделе вы увидите, как расширить свои знания и создать классы из других классов.

Проверьте свое понимание

Разверните блок ниже, чтобы проверить свое понимание:

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

  1. .color , в котором название цвета автомобиля хранится в виде строки
  2. .

  3. . Пробег , в котором хранится количество миль на автомобиле в виде целого числа

Затем создайте экземпляры двух объектов Car — синего автомобиля с пробегом 20 000 миль и красного автомобиля с пробегом 30 000 миль — и распечатайте их цвета и пробег.Ваш результат должен выглядеть так:

  У синей машины 20 000 миль.
У красной машины 30 000 миль.
  

Вы можете развернуть блок ниже, чтобы увидеть решение:

Сначала создайте класс Car с атрибутами экземпляра .color и .m:

  класс Автомобиль:
    def __init __ (сам, цвет, пробег):
        self.color = цвет
        собственный пробег = пробег
  

Цвет и пробег параметры .__init __ () присваиваются self.color и self.m, что создает два атрибута экземпляра.

Теперь вы можете создать два экземпляра Car :

  blue_car = Автомобиль (цвет = "синий", пробег = 20_000)
red_car = Автомобиль (цвет = "красный", пробег = 30_000)
  

Экземпляр blue_car создается путем передачи значения «синий» в параметр цвета и 20_000 в параметр пробег .Аналогичным образом создается red_car со значениями «красный» и 30_000 .

Чтобы распечатать цвет и пробег каждого объекта Car , вы можете перебрать кортеж , содержащий оба объекта:

  на машину в (blue_car, red_car):
    print (f "У машины {car.color} {car.m900 :,} миль")
  

Строка f в приведенном выше цикле для вставляет атрибуты .color и .m gather в строку и использует спецификатор формата :, для печати пробега, сгруппированного по тысячам и разделенных запятой.

Окончательный результат выглядит так:

  У синей машины 20 000 миль.
У красной машины 30 000 миль.
  

Когда будете готовы, можете переходить к следующему разделу.

Наследование от других классов в Python

Наследование — это процесс, при котором один класс перенимает атрибуты и методы другого. Вновь сформированные классы называются дочерними классами , а классы, производные от дочерних классов, называются родительскими классами .

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

Хотя аналогия не идеальна, вы можете думать о наследовании объектов как о генетическом наследовании.

Возможно, вы унаследовали цвет волос от матери. Это атрибут, с которым вы родились. Допустим, вы решили покрасить волосы в фиолетовый цвет.Предполагая, что у вашей матери нет фиолетовых волос, вы всего лишь переопределили атрибут цвета волос, который вы унаследовали от своей мамы.

Вы также в некотором смысле наследуете свой язык от своих родителей. Если ваши родители говорят по-английски, то вы тоже будете говорить по-английски. А теперь представьте, что вы решили выучить второй язык, например, немецкий. В этом случае вы расширили своих атрибутов, потому что вы добавили атрибут, которого нет у ваших родителей.

Пример парка собак

Представьте на мгновение, что вы находитесь в собачьем парке.В парке много собак разных пород, и все они ведут себя по-разному.

Предположим, теперь вы хотите смоделировать парк собак с помощью классов Python. Класс Dog , который вы написали в предыдущем разделе, может различать собак по имени и возрасту, но не по породе.

Вы можете изменить класс Dog в окне редактора, добавив атрибут .breed :

  класс Собака:
    разновидности = "Canis knownis"

    def __init __ (я, имя, возраст, порода):
        себя.name = имя
        self.age = возраст
        self.breed = порода
  

Методы экземпляра, определенные ранее, здесь опускаются, потому что они не важны для этого обсуждения.

Нажмите F5 , чтобы сохранить файл. Теперь вы можете смоделировать парк собак, создав несколько экземпляров разных собак в интерактивном окне:

>>>

  >>> miles = Dog ("Майлз", 4, "Джек-Рассел-терьер")
>>> buddy = Собака («Бадди», 9, «Такса»)
>>> jack = Собака («Джек», 3, «Бульдог»)
>>> jim = Dog («Джим», 5, «Бульдог»)
  

У каждой породы собак немного разное поведение.Например, у бульдогов низкий лай, который звучит как гав , но у такс более высокий лай, который больше похож на гав .

Используя только класс Dog , вы должны предоставить строку для аргумента sound из .speak () каждый раз, когда вы вызываете его в экземпляре Dog :

>>>

  >>> buddy.speak ("Яп")
'Бадди говорит Яп'

>>> jim.speak ("Гав")
'Джим говорит Гав'

>>> домкрат.говорить ("Гав")
'Джек говорит Гав'
  

Передача строки при каждом вызове .speak () является повторяющейся и неудобной. Более того, строка, представляющая звук, который издает каждый экземпляр Dog , должна определяться его атрибутом .breed , но здесь вам нужно вручную передавать правильную строку в .speak () каждый раз, когда он вызывается.

Вы можете упростить работу с классом Dog , создав дочерний класс для каждой породы собак.Это позволяет расширить функциональность, которую наследует каждый дочерний класс, включая указание аргумента по умолчанию для .speak () .

Родительские классы и дочерние классы

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

Для справки, вот полное определение класса Dog :

  класс Собака:
    разновидности = "Canis knownis"

    def __init __ (я, имя, возраст):
        себя.name = имя
        self.age = возраст

    def __str __ (сам):
        return f "{self.name} {self.age} лет"

    def говорить (сам, звук):
        return f "{self.name} говорит {звук}"
  

Помните, чтобы создать дочерний класс, вы создаете новый класс с его собственным именем, а затем помещаете имя родительского класса в круглые скобки. Добавьте следующее в файл dog.py , чтобы создать три новых дочерних класса класса Dog :

  класс JackRussellTerrier (Собака):
    проходить

класс Такса (Собака):
    проходить

класс Бульдог (Собака):
    проходить
  

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

>>>

  >>> miles = JackRussellTerrier ("Мили", 4)
>>> buddy = Такса ("Бадди", 9)
>>> jack = Бульдог ("Джек", 3)
>>> jim = Бульдог ("Джим", 5)
  

Экземпляры дочерних классов наследуют все атрибуты и методы родительского класса:

>>>

  >>> miles.species
'Canis familis'

>>> дружище.имя
'Приятель'

>>> печать (домкрат)
Джеку 3 года

>>> jim.speak ("Гав")
'Джим говорит Гав'
  

Чтобы определить, к какому классу принадлежит данный объект, вы можете использовать встроенный тип () :

>>>

  >>> тип (мили)
<класс '__main __. JackRussellTerrier'>
  

Что делать, если вы хотите определить, является ли миль также экземпляром класса Dog ? Вы можете сделать это с помощью встроенного isinstance () :

.
>>>

  >>> isinstance (мили, собака)
Правда
  

Обратите внимание, что isinstance () принимает два аргумента: объект и класс.В приведенном выше примере isinstance () проверяет, является ли миль экземпляром класса Dog и возвращает True .

Объекты miles , buddy , jack и jim являются экземплярами Dog , но miles не являются экземпляром Bulldog , а jack не являются экземпляром Dachshund :

>>>

  >>> isinstance (мили, бульдог)
Ложь

>>> isinstance (Джек, Такса)
Ложь
  

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

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

Расширение функциональности родительского класса

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

Чтобы переопределить метод, определенный в родительском классе, вы определяете метод с тем же именем в дочернем классе.Вот как это выглядит для класса JackRussellTerrier :

  класс JackRussellTerrier (Собака):
    def Speak (self, sound = "Arf"):
        return f "{self.name} говорит {звук}"
  

Теперь .speak () определен в классе JackRussellTerrier с аргументом по умолчанию для звука , установленным на "Arf" .

Обновите dog.py с новым классом JackRussellTerrier и нажмите F5 , чтобы сохранить и запустить файл.Теперь вы можете вызвать .speak () в экземпляре JackRussellTerrier без передачи аргумента в sound :

>>>

  >>> miles = JackRussellTerrier ("Мили", 4)
>>> miles.speak ()
'Майлз говорит Арф'
  

Иногда собаки лают по-разному, поэтому, если Майлз злится и рычит, вы все равно можете позвонить по номеру .speak () с другим звуком:

>>>

  >>> miles.speak ("Гррр")
'Майлз говорит Grrr'
  

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

Например, в окне редактора измените строку, возвращаемую функцией .speak () в классе Dog :

  класс Собака:
    # Остальные атрибуты и методы оставьте как есть

    # Измените строку, возвращаемую .speak ()
    def говорить (сам, звук):
        return f "{self.name} лай: {звук}"
  

Сохраните файл и нажмите F5 . Теперь, когда вы создаете новый экземпляр Bulldog с именем jim , jim.Speak () возвращает новую строку:

>>>

  >>> jim = Бульдог ("Джим", 5)
>>> jim.speak ("Гав")
'Джим лает: Гав'
  

Однако вызов .speak () в экземпляре JackRussellTerrier не покажет новый стиль вывода:

>>>

  >>> miles = JackRussellTerrier ("Мили", 4)
>>> miles.speak ()
'Майлз говорит Арф'
  

Иногда имеет смысл полностью переопределить метод родительского класса.Но в этом случае мы не хотим, чтобы класс JackRussellTerrier потерял любые изменения, которые могут быть внесены в форматирование выходной строки Dog.speak () .

Для этого вам все еще нужно определить метод .speak () для дочернего класса JackRussellTerrier . Но вместо явного определения выходной строки вам нужно вызвать .speak () класса Dog внутри дочернего класса .speak () , используя те же аргументы, которые вы передали JackRussellTerrier.Говори () .

Вы можете получить доступ к родительскому классу из метода дочернего класса, используя super () :

  класс JackRussellTerrier (Собака):
    def Speak (self, sound = "Arf"):
        вернуть супер (). говорить (звук)
  

Когда вы вызываете super (). Speak (звук) внутри JackRussellTerrier , Python ищет в родительском классе Dog метод .speak () и вызывает его с переменной sound .

Обновите dog.py , добавив новый класс JackRussellTerrier . Сохраните файл и нажмите F5 , чтобы вы могли протестировать его в интерактивном окне:

>>>

  >>> miles = JackRussellTerrier ("Мили", 4)
>>> miles.speak ()
Майлз лает: Арф
  

Теперь, когда вы вызываете miles.speak () , вы увидите результат, отражающий новое форматирование в классе Dog .

Примечание: В приведенных выше примерах иерархия классов очень проста.Класс JackRussellTerrier имеет единственный родительский класс — Dog . В реальных примерах иерархия классов может быть довольно сложной.

super () делает гораздо больше, чем просто ищет метод или атрибут в родительском классе. Он просматривает всю иерархию классов в поисках соответствующего метода или атрибута. Если вы не будете осторожны, super () может дать удивительные результаты.

Проверьте свое понимание

Разверните блок ниже, чтобы проверить свое понимание:

Создайте класс GoldenRetriever , который наследуется от класса Dog .Присвойте аргументу sound для GoldenRetriever.speak () значение по умолчанию "Bark" . Используйте следующий код для родительского класса Dog :

.

  класс Собака:
    разновидности = "Canis knownis"

    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст

    def __str __ (сам):
        return f "{self.name} {self.age} лет"

    def говорить (сам, звук):
        return f "{self.name} говорит {звук}"
  

Вы можете развернуть блок ниже, чтобы увидеть решение:

Создайте класс с именем GoldenRetriever , который наследуется от класса Dog и переопределяет .Speak () метод:

  класс GoldenRetriever (Dog):
    def Speak (self, sound = "Лай"):
        вернуть супер (). говорить (звук)
  

Звуку параметру в GoldenRetriever.speak () присвоено значение по умолчанию «Лай» . Затем super () используется для вызова метода .speak () родительского класса с тем же аргументом, переданным в sound , что и метод .speak () класса GoldenRetriever .

Заключение

Из этого руководства вы узнали об объектно-ориентированном программировании (ООП) на Python. Большинство современных языков программирования, таких как Java, C # и C ++, следуют принципам ООП, поэтому полученные здесь знания будут применимы независимо от того, куда приведет ваша карьера программиста.

В этом руководстве вы узнали, как:

  • Определите класс , который является своего рода схемой для объекта
  • Создать экземпляр объекта из класса
  • Используйте атрибутов и методы для определения свойств и поведения объекта
  • Используйте наследование для создания дочерних классов из родительского класса
  • Ссылка на метод родительского класса с помощью super ()
  • Проверить, наследуется ли объект от другого класса, используя isinstance ()

Если вам понравилось то, что вы узнали из этого примера из книги Основы Python: Практическое введение в Python 3 , то обязательно прочтите оставшуюся часть книги.

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

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

Python — это язык программирования с несколькими парадигмами. Он поддерживает разные подходы к программированию.

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

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

Возьмем пример:

Попугай — это объект, так как он обладает следующими свойствами:

  • имя, возраст, цвет как атрибуты
  • пение, танец как поведение

Концепция ООП в Python направлена ​​на создание повторно используемого кода.Эта концепция также известна как СУХОЙ (Не повторяйся).

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


Класс

Класс — это план объекта.

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

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

класс Попугай:
    пройти 

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


Объект

Объект (экземпляр) — это экземпляр класса. Когда класс определен, определяется только описание объекта. Таким образом, ни память, ни хранилище не выделяются.

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

obj = Попугай () 

Здесь obj — это объект класса Parrot .

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

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

  класс Попугай:

    # атрибут класса
    разновидности = "птица"

    # атрибут экземпляра
    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст

# создать экземпляр класса Parrot
blu = Попугай ("Голубой", 10)
woo = Попугай ("Ву", 15)

# доступ к атрибутам класса
print ("Blu is a {}". format (blu .__ class __. разновидности))
print ("Ву тоже {}".формат (ву .__ класс __. виды))

# доступ к атрибутам экземпляра
print ("{} исполнилось {} лет" .format (blu.name, blu.age))
print ("{} {} лет" .format (woo.name, woo.age))  

Выход

  Blu - птица
Ву тоже птица
Блю 10 лет
Ву 15 лет  

В приведенной выше программе мы создали класс с именем Parrot . Затем мы определяем атрибуты. Атрибуты — это характеристика объекта.

Эти атрибуты определены внутри метода класса __init__ .Это метод инициализатора, который запускается первым при создании объекта.

Затем мы создаем экземпляры класса Parrot . Здесь blu и woo — это ссылки (значения) на наши новые объекты.

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

Чтобы узнать больше о классах и объектах, перейдите в раздел Классы и объекты Python


Методы

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

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

  класс Попугай:
    
    # атрибутов экземпляра
    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст
    
    # метод экземпляра
    def Sing (я, песня):
        верните "{} sings {}".формат (собственное имя, песня)

    def dance (сам):
        return "{} теперь танцует" .format (self.name)

# создать экземпляр объекта
blu = Попугай ("Голубой", 10)

# вызываем наши методы экземпляра
print (blu.sing ("Счастливый"))
печать (blu.dance ())  

Выход

  Blu поет 'Happy'
Blu сейчас танцует  

В приведенной выше программе мы определяем два метода: sing () и dance () . Они называются методами экземпляра, потому что они вызываются для объекта экземпляра i.e blu .


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

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

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

  # родительский класс
класс Bird:
    
    def __init __ (сам):
        print («Птица готова»)

    def whoisThis (я):
        print ("Птица")

    def плавать (сам):
        print («Плыви быстрее»)

# дочерний класс
класс Пингвин (Птица):

    def __init __ (сам):
        # вызов функции super ()
        супер().__в этом__()
        print («Пингвин готов»)

    def whoisThis (я):
        print («Пингвин»)

    def run (self):
        print («Беги быстрее»)

пегги = Пингвин ()
peggy.whoisThis ()
peggy.swim ()
peggy.run ()  

Выход

  Птица готова
Пингвин готов
Пингвин
Плыви быстрее
Беги быстрее  

В приведенной выше программе мы создали два класса, то есть Bird (родительский класс) и Penguin (дочерний класс). Дочерний класс наследует функции родительского класса.Мы можем увидеть это из метода swim () .

Опять же, дочерний класс изменил поведение родительского класса. Мы можем видеть это из метода whoisThis () . Кроме того, мы расширяем функции родительского класса, создавая новый метод run () .

Кроме того, мы используем функцию super () внутри метода __init __ () . Это позволяет нам запускать метод __init __ () родительского класса внутри дочернего класса.


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

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

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

  класс Компьютер:

    def __init __ (сам):
        self .__ maxprice = 900

    def sell (self):
        print ("Цена продажи: {}".формат (self .__ maxprice))

    def setMaxPrice (self, price):
        self .__ maxprice = цена

c = Компьютер ()
c.sell ()

# изменить цену
c .__ maxprice = 1000
c.sell ()

# использование функции установки
c.setMaxPrice (1000)
c.sell ()  

Выход

  Цена продажи: 900
Цена продажи: 900
Цена продажи: 1000  

В приведенной выше программе мы определили класс Computer .

Мы использовали метод __init __ () для хранения максимальной продажной цены Computer .Мы пытались изменить цену. Однако мы не можем его изменить, потому что Python обрабатывает __maxprice как частные атрибуты.

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


Полиморфизм

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

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

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

  класс Попугай:

    def fly (self):
        print («Попугай умеет летать»)
    
    def плавать (сам):
        print («Попугай не умеет плавать»)

класс Пингвин:

    def fly (self):
        print («Пингвин не умеет летать»)
    
    def плавать (сам):
        print («Пингвин умеет плавать»)

# Общий интерфейс
def flying_test (птица):
    bird.fly ()

#instantiate objects
blu = Попугай ()
пегги = Пингвин ()

# передача объекта
летающий_тест (blu)
fly_test (пегги)  

Выход

  Попугай умеет летать
Пингвин не умеет летать  

В приведенной выше программе мы определили два класса Parrot и Penguin .У каждого из них есть общий метод fly () . Однако их функции разные.

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


Ключевые моменты, о которых следует помнить:

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

Понять O.O.P. в Python с одной статьей | Джулиан Эррера

Чтобы начать понимать интуицию, лежащую в основе этой техники программирования, давайте взглянем на начальный пример. Представьте, что вам нужно описать машину кому-то, кто никогда ее раньше не видел. Как бы вы это сделали?

Фото vaea Garrido на Unsplash

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

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

Чтобы облегчить компьютерам понимание этих новых концепций, Python использует шаблон программирования под названием объектно-ориентированное программирование , который моделирует концепции с помощью классов и объектов. Это гибкая и мощная парадигма, в которой классы представляют и определяют концепции, а объекты являются экземплярами классов .В примере с автомобилем мы можем создать класс с именем car , который определяет его характеристики для компьютера. Мы могли бы создать тысячи экземпляров этого класса car , которые являются отдельными объектами этого класса.

Идея объектно-ориентированного программирования может показаться абстрактной и сложной, но если вы запрограммировали какое-либо программное обеспечение, вы, возможно, уже использовали объекты, даже не осознавая этого. Почти все в Python — это объект , все числа, строки, списки и словари включены в этот тип элемента.Основная концепция объектно-ориентированного программирования сводится к атрибутам и методам , связанным с типом:

  • Атрибуты — это характеристики, связанные с типом.
  • Методы — это функции, связанные с типом.

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

Как вы можете видеть на изображении выше, когда мы используем функцию типа , как мы только что сделали здесь, Python сообщает нам, к какому классу принадлежит значение или переменная. А поскольку целых чисел и строк являются классами, с ними связано множество атрибутов и методов. Вы можете получить доступ к атрибутам и методам класса с помощью функции dir в Python, как показано ниже:

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

Почему существует множество методов, которые начинаются и заканчиваются двойным подчеркиванием?

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

Если вы хотите знать, что делает конкретный метод, вам следует использовать функцию help :

Когда мы используем функцию help для любой переменной или значения, мы получаем доступ ко всей документации для соответствующего класса. В этом случае мы смотрим на документацию для классов str и int .

Хотя Python поставляется с множеством предопределенных классов для нас, сила объектно-ориентированного программирования проявляется тогда, когда мы определяем наши собственные классы с их собственными атрибутами и методами.

Как упоминалось ранее, цель объектно-ориентированного программирования — помочь определить концепцию реального мира таким образом, чтобы ее понимал компьютер. Давайте создадим новый класс на примере автомобиля:

Давайте проясним конкретные элементы кода:

  • В Python мы используем зарезервированное ключевое слово class , чтобы сообщить компьютеру, что мы запускаем новый класс. . За ним следует имя класса и двоеточие. Руководства по стилю Python рекомендуют, чтобы имена классов начинались с заглавной буквы .В моем случае класс называется Car .
  • После строки с определением класса идет тело класса с отступом вправо по шаблону циклов или функций.
  • Мы рассмотрим специальные методы init и repr в четвертом разделе этой статьи.

Как мы можем расширить наше определение класса Car? Вероятно, он будет иметь те же атрибуты, которые представляют информацию, которую мы хотим связать с автомобилем, например марку и цвет.

Теперь приступим к созданию экземпляра класса Car и присвоим его переменной с именем «my_car». Чтобы создать новый экземпляр любого класса, мы вызываем имя класса, как если бы это была функция:

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

Синтаксис, используемый для доступа к атрибутам, называется точечной нотацией из-за точки, используемой в выражении.Точечная запись позволяет получить доступ к любым возможностям объекта, например к бренду или цвету.

Атрибуты и методы некоторых объектов могут быть другими объектами и могут иметь собственные атрибуты и методы. Например, мы могли бы использовать методы upper или capitalize для изменения обоих строковых атрибутов моего экземпляра:

До сих пор мы создали один экземпляр класса Car и установили его атрибуты. Теперь мы могли бы создать новый экземпляр класса с другими атрибутами:

Методы, по сути, вызываются для того, чтобы объекты выполняли какие-то действия.Например, верхний и заглавные для строк. Ключ к познанию интуиции методов в O.O.P. означает понимать, что методы — это функции, которые работают с атрибутами конкретного экземпляра класса . Когда мы вызываем метод lower для строки, мы переводим содержимое этой конкретной строки в нижний регистр.

Давайте рассмотрим подробнее, создав новый класс с именем Dog и определив наши собственные методы. Во-первых, нам нужно определить класс и создать его экземпляр, как мы делали это раньше с классом Car.Хотя моя собака может быть отличной, она не может выполнять никаких действий, пока я не определю для нее методы. Взгляните на пример:

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

Функция получает параметр под названием «self». Этот параметр представляет экземпляр, в котором выполняется метод.

Даже если моя собака лает, она всегда будет делать это одинаково.Мы можем изменить то, как он будет лаять, с помощью простой модификации кода, чтобы получить гибкость в атрибутах и ​​методах, которые мы настраиваем для наших классов:

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

Итак, при написании кода рекомендуется установить атрибуты и методы, которые будут меняться в зависимости от экземпляра при создании класса, чтобы гарантировать, что каждый экземпляр содержит одни и те же важные атрибуты.Для этого нам нужно использовать специальный метод под названием Constructor .

Конструктор класса — это метод, который вызывается при вызове имени класса. Он всегда называется init .

Он содержит ключевое слово self, которое относится к создаваемому экземпляру, и аргументы, которые будут переданы программистом как атрибуты после создания экземпляра, как мы это делаем в примере ниже:

Второй метод class — это метод repr , который сообщает Python печатать заранее определенный оператор каждый раз, когда вызывается экземпляр класса, как на изображении выше.

Хотите знать, какая функция у того или иного метода? См. Ранее введенную функцию help . Поскольку встроенные классы включают руководство, помогающее пользователям понять интуицию, лежащую в основе каждого метода или атрибута, мы также можем сделать это для наших собственных классов, методов и функций. Мы можем сделать это, добавив Docstring .

Строка документации — это краткий текст, объясняющий, что что-то делает.

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

Другой важный аспект объектно-ориентированного программирования — Inheritance . Точно так же, как у людей есть родители, бабушки и дедушки и т. Д., У объектов есть предки. Принцип наследования позволяет программисту строить отношения между концепциями и группировать их вместе. В частности, это позволяет нам уменьшить дублирование кода за счет обобщения нашего кода.

Например, как мы можем определить представление « других транспортных средств» отдельно от машины, которую мы уже создали, или других домашних животных, кроме моей собаки.Эта характеристика группирования позволяет нам создавать другие классы, которые разделяют некоторые атрибуты существующих классов, но не все из них, чтобы добавлять другие похожие экземпляры без перезаписи существующего кода.

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

С помощью метода наследования мы можем использовать класс транспорта для хранения информации, относящейся ко всем доступным видам транспорта, и сохранить атрибуты, специфичные для автомобилей или поездов, в их собственных классах. Вы можете рассматривать класс MyTransports как родительский класс, а классы Car и Train как братьев и сестер.

Примером, который ближе к задачам, которые вы выполняете в ИТ-отделе, может быть система, которая обслуживает сотрудников вашей компании. У вас может быть класс с именем employee , который может иметь атрибуты для таких вещей, как , полное имя человека, имя пользователя , используемое в системах компании, группы , к которым принадлежит сотрудник, и так далее.В системе также может быть класс менеджера, который также является сотрудником, но с ним связана дополнительная информация, например, сотрудники, которые подчиняются определенному менеджеру.

Классы Python: Учебное пособие по объектно-ориентированному программированию (ООП) с примерами кода

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

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

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

Объектно-ориентированное программирование основано на парадигме императивного программирования, которая использует операторы для изменения состояния программы. Он фокусируется на описании того, как должна работать программа. Примеры императивных языков программирования: C, C ++, Java, Go, Ruby и Python. Это контрастирует с декларативным программированием, которое фокусируется на том, что должна выполнять компьютерная программа, без указания того, как. Примерами являются языки запросов к базам данных, такие как SQL и XQuery, где один только сообщает компьютеру, какие данные и откуда запрашивать, а теперь как это сделать.

ООП использует концепцию объектов и классов. Класс можно рассматривать как «план» для объектов. Они могут иметь свои собственные атрибуты (характеристики, которыми они обладают) и методы (действия, которые они выполняют).

Пример ООП

Примером класса является класс Dog . Не думайте об этом как о конкретной собаке или своей собственной собаке. Мы описываем, что такое собака , и может делать в целом. Собаки обычно имеют кличку и возраст ; это атрибуты экземпляра.Собаки также могут лаять ; это метод.

Когда вы говорите о конкретной собаке, у вас будет объект в программировании: объект является экземпляром класса. Это основной принцип, на котором основано объектно-ориентированное программирование. Так что моя собака Оззи, например, принадлежит к классу Dog . Его атрибуты: name = 'Ozzy' и age = '2' . У разных собак будут разные атрибуты.

ООП в Python

Python — отличный язык программирования, поддерживающий ООП.Вы будете использовать его для определения класса с атрибутами и методами, которые затем будете вызывать. Python предлагает ряд преимуществ по сравнению с другими языками программирования, такими как Java, C ++ или R. Это динамический язык с типами данных высокого уровня. Это означает, что разработка происходит намного быстрее, чем на Java или C ++. От программиста не требуется объявлять типы переменных и аргументов. Это также упрощает понимание и изучение Python для начинающих, а его код становится более читаемым и интуитивно понятным.

Если вы новичок в Python, обязательно ознакомьтесь с курсом DataCamp Intro to Python for Data Science.

Как создать класс

Чтобы определить класс в Python, вы можете использовать ключевое слово class , за которым следует имя класса и двоеточие. Внутри класса должен быть определен метод __init__ с def . Это инициализатор, который позже можно использовать для создания экземпляров объектов. Он похож на конструктор в Java. __init__ должен присутствовать всегда! Он принимает один аргумент: self , который относится к самому объекту.Внутри метода сейчас используется ключевое слово pass , потому что Python ожидает, что вы что-то там напечатаете. Не забывайте использовать правильный отступ!

  класс Собака:

    def __init __ (сам):
        проходить
  

Примечание : self в Python эквивалентно , а это в C ++ или Java.

В этом случае у вас есть (в основном пустой) класс Dog , но еще нет объекта. Создадим один!

Создание экземпляров объектов

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

  Оззи = Собака ()
  

И распечатайте:

  печать (оззи)
  
  <__ main__.Dog объект в 0x111f47278>
  

Добавление атрибутов в класс

После печати ozzy становится ясно, что это собака. Но вы еще не добавили никаких атрибутов. Давайте дадим классу Dog имя и возраст, переписав его:

.

  класс Собака:

    def __init __ (я, имя, возраст):
        себя.name = имя
        self.age = возраст
  

Вы можете видеть, что функция теперь принимает два аргумента после self : name и age . Затем им присваиваются значения self.name и self.age соответственно. Теперь вы можете создать новый объект ozzy с именем и возрастом:

.

  ozzy = Собака ("Оззи", 2)
  

Для доступа к атрибутам объекта в Python вы можете использовать точечную нотацию.Это делается путем ввода имени объекта, точки и имени атрибута.

  печать (ozzy.name)

печать (ozzy.age)
  
  Оззи
2
  

Это также можно объединить в более сложное предложение:

  print (ozzy.name + "is" + str (ozzy.age) + "год (лет).")
  
  Оззи 2 года (лет).
  

Функция str () используется здесь для преобразования атрибута age , который является целым числом, в строку, чтобы вы могли использовать его в функции print () .

Определите методы в классе

Теперь, когда у вас есть класс Dog , у него есть имя и возраст, которые вы можете отслеживать, но на самом деле он ничего не делает. Вот тут-то и пригодятся методы экземпляра. Вы можете переписать класс, включив в него метод bark () . Обратите внимание, как снова используется ключевое слово def , а также аргумент self .

  класс Собака:

    def __init __ (я, имя, возраст):
        себя.name = имя
        self.age = возраст

    def кора (сам):
        печать («кора кора!»)
  

Метод bark теперь может быть вызван с использованием точечной записи после создания нового объекта ozzy . Метод должен напечатать «кора, кора!» к экрану. Обратите внимание на круглые скобки (фигурные скобки) в .bark () . Они всегда используются при вызове метода. В этом случае они пусты, поскольку метод bark () не принимает никаких аргументов.

  ozzy = Собака ("Оззи", 2)

ozzy.bark ()
  
  кора кора!
  

Вспомните, как вы раньше печатали ozzy ? Приведенный ниже код теперь реализует эту функциональность в классе Dog с методом doginfo () . Затем вы создаете экземпляры некоторых объектов с разными свойствами и вызываете для них метод.

  класс Собака:

    def __init __ (я, имя, возраст):
        self.name = имя
        себя.age = возраст

    def кора (сам):
        печать («кора кора!»)

    def doginfo (сам):
        print (self.name + "is" + str (self.age) + "year (s) old.")
  
  ozzy = Собака ("Оззи", 2)
skippy = Dog ("Скиппи", 12)
filou = Собака ("Filou", 8)
  
  ozzy.doginfo ()
skippy.doginfo ()
filou.doginfo ()
  
  Оззи 2 года (лет).
Скиппи 12 лет.
Филу 8 лет. 

Как видите, вы можете вызывать метод doginfo () для объектов с точечной нотацией. Теперь ответ зависит от того, для какого объекта Dog вы вызываете метод.

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

  ozzy.age = 3
  
  печать (ozzy.age)
  
  3
  

Это так же просто, как присвоить атрибуту новое значение.Вы также можете реализовать это как метод birthday () в классе Dog :

  класс Собака:

    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст

    def кора (сам):
        печать («кора кора!»)

    def doginfo (сам):
        print (self.name + "is" + str (self.age) + "year (s) old.")

    def день рождения (сам):
        self.age + = 1
  
  ozzy = Собака ("Оззи", 2)
  
  печать (ozzy.возраст)
  
  2
  
  оззи. День рождения ()
  
  печать (ozzy.age)
  
  3
  

Теперь вам не нужно вручную изменять возраст собаки. всякий раз, когда у него день рождения, вы можете просто вызвать метод birthday () .

Передача аргументов методам

Вы бы хотели, чтобы у наших собак был приятель. Это должно быть необязательно, поскольку не все собаки так общительны.Взгляните на метод setBuddy () ниже. Он принимает self , как обычно, и buddy в качестве аргументов. В этом случае buddy будет еще одним объектом Dog . Установите для атрибута self.buddy значение buddy и для атрибута buddy.buddy значение self . Это означает, что отношения взаимны; ты приятель твоего приятеля. В этом случае Филу будет приятелем Оззи, а это означает, что Оззи автоматически становится приятелем Филу.Вы также можете установить эти атрибуты вручную вместо определения метода, но это потребует больше работы (написание 2 строк кода вместо 1) каждый раз, когда вы захотите установить друга. Обратите внимание, что в Python вам не нужно указывать тип аргумента. Если бы это была Java, это потребовалось бы.

  класс Собака:

    def __init __ (я, имя, возраст):
        self.name = имя
        self.age = возраст

    def кора (сам):
        печать («кора кора!»)

    def doginfo (сам):
        печать (сам.name + "is" + str (self.age) + "год (лет)")

    def день рождения (сам):
        self.age + = 1

    def setBuddy (я, приятель):
        self.buddy = приятель
        buddy.buddy = self
  

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

.

  ozzy = Собака ("Оззи", 2)
filou = Собака ("Filou", 8)

ozzy.setBuddy (filou)
  

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

  печать (ozzy.buddy.name)
печать (ozzy.buddy.age)
  
  Филу
8
  

Обратите внимание, как это можно сделать и для Filou.

  печать (filou.buddy.name)
печать (filou.buddy.age)
  
  Оззи
2
  

Методы приятеля также могут быть вызваны. Аргумент self , который передается в doginfo () , теперь равен ozzy.приятель , то есть filou .

  ozzy.buddy.doginfo ()
  
  Филу 8 лет (лет).
  

Пример: ООП в Python для финансов

Примером, где может пригодиться объектно-ориентированное программирование на Python, является наш учебник «Python для финансов: алгоритмическая торговля». В нем Карлин объясняет, как настроить торговую стратегию для портфеля акций. Торговая стратегия основана на скользящей средней цены акции.Если выполняется сигналов ['short_mavg'] [short_window:]> сигналов ['long_mavg'] [short_window:] , создается сигнал. Этот сигнал является предсказанием будущего изменения цены акции. В приведенном ниже коде вы увидите, что сначала выполняется инициализация, а затем вычисление скользящего среднего и генерация сигнала. Поскольку это не объектно-ориентированный код, это всего лишь один большой фрагмент, который выполняется сразу. Обратите внимание, что в примере мы используем aapl , тикер акций Apple.Если вы захотите сделать это для другой акции, вам придется переписать код.

  # Инициализировать
short_window = 40
long_window = 100
сигналы = pd.DataFrame (индекс = aapl.index)
сигналы ['signal'] = 0,0

# Создайте короткую простую скользящую среднюю по короткому окну
сигналы ['short_mavg'] = aapl ['Close']. Rolling (window = short_window, min_periods = 1, center = False) .mean ()

# Создать длинную простую скользящую среднюю по длинному окну
сигналы ['long_mavg'] = aapl ['Закрыть'].скользящее (окно = длинное_окно, min_periods = 1, center = False) .mean ()

# Создать сигналы
сигналы ['сигнал'] [short_window:] = np.where (сигналы ['short_mavg'] [short_window:]> сигналы ['long_mavg'] [short_window:], 1.0, 0.0)

# Генерация торговых приказов
сигналы ['позиции'] = сигналы ['сигнал']. diff ()

# Вывести `сигналы`
печать (сигналы)
  

При объектно-ориентированном подходе вам нужно всего один раз написать код инициализации и генерации сигнала.Затем вы можете создать новый объект для каждой акции, для которой хотите рассчитать стратегию, и вызвать для него метод generate_signals () . Обратите внимание, что код ООП очень похож на код выше, с добавлением self .

  класс MovingAverage ():

    def __init __ (self, symbol, bars, short_window, long_window):
        self.symbol = символ
        self.bars = бары
        self.short_window = короткое_окно
        self.long_window = длинное_окно

    def generate_signals (сам):
        сигналы = pd.DataFrame (index = self.bars.index)
        сигналы ['signal'] = 0,0

        сигналы ['short_mavg'] = бары ['Close']. Rolling (window = self.short_window, min_periods = 1, center = False) .mean ()
        сигналы ['long_mavg'] = бары ['Close']. Rolling (window = self.long_window, min_periods = 1, center = False) .mean ()

        сигналы ['сигнал'] [self.short_window:] = np.where (сигналы ['short_mavg'] [self.short_window:]> сигналы ['long_mavg'] [self.short_window:], 1.0, 0.0)

        сигналы ['позиции'] = сигналы ['сигнал'].diff ()

        ответные сигналы
  

Теперь вы можете просто создать экземпляр объекта с нужными параметрами и сгенерировать для него сигналы.

  яблоко = MovingAverage ('aapl', aapl, 40, 100)
печать (apple.generate_signals ())
  

Сделать это для другой акции становится очень просто. Это просто вопрос создания экземпляра нового объекта с другим символом акций.

  microsoft = MovingAverage ('msft', msft, 40, 100)
печать (microsoft.generate_signals ())
  

Поздравляем!

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

С ООП ваш код будет усложняться по мере увеличения вашей программы.У вас будут разные классы, подклассы, объекты, наследование, методы экземпляра и многое другое. Вы захотите, чтобы ваш код был правильно структурирован и читабельным. Для этого рекомендуется следовать шаблонам проектирования. Это принципы дизайна, которые представляют собой набор рекомендаций, позволяющих избежать плохого дизайна. Каждый из них представляет конкретную проблему, которая часто повторяется в ООП, и описывает решение этой проблемы, которое затем можно использовать повторно. Эти шаблоны проектирования ООП можно разделить на несколько категорий: шаблоны создания, структурные шаблоны и поведенческие шаблоны.Примером шаблона создания является синглтон, который следует использовать, если вы хотите убедиться, что может быть создан только один экземпляр класса. Итератор, который используется для перебора всех объектов в коллекции, является примером поведенческого шаблона. Отличный ресурс для шаблонов проектирования — oodesign.com. Если вам больше нравятся книги, я бы порекомендовал вам прочитать Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения.

OOP Python Tutorial: объектно-ориентированное программирование

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

Общее введение

Хотя Python является объектно-ориентированным языком без суеты и придирок, мы до сих пор намеренно избегали рассмотрения объектно-ориентированного программирования (ООП) в предыдущих главах нашего руководства по Python.Мы пропустили ООП, потому что убеждены, что легче и увлекательнее начать изучать Python, не зная всех деталей объектно-ориентированного программирования.

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

Хотя многие компьютерные ученые и программисты считают ООП современной парадигмой программирования, ее корни уходят в 1960-е годы. Первым языком программирования, использующим объекты, был Simula 67. Как следует из названия, Simula 67 была представлена ​​в 1967 году. Важным прорывом в объектно-ориентированном программировании стал язык программирования Smalltalk в 1970-х.

Вы узнаете четыре основных принципа объектной ориентации и то, как Python работает с ними, в следующем разделе этого руководства по объектно-ориентированному программированию:

  • Инкапсуляция
  • Абстракция данных
  • Полиморфизм
  • Наследование

Прежде чем мы начнем раздел о том, как ООП используется в Python, мы хотим дать вам общее представление об объектно-ориентированном программировании. Для этого хотим обратить ваше внимание на публичную библиотеку.Давайте подумаем о таком огромном, как «Британская библиотека» в Лондоне или «Нью-Йоркская публичная библиотека» в Нью-Йорке. Если это поможет, вы можете представить себе библиотеки в Париже, Берлине, Оттаве или Торонто *. Каждый из них содержит организованную коллекцию книг, периодических изданий, газет, аудиокниг, фильмов и так далее.

Как правило, существует два противоположных способа хранения материала в библиотеке. Вы можете использовать метод «закрытого доступа», когда товар не отображается на открытых полках. В этой системе обученный персонал доставляет книги и другие публикации пользователям по запросу.Другой способ работы библиотеки — полки с открытым доступом, также известные как «открытые полки». «Открытый» означает открытый для всех пользователей библиотеки, а не только специально обученный персонал. В этом случае книги выставляются открыто. Императивные языки, такие как C, можно рассматривать как полочные библиотеки с открытым доступом. Пользователь может все. Пользователь должен найти книги и положить их обратно на нужную полку. Несмотря на то, что это хорошо для пользователя, в долгосрочной перспективе это может привести к серьезным проблемам. Например, некоторые книги будут потеряны, поэтому их будет сложно найти снова.Как вы уже догадались, «закрытый доступ» можно сравнить с объектно-ориентированным программированием. Аналогию можно увидеть так: книги и другие публикации, которые предлагает библиотека, подобны данным в объектно-ориентированной программе. Доступ к книгам ограничен, как и доступ к данным в ООП. Получить или вернуть книгу можно только через сотрудников. Штатные функции аналогичны методам в ООП, которые контролируют доступ к данным. Таким образом, данные, часто называемые атрибутами, в такой программе можно рассматривать как скрытые и защищенные оболочкой, и к ним могут получить доступ только специальные функции, обычно называемые методами в контексте ООП.Помещение данных в «оболочку» называется инкапсуляция .
Таким образом, библиотеку можно рассматривать как класс, а книгу — как экземпляр или объект этого класса. Вообще говоря, объект определяется классом. Класс — это формальное описание того, как спроектирован объект, то есть какие атрибуты и методы он имеет. Эти объекты также называются экземплярами. Выражения в большинстве случаев используются как синонимы. Не следует путать класс с объектом.

ООП на Python

Хотя мы не говорили о классах и объектной ориентации в предыдущих главах, мы работали с классами все время.Фактически, в Python все является классом. Гвидо ван Россум разработал язык по принципу «все первоклассно». Он писал: «Одна из моих целей для Python состояла в том, чтобы сделать так, чтобы все объекты были« первоклассными ». Этим я имел в виду, что мне нужны все объекты, которые могут быть названы на языке (например, целые числа, строки, функции, классы, модули, методы и т. д.), чтобы иметь одинаковый статус, то есть они могут быть присвоены переменным, помещены в списки, сохранены в словарях, переданы как аргументы и т. д.»(Блог, История Python, 27 февраля 2009 г.) Другими словами,» все «обрабатывается одинаково, все является классом: функции и методы являются значениями, такими же, как списки, целые числа или числа с плавающей запятой. Каждый из них является экземпляром их соответствующих классов.

Python OOP — Основное руководство по объектно-ориентированному программированию Python

Это объектно-ориентированное программирование Python ясно объясняет вам объектно-ориентированное программирование Python, чтобы вы могли применять его для более эффективной разработки программного обеспечения.

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

Что вы узнаете

  • Создавайте объекты в Python, определяя классы и методы.
  • Расширить классы с помощью наследования.
  • Поймите, когда использовать объектно-ориентированные функции и, что более важно, когда их не использовать.

Для кого предназначен этот учебник

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

Раздел 1. Классы и объекты

  • Классы и объекты — узнайте, как определять класс и создавать новые объекты из класса.
  • Метод __init __ () — покажет, как определить конструктор для класса с помощью метода __init __ ().
  • Атрибуты экземпляра и класса — поймите атрибуты экземпляра и атрибуты класса и, что более важно, когда вам следует использовать атрибуты класса.
  • Частные атрибуты — узнайте о частных атрибутах и ​​о том, как их эффективно использовать.
  • Свойства — покажите, как использовать декоратор @property для определения свойств класса.
  • Статические методы — объяснят вам статические методы и покажут, как их использовать для группировки связанных функций в классе.

Раздел 2. Строковое представление объектов

  • Метод __str__ — покажет, как использовать метод __str__ dunder для возврата строкового представления объекта.
  • Метод __repr__ — узнайте, как использовать метод __repr__ и основные различия между методами __str__ и __repr__.

Раздел 3. Сравнение объектов

  • Метод __eq__ — узнайте, как определить логику равенства для сравнения объектов по значениям.

Раздел 4. Наследование

  • Наследование — объясните вам концепцию наследования и способы определения класса, который наследуется от другого класса.
  • Абстрактные классы — покажите, как определять абстрактные классы и как использовать их для создания схем элементов для других классов.

Вы нашли это руководство полезным?

Python OOPs Concepts — GeeksforGeeks

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

Основные концепции объектно-ориентированного программирования (ООП)

  • Класс
  • Объекты
  • Полиморфизм
  • Инкапсуляция
  • Наследование

Класс

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

Чтобы понять необходимость создания класса, давайте рассмотрим пример, допустим, вы хотите отслеживать количество собак, которые могут иметь разные атрибуты, такие как порода, возраст. Если используется список, первым элементом может быть порода собаки, а вторым элементом — ее возраст. Предположим, есть 100 разных собак, тогда как вы узнаете, какой элемент должен быть каким? Что, если бы вы захотели добавить этим собакам другие свойства? Здесь не хватает организации, и это как раз необходимость занятий.

Некоторые точки класса Python:

  • Классы создаются с помощью ключевого слова class.
  • Атрибуты — это переменные, принадлежащие классу.
  • Атрибуты всегда общедоступны, и к ним можно получить доступ с помощью оператора точка (.). Например: Myclass.Myattribute

Синтаксис определения класса:

 class ClassName:
   # Заявление-1
   .
   .
   .
   # Statement-N 

Пример: создание пустого класса в Python

Python

class Dog:

pass

В приведенном выше Например, мы создали класс с именем dog, используя ключевое слово class.

Объекты

Объект — это сущность, с которой связаны состояние и поведение. Это может быть любой объект реального мира, такой как мышь, клавиатура, стул, стол, ручка и т. Д. Целые числа, строки, числа с плавающей запятой, даже массивы и словари — все это объекты. Более конкретно, любое целое число или любая отдельная строка является объектом. Число 12 — это объект, строка «Hello, world» — это объект, список — это объект, который может содержать другие объекты, и так далее. Вы все время использовали предметы и, возможно, даже не осознавали этого.

Объект состоит из:

  • Состояние: Он представлен атрибутами объекта. Он также отражает свойства объекта.
  • Поведение: Представлено методами объекта. Он также отражает реакцию объекта на другие объекты.
  • Идентификатор: Он дает уникальное имя объекту и позволяет одному объекту взаимодействовать с другими объектами.

Чтобы понять состояние, поведение и идентичность, давайте возьмем пример с классной собакой (объясненной выше).

  • Личность можно рассматривать как кличку собаки.
  • Состояние или атрибуты могут рассматриваться как порода, возраст или окрас собаки.
  • Можно определить поведение собаки в зависимости от того, ест она или спит.

Пример: Создание объекта

Будет создан объект с именем obj класса Dog, определенного выше. Прежде чем углубляться в объекты и классы, давайте разберемся с некоторыми основными ключевыми словами, которые мы будем использовать при работе с объектами и классами.

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

  1. должны иметь дополнительный первый параметр в определении метода. Мы не указываем значение для этого параметра при вызове метода, Python предоставляет его
  2. Если у нас есть метод, который не принимает аргументов, то у нас все равно должен быть один аргумент.
  3. Это похоже на этот указатель в C ++ и эту ссылку в Java.

Когда мы вызываем метод этого объекта как myobject.method (arg1, arg2), он автоматически преобразуется Python в MyClass.метод (myobject, arg1, arg2) — это все, о чем идет речь в специальном self.

Примечание: Для получения дополнительной информации обратитесь к self в классе Python

Метод __init__

Метод __init__ аналогичен конструкторам в C ++ и Java. Он запускается, как только создается экземпляр объекта класса. Этот метод полезен для любой инициализации, которую вы хотите выполнить с вашим объектом.

Теперь давайте определим класс и создадим несколько объектов, используя методы self и __init__.

Пример 1: Создание класса и объекта с атрибутами класса и экземпляра

Python3

class Dog:

attr1 = "млекопитающее"

def __init __ ( self , имя):

self .имя = имя

Роджер = Собака ( «Роджер» )

Томми = Собака ( «Томми» )

печать ( "Роджер - это {}" . формат (Роджер .__ класс __. Attr1))

печать ( "Томми также является {} " . формат (Tommy .__ class __. Attr1))

печать ( "Меня зовут {}" . формат (Rodger.name))

печать ( "Меня зовут {}" . формат (Tommy.name))

Вывод

 Роджер - млекопитающее
Томми тоже млекопитающее
Меня зовут роджер
Меня зовут томми
 

Пример 2: Создание класса и объектов с помощью методов

Python3

класс Dog:

attr1 = "млекопитающее"

def __init __ ( self , name):

self .имя = имя

def говорить ( self ):

печать ( "Меня зовут {}" . формат ( self .name))

Rodger = Dog ( "Rodger" )

Tommy = Собака ( "Томми" )

Роджер.Speak ()

Tommy.speak ()

Выход

 Меня зовут Роджер
Меня зовут томми
 

Примечание. Для получения дополнительной информации см. Классы и объекты Python

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

Наследование — это способность одного класса наследовать свойства другого класса. Класс, который наследует свойства, называется производным классом или базовым классом, а класс, от которого наследуются свойства, называется базовым классом или родительским классом.Преимущества наследования:

  • Оно хорошо отражает реальные отношения.
  • Обеспечивает возможность повторного использования кода. Нам не нужно писать один и тот же код снова и снова. Кроме того, это позволяет нам добавлять в класс дополнительные функции, не изменяя его.
  • Он носит транзитивный характер, что означает, что если класс B наследуется от другого класса A, тогда все подклассы B будут автоматически наследоваться от класса A.

Пример: наследование в Python

Python3

класс Лицо ( объект ):

def __init __ ( self , имя, идентификационный номер) 9: 8 9000 собственное .имя = имя

self .idnumber = idnumber

def дисплей ( self ):

печать ( self .name)

печать ( self .idnumber)

def детали ( self ):

print ( "Меня зовут {}" . формат ( self .name))

print ( "IdNumber: {}" . формат ( self .idnumber))

class Сотрудник (человек):

def __init __ ( self , имя, idnumber, зарплата, должность):

self . Зарплата = зарплата

self .post = post

Person.__init __ ( self , имя, idnumber)

def детали ( self ):

print ( "Меня зовут {} " . формат ( self .name))

печать ( " IdNumber: {} " . формат ( self .idnumber))

print ( "Post: {}" . формат ( self .post) )

a = Сотрудник ( «Рахул» , 886012 , 200000 , «Внутренний» )

а.дисплей ()

a.details ()

Выход

 Rahul
886012
Меня зовут рахул
IdNumber: 886012
Сообщение: Intern 

В приведенной выше статье мы создали два класса: Person (родительский класс) и Employee (дочерний класс). Класс Employee наследуется от класса Person. Мы можем использовать методы класса людей через класс сотрудников, как показано в функции отображения в приведенном выше коде. Дочерний класс также может изменять поведение родительского класса, как видно из метода details ().

Примечание: Для получения дополнительной информации см. Наше руководство по наследованию в Python.

Полиморфизм

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

Пример: полиморфизм в Python

Python3

класс Bird:

def intro (

0 self

7): печать ( "Есть много видов птиц." )

def полет ( self ):

print ( « Большинство птиц могут летать, но некоторые не могут ». )

класс воробей (Bird):

def полет ( self ):

печать ( «Воробьи умеют летать." )

класс страус (птица):

def полет ( self ):

печать

печать ( «Страусы не умеют летать». )

obj_bird = Bird ()

obj_spr = sparrow

ob_ost = страус ()

obj_bird.intro ()

obj_bird.flight ()

obj_spr.intro ()

obj_spr.flight ()

82 obj obj_ost.flight ()

Выход

 Есть много видов птиц.
Большинство птиц умеют летать, но некоторые - нет.
Есть много видов птиц.
Воробьи умеют летать.
Есть много видов птиц.Страусы не умеют летать.
 

Примечание: Дополнительные сведения см. В нашем учебнике «Полиморфизм в Python».

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

Инкапсуляция - одна из фундаментальных концепций объектно-ориентированного программирования (ООП). В нем описывается идея обертывания данных и методы, которые работают с данными в одном блоке. Это накладывает ограничения на прямой доступ к переменным и методам и может предотвратить случайное изменение данных. Чтобы предотвратить случайное изменение, переменную объекта можно изменить только с помощью метода объекта.Эти типы переменных известны как частные переменные.

Класс является примером инкапсуляции, поскольку он инкапсулирует все данные, которые являются функциями-членами, переменными и т. Д.

Пример: инкапсуляция в Python

Python3

50

0

В приведенном выше примере мы создали переменную c как частный атрибут.Мы даже не можем напрямую получить доступ к этому атрибуту и ​​даже не можем изменить его значение.

Примечание: для получения дополнительной информации см. Наше руководство по инкапсуляции в Python.

Объектно-ориентированное программирование на Python | Набор 2 (Скрытие данных и печать объектов)

https://youtu.be/CiH7lN4

Автор статьи Shwetanshu Rohatgi .

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

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

класс База:

def __init __ ( self ):

self .a = "GeeksforGeeks"

self .__ c = "GeeksforGeeks"

класс

0 Получено (базовый):

def __init __ ( self ):

Base.__init __ ( self )

print ( «Вызов частного члена базового класса:» )

print ( self .__ c)

obj1 = Base ()

print (obj1.a)