Файл: Объектноориентированное программирование на Python.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 10.04.2024
Просмотров: 33
Скачиваний: 0
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Объектно-ориентированное программирование на Python
Введение
Объектно-ориентированное программирование (ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов.
Класс — тип, описывающий устройство объектов.
Объект — это экземпляр класса.
Класс можно сравнить с чертежом, по которому создаются объекты.
Объектно-ориентированная парадигма имеет несколько принципов:
-
Данные структурируются в виде объектов, каждый из которых имеет определенный тип, то есть принадлежит к какому-либо классу. -
Классы – результат формализации решаемой задачи, выделения главных ее аспектов. -
Внутри объекта инкапсулируется логика работы с относящейся к нему информацией. -
Объекты в программе взаимодействуют друг с другом, обмениваются запросами и ответами. -
При этом объекты одного типа сходным образом отвечают на одни и те же запросы. -
Объекты могут организовываться в более сложные структуры, например, включать другие объекты или наследоваться от одного или нескольких объектов.
Python соответствует принципам объектно-ориентированного программирования. В python ВСЁ является объектами - и строки, и списки, и словари, и даже функции.
Программист может написать свой пользовательский тип данных (класс), определить в нём свои поля и методы. Это не является обязательным - мы можем пользоваться только встроенными объектами, однако это полезно при долгосрочной разработке программы несколькими людьми, так как это упрощает понимание кода.
Основы ООП
Класс (class) - элемент программы, который описывает какой-то тип данных. Класс описывает шаблон для создания объектов, как правило, указывает переменные этого объекта и действия, которые можно выполнять применимо к объекту.
Экземпляр класса (instance) - объект, который является представителем класса.
Метод (method) - функция, которая определена внутри класса и описывает какое-то действие, которое поддерживает класс
Переменная экземпляра (instance variable, а иногда и instance attribute) - данные, которые относятся к объекту
Переменная класса (class variable) - данные, которые относятся к классу и разделяются всеми экземплярами класса
Атрибут экземпляра (instance attribute) - переменные и методы, которые относятся к объектам (экземплярам) созданным на основании класса. У каждого объекта есть своя копия атрибутов.
Пример из реальной жизни в стиле ООП:
-
Проект дома - это класс -
Конкретный дом, который был построен по проекту - экземпляр класса -
Такие особенности как цвет дома, количество окон - переменные экземпляра, то есть конкретного дома -
Дом можно продать, покрасить, отремонтировать - это методы
Основы ООП в Python
Классы
Примечание: Имена классов: в Python принято писать имена классов в формате CamelCase.
Создадим свой пустой класс (объявление класса):
class Person: def sayHi(self): print('Привет! Как дела?') p = Person() p.sayHi() |
Вывод:
python simplestclass.py
<__main__.Person object at 0x019F85F0>
Как это работает:
Мы создаём новый класс при помощи оператора class и имени класса. За этим следует блок выражений, формирующих тело класса. В данном случае блок у нас пуст, на что указывает оператор pass.
Далее мы создаём объект-экземпляр класса, записывая имя класса со скобками. (Мы узнаем больше о реализации в следующем разделе). Для проверки мы выясняем тип переменной, просто выводя её на экран. Так мы видим, что у нас есть экземпляр класса Person в модуле __main__.
Обратите внимание, что выводится также и адрес в памяти компьютера, где хранится ваш объект. На вашем компьютере адрес будет другим, так как Python хранит объекты там, где имеется свободное место.
Классы можно наследовать от других классов. Классы-родители (супер-классы) перечисляются в скобках через запятую (реализацию наследования подробнее рассмотрим ниже):
class SomeClass(ParentClass1, ParentClass2, ...): # поля и методы класса SomeClass |
Свойства классов устанавливаются с помощью простого присваивания:
class SomeClass(): attr1 = 42 attr2 = "Hello, World" |
Методы объявляются как простые функции внутри класса:
class SomeClass(): def method1(self, x): # код метода |
Обратите внимание на первый аргумент – 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:
class SomeClass(object): attr1 = 42 def method1(self, x): return 2*x obj1 = SomeClass() obj1.method1(6) # 12 obj1.attr1 # 42 obj2 = SomeClass() obj2.method1(8) # 16 obj2.attr1 # 42 |
Пример 2:
class Person: name = "Tom" def display_info(self): print("Привет, меня зовут", self.name) person1 = Person() person1.display_info() # Привет, меня зовут Tom person2 = Person() person2.name = "Sam" person2.display_info() # Привет, меня зовут Sam |
Класс Person определяет атрибут name, который хранит имя человека, и метод display_info, с помощью которого выводится информация о человеке.
После определения класс Person создаем пару его объектов - person1 и person2. Используя имя объекта, мы можем обратиться к его методам и атрибутам. В данном случае у каждого из объектов вызываем метод display_info(), который выводит строку на консоль, и у второго объекта также изменяем атрибут name. При этом при вызове метода display_info не надо передавать значение для параметра self.
Конструктор (__init__)
В ООП конструктором класса называют метод, который автоматически вызывается при создании объектов. Его также можно назвать конструктором объектов класса. Имя такого метода обычно регламентируется синтаксисом конкретного языка программирования. Так в Java имя конструктора класса совпадает с именем самого класса. В Python же роль конструктора играет метод __init__().
В Python наличие пар знаков подчеркивания спереди и сзади в имени метода говорит о том, что он принадлежит к группе методов перегрузки операторов (или магическим методам, это официальное название). Если подобные методы определены в классе, то объекты могут участвовать в таких операциях как сложение, вычитание, вызываться как функции и др.
При этом методы перегрузки операторов не надо вызывать по имени. Вызовом для них является сам факт участия объекта в определенной операции. В случае конструктора класса – это операция создания объекта. Так как объект создается в момент вызова класса по имени, то в этот момент вызывается метод __init__(), если он определен в классе.
Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. Пусть имеется класс Person, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан подобным образом.
Для примера возьмем класс Point (точка 3d пространства), объекты которого должны иметь определенные координаты:
class Point(object): def __init__(self, x, y, z): self.coord = (x, y, z) p1 = Point(13, 14, 15) p2 = Point(23, 24, 25) p1.coord # (13, 14, 15) p2.coord # (23, 24, 25) |
Рассмотрим еще один пример, создадим класс Person:
class Person: def __init__(self, n, s): self.name = n self.surname = s p1 = Person("Sam", "Baker") print(p1.name, p1.surname) |
Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__().
Однако бывает, что надо допустить создание объекта, даже если никакие данные в конструктор не передаются. В таком случае параметрам конструктора класса задаются значения по умолчанию:
class Rectangle: def __init__(self, w = 0.5, h = 1): self.width = w self.height = h def square(self): return self.width * self.height rec1 = Rectangle(5, 2) rec2 = Rectangle() rec3 = Rectangle(3) rec4 = Rectangle(h = 4) print(rec1.square()) print(rec2.square()) print(rec3.square()) print(rec4.square()) #Вывод 10 0.5 3 2.0 |
Деструктор (__del__)
Если конструктор вызывается при создании объекта, то перед уничтожением объекта автоматически вызывается метод, называемый деструктором т.е. "уничтожитель". В языке программирования Python деструктор реализуется в виде предопределенного метода __del__(). Следует заметить, что метод не будет вызван, если на экземпляр класса существует хотя бы одна ссылка. Кроме того, т.к. интерпретатор самостоятельно заботится об удалении объектов (инструмент garbage collector), использование деструктора в языке программирования Python не имеет особого смысла.
class Class1: def __init__(self): # Конструктор класса print("Вызван метод __init__()") def __del__(self): # Деструктор класса print("Вызван метод __del__()") c1 = Class1() # Выведет: Вызван метод __init__() del c1 # Выведет: Вызван метод __del__() c2 = Class1() # Выведет: Вызван метод __init__() c3 = c2 # Создаем ссылку на экземпляр класса del c2 # Ничего не выведет, т.к. существует ссылка del c3 # Выведет: Вызван метод __del__() |
Практическая работа. Конструктор и деструктор
Напишите программу по следующему описанию:
-
Есть класс 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 не используется, т.к. обращение к полям и методам происходит на уровне всего класса, а не отдельных объектов.. Отличие атрибутов и методов класса от атрибутов и методов объектов будет рассмотрено ниже.