Файл: Объектноориентированное программирование на Python.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 10.04.2024

Просмотров: 36

Скачиваний: 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__()



Практическая работа. Конструктор и деструктор


Напишите программу по следующему описанию:

  1. Есть класс Person, конструктор которого принимает три параметра (не учитывая self) – имя, фамилию и квалификацию специалиста. Квалификация имеет значение заданное по умолчанию, равное единице.

  2. У класса Person есть метод, который возвращает строку, включающую в себя всю информацию о сотруднике.

  3. Класс Person содержит деструктор, который выводит на экран фразу "До свидания, мистер …" (вместо троеточия должны выводиться имя и фамилия объекта).

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

  5. В конце программы добавьте функцию input(), чтобы скрипт не завершился сам, пока не будет нажат Enter. Иначе вы сразу увидите как удаляются все объекты при завершении работы программы.



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


С точки зрения пространства имен класс можно представить подобным модулю. Также как в модуле в классе могут быть свои переменные со значениями и функции. Также как в модуле у класса есть собственное пространство имен, доступ к которому возможен через имя класса:
class B:
n = 5
def adder(v):
return v + B.n

>>> B.n
5
>>> B.adder(4)
9
Примечание: В данном примере поле n и метод adder являются полем и методом класса и ключевое слово self не используется, т.к. обращение к полям и методам происходит на уровне всего класса, а не отдельных объектов.. Отличие атрибутов и методов класса от атрибутов и методов объектов будет рассмотрено ниже.