Python Основы OOP 1. Объектноориентированное программирование на Python
Скачать 300.03 Kb.
|
Объектно-ориентированное программирование на Python ВведениеОбъектно-ориентированное программирование (ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов. Класс — тип, описывающий устройство объектов. Объект — это экземпляр класса. Класс можно сравнить с чертежом, по которому создаются объекты. Объектно-ориентированная парадигма имеет несколько принципов: Данные структурируются в виде объектов, каждый из которых имеет определенный тип, то есть принадлежит к какому-либо классу. Классы – результат формализации решаемой задачи, выделения главных ее аспектов. Внутри объекта инкапсулируется логика работы с относящейся к нему информацией. Объекты в программе взаимодействуют друг с другом, обмениваются запросами и ответами. При этом объекты одного типа сходным образом отвечают на одни и те же запросы. Объекты могут организовываться в более сложные структуры, например, включать другие объекты или наследоваться от одного или нескольких объектов. Python соответствует принципам объектно-ориентированного программирования. В python ВСЁ является объектами - и строки, и списки, и словари, и даже функции. Программист может написать свой пользовательский тип данных (класс), определить в нём свои поля и методы. Это не является обязательным - мы можем пользоваться только встроенными объектами, однако это полезно при долгосрочной разработке программы несколькими людьми, так как это упрощает понимание кода. Основы ООПКласс (class) - элемент программы, который описывает какой-то тип данных. Класс описывает шаблон для создания объектов, как правило, указывает переменные этого объекта и действия, которые можно выполнять применимо к объекту. Экземпляр класса (instance) - объект, который является представителем класса. Метод (method) - функция, которая определена внутри класса и описывает какое-то действие, которое поддерживает класс Переменная экземпляра (instance variable, а иногда и instance attribute) - данные, которые относятся к объекту Переменная класса (class variable) - данные, которые относятся к классу и разделяются всеми экземплярами класса Атрибут экземпляра (instance attribute) - переменные и методы, которые относятся к объектам (экземплярам) созданным на основании класса. У каждого объекта есть своя копия атрибутов. Пример из реальной жизни в стиле ООП: Проект дома - это класс Конкретный дом, который был построен по проекту - экземпляр класса Такие особенности как цвет дома, количество окон - переменные экземпляра, то есть конкретного дома Дом можно продать, покрасить, отремонтировать - это методы Основы ООП в PythonКлассыПримечание: Имена классов: в Python принято писать имена классов в формате CamelCase. Создадим свой пустой класс (объявление класса):
Вывод: python simplestclass.py <__main__.Person object at 0x019F85F0> Как это работает: Мы создаём новый класс при помощи оператора class и имени класса. За этим следует блок выражений, формирующих тело класса. В данном случае блок у нас пуст, на что указывает оператор pass. Далее мы создаём объект-экземпляр класса, записывая имя класса со скобками. (Мы узнаем больше о реализации в следующем разделе). Для проверки мы выясняем тип переменной, просто выводя её на экран. Так мы видим, что у нас есть экземпляр класса Person в модуле __main__. Обратите внимание, что выводится также и адрес в памяти компьютера, где хранится ваш объект. На вашем компьютере адрес будет другим, так как Python хранит объекты там, где имеется свободное место. Классы можно наследовать от других классов. Классы-родители (супер-классы) перечисляются в скобках через запятую (реализацию наследования подробнее рассмотрим ниже):
Свойства классов устанавливаются с помощью простого присваивания:
Методы объявляются как простые функции внутри класса:
Обратите внимание на первый аргумент – self – общепринятое имя для ссылки на объект, в контексте которого вызывается метод. self - обязательный аргумент, содержащий в себе экземпляр класса, передающийся при вызове метода поэтому этот аргумент должен присутствовать во всех методах класса. selfМетоды класса имеют одно отличие от обычных функций: они должны иметь дополнительно имя, добавляемое к началу списка параметров. Однако, при вызове метода никакого значения этому параметру присваивать не нужно – его укажет Python. Эта переменная указывает на сам объект экземпляра класса, и по традиции она называется self. Хотя этому параметру можно дать любое имя, настоятельно рекомендуется использовать только имя self; использование любого другого имени не приветствуется. Есть много достоинств использования стандартного имени: во-первых, любой человек, просматривающий вашу программу, легко узнает его; во-вторых, некоторые специализированные Интегрированные среды разработки (IDE) изначально рассчитаны на использование self. Примечание: Замечание для программистов на C++, Java и C# self в Python эквивалентно указателю this в C++ и ссылке this в Java и C#. Поясним работу self на примере: Предположим, у нас есть класс с именем MyClass и экземпляр этого класса с именем myobject. При вызове метода этого объекта, например, myobject.method(arg1, arg2), Python автоматически превращает это MyClass.method(myobject, arg1, arg2) – в этом и состоит смысл self. Это также означает, что если какой-либо метод не принимает аргументов, у него всё равно будет один аргумент – self. Дополнительный материал по self: https://pythonz.net/references/named/self/ Объекты (экземпляры классов)Создадим несколько экземпляров класса, который мы объявили выше: Пример 1:
Пример 2:
Класс Person определяет атрибут name, который хранит имя человека, и метод display_info, с помощью которого выводится информация о человеке. После определения класс Person создаем пару его объектов - person1 и person2. Используя имя объекта, мы можем обратиться к его методам и атрибутам. В данном случае у каждого из объектов вызываем метод display_info(), который выводит строку на консоль, и у второго объекта также изменяем атрибут name. При этом при вызове метода display_info не надо передавать значение для параметра self. Конструктор (__init__)В ООП конструктором класса называют метод, который автоматически вызывается при создании объектов. Его также можно назвать конструктором объектов класса. Имя такого метода обычно регламентируется синтаксисом конкретного языка программирования. Так в Java имя конструктора класса совпадает с именем самого класса. В Python же роль конструктора играет метод __init__(). В Python наличие пар знаков подчеркивания спереди и сзади в имени метода говорит о том, что он принадлежит к группе методов перегрузки операторов (или магическим методам, это официальное название). Если подобные методы определены в классе, то объекты могут участвовать в таких операциях как сложение, вычитание, вызываться как функции и др. При этом методы перегрузки операторов не надо вызывать по имени. Вызовом для них является сам факт участия объекта в определенной операции. В случае конструктора класса – это операция создания объекта. Так как объект создается в момент вызова класса по имени, то в этот момент вызывается метод __init__(), если он определен в классе. Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. Пусть имеется класс Person, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан подобным образом. Для примера возьмем класс Point (точка 3d пространства), объекты которого должны иметь определенные координаты:
Рассмотрим еще один пример, создадим класс Person:
Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__(). Однако бывает, что надо допустить создание объекта, даже если никакие данные в конструктор не передаются. В таком случае параметрам конструктора класса задаются значения по умолчанию:
Деструктор (__del__)Если конструктор вызывается при создании объекта, то перед уничтожением объекта автоматически вызывается метод, называемый деструктором т.е. "уничтожитель". В языке программирования Python деструктор реализуется в виде предопределенного метода __del__(). Следует заметить, что метод не будет вызван, если на экземпляр класса существует хотя бы одна ссылка. Кроме того, т.к. интерпретатор самостоятельно заботится об удалении объектов (инструмент garbage collector), использование деструктора в языке программирования Python не имеет особого смысла.
Практическая работа. Конструктор и деструкторНапишите программу по следующему описанию: Есть класс Person, конструктор которого принимает три параметра (не учитывая self) – имя, фамилию и квалификацию специалиста. Квалификация имеет значение заданное по умолчанию, равное единице. У класса Person есть метод, который возвращает строку, включающую в себя всю информацию о сотруднике. Класс Person содержит деструктор, который выводит на экран фразу "До свидания, мистер …" (вместо троеточия должны выводиться имя и фамилия объекта). В основной ветке программы создайте три объекта класса Person. Посмотрите информацию о сотрудниках и увольте самое слабое звено. В конце программы добавьте функцию input(), чтобы скрипт не завершился сам, пока не будет нажат Enter. Иначе вы сразу увидите как удаляются все объекты при завершении работы программы. Параметры и методы классовС точки зрения пространства имен класс можно представить подобным модулю. Также как в модуле в классе могут быть свои переменные со значениями и функции. Также как в модуле у класса есть собственное пространство имен, доступ к которому возможен через имя класса: class B: n = 5 def adder(v): return v + B.n >>> B.n 5 >>> B.adder(4) 9 Примечание: В данном примере поле n и метод adder являются полем и методом класса и ключевое слово self не используется, т.к. обращение к полям и методам происходит на уровне всего класса, а не отдельных объектов.. Отличие атрибутов и методов класса от атрибутов и методов объектов будет рассмотрено ниже. В случае классов используется особая терминология. Пусть имена, определенные в классе, называются атрибутами этого класса. В примере имена n и adder – это атрибуты класса B. Атрибуты-переменные часто называют полями или свойствами (в других языках понятия "поле" и "свойство" не совсем одно и то же). Полем является n. Атрибуты-функции называются методами. Методом в классе B является adder. Количество свойств и методов в классе может быть любым. Переменные класса и объектаДанные, т.е. поля, являются не чем иным, как обычными переменными, заключёнными в пространствах имён классов и объектов. Это означает, что их имена действительны только в контексте этих классов или объектов. Отсюда и название “пространство имён”. Существует два типа полей: переменные класса (рассмотрели выше) и переменные объекта, которые различаются в зависимости от того, принадлежит ли переменная классу или объекту соответственно. Переменные класса разделяемы – доступ к ним могут получать все экземпляры этого класса. Переменная класса существует только одна, поэтому когда любой из объектов изменяет переменную класса, это изменение отразится и во всех остальных экземплярах того же класса. Переменные объекта принадлежат каждому отдельному экземпляру класса. В этом случае у каждого объекта есть своя собственная копия поля, т.е. не разделяемая и никоим образом не связанная с другими такими же полями в других экземплярах. Это легко понять на примере (сохраните как objvar.py):
Вывод: $ python3 objvar.py (Инициализация R2-D2) Приветствую! Мои хозяева называют меня R2-D2. У нас 1 роботов. (Инициализация C-3PO) Приветствую! Мои хозяева называют меня C-3PO. У нас 2 роботов. Здесь роботы могут проделать какую-то работу. Роботы закончили свою работу. Давайте уничтожим их. R2-D2 уничтожается! Осталось 1 работающих роботов. C-3PO уничтожается! C-3PO был последним. У нас 0 роботов. Как это работает: Это длинный пример, но он помогает продемонстрировать природу переменных класса и объекта. Здесь population принадлежит классу Robot, и поэтому является переменной класса. Переменная name принадлежит объекту (ей присваивается значение при помощи self), и поэтому является переменной объекта. Таким образом, мы обращаемся к переменной класса population как Robot.population, а не self.population. К переменной же объекта name во всех методах этого объекта мы обращаемся при помощи обозначения self.name. Помните об этой простой разнице между переменными класса и объекта. Также имейте в виду, что переменная объекта с тем же именем, что и переменная класса, сделает недоступной (“спрячет”) переменную класса! Метод howMany принадлежит классу, а не объекту. Примечание: В этом примере мы также наблюдали применение строк документации для классов, равно как и для методов. Во время выполнения мы можем обращаться к строке документации класса при помощи Robot.__doc__, а к строке документации метода – при помощи Robot.sayHi.__doc__. Динамическое изменение (не рекомендуется использовать)Классы в Python могут динамически изменяться после определения:
* python позволяет добавлять новые атрибуты в любой экземпляр класса в любом месте программы, но так делать не рекомендуется, т.к. это может привести к неправильной работе экземпляра. Примечание: При вызове метода экземпляра класса, ссылка на экземпляр передается первым аргументом. При этом, экземпляр передается неявно, но параметр надо указывать явно. Практическая работа “Игра воин”:Напишите программу по следующему описанию. Есть класс "Воин". От него создаются два экземпляра-юнита. Каждому устанавливается здоровье в 100 очков. В случайном порядке они бьют друг друга. Тот, кто бьет, здоровья не теряет. У того, кого бьют, оно уменьшается на 20 очков от одного удара. После каждого удара надо выводить сообщение, какой юнит атаковал, и сколько у противника осталось здоровья. Как только у кого-то заканчивается ресурс здоровья, программа завершается сообщением о том, кто одержал победу. |