ООП на Python
karpov.coursesООП (Объектно-ориентированное программирование) — подход к разработке программного обеспечения, в котором всё строится вокруг понятия «объект».

Объект в ООП — этакий контейнер с данными и функциями, независимая и самодостаточная сущность внутри программы. Можно сказать, что большая часть кода в парадигме ООП состоит из описания объектов и их взаимодействий.
Вот несколько основополагающих понятий ООП (ниже мы раскрываем каждое из них подробно):
- Класс — шаблон, определяющий свойства и встроенные функции (методы) объектов.
- Метод класса — функция, определённая внутри класса.
- Экземпляр класса — конкретный объект, созданный на основе класса.
- Конструктор класса — метод, вызываемый при создании нового экземпляра.
- Переменная класса — переменная, общая для всех экземпляров класса.
- Переменная экземпляра класса — переменная, принадлежащая одному конкретному экземпляру.
- Наследование классов — механизм создания нового класса на основе существующего.
Класс
Класс — это определённый шаблон, заготовка, описывающая, из чего должен состоять объект (атрибуты) и что с ним можно делать (методы).
Например, так может выглядеть класс «Человек» с атрибутами «имя», «возраст» и методом «приветствие»:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"Привет, меня зовут {self.name} и мне {self.age} лет.")
Метод класса
Метод класса — это функция, определённая внутри класса. Методы используются для доступа к атрибутам объекта, для изменения его состояния и взаимодействия с другими объектами.
В разделе выше есть пример уже определения метода («приветствие» в классе «Человек»). Аналогично, скажем, для класса «Прямоугольник» можно определить методы «вычисление площади» и «вывод периметра»:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height
def print_perimeter(self):
p = 2 * (self.width + self.height)
print(f"Периметр прямоугольника P = {p}.")
О том, как вызвать метод для конкретного объекта класса — в разделе «Экземпляр класса».
Конструктор класса
Конструктор класса — специальный метод __init__, через который можно передать все необходимые характеристики для создания нового конкретного объекта по шаблону класса. Конструктор принимает параметры и задаёт начальное состояние (то есть значения атрибутов) объекта.
Так, в нашем классе «Человек» конструктор принимает обязательный параметр self (ссылка на сам экземпляр), имя и возраст, а также может выводить сообщение о создании объекта:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Создан пользователь {self.name}.")
def say_hello(self):
print(f"Привет, меня зовут {self.name} и мне {self.age} лет.")
person1 = Person("Алиса", 25)# Вывод: Создан пользователь Алиса.
person2 = Person("Вася", 40) # Вывод: Создан пользователь Вася.
Если же попытаться создать экземпляр, передав не все указанные в _init_ аргументы, возникнет ошибка:
person3 = Person("Никита") # TypeError: __init__() missing 1 required positional argument: 'age'
Экземпляр класса
Экземпляр класса — конкретный объект, созданный на основе класса с помощью конструктора. Каждый экземпляр использует определённый в классе набор атрибутов и методов, но обладает собственным состоянием.
Скажем, можно создать экземпляр класса «Человек» с именем Алиса и возрастом 25 лет и экземпляр класса «Прямоугольник» со сторонами 5 и 3:
person = Person("Алиса", 25)
rectangle = Rectangle(5, 3)
А потом вызывать их методы:
person.say_hello() # Вывод: Привет, меня зовут Алиса и мне 25 лет. rectangle.print_perimeter() # Вывод: Периметр прямоугольника P = 16.
И даже вызывать и изменять атрибуты:
print(person.age) # Вывод: 25 person.age = person.age + 1 print(person.age) # Вывод: 26
Переменная класса
Переменная класса — это атрибут, определённый внутри класса и доступный всем его экземплярам. Также переменная класса доступна через имя класса.
Например, при создании класса «Человек» мы могли бы определить переменную класса «Счётчик», чтобы считать количество созданных экземпляров:
class Person:
count = 0
def __init__(self, name):
self.name = name
Person.count += 1
@staticmethod
def get_count():
return Person.count
print(Person.get_count()) # Вывод: 0
person1 = Person("Алиса")
print(person1.get_count()) # Вывод: 1
person2 = Person("Вася")print
(person2.get_count()) # Вывод: 2
Переменная экземпляра класса
Переменная экземпляра класса — атрибут, принадлежащий одному конкретному экземпляру. Каждый экземпляр хранит собственные значения таких атрибутов.
Например, в классе «Прямоугольник», «длина» и «ширина» — уникальные для каждого экземпляра переменные:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def print_sides(self):
print(f"Это прямоугольник {self.width} на {self.height}.)
rectangle1 = Rectangle(5, 3)
rectangle2 = Rectangle(8, 2)
rectangle1.print_sides() # Вывод: Это прямоугольник 5 на 3.
rectangle2.print_sides() # Вывод: Это прямоугольник 8 на 2.
Наследование классов
Наследование классов — механизм, позволяющий создавать новые классы на основе существующих. Дочерний класс или потомок по умолчанию наследует свойства и методы родительского класса, но также может иметь свои собственные.
Возьмём, к примеру, наш класс «Прямоугольник» с атрибутами «длина», «ширина» и методами «вычисление площади», «вывод размеров»:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height
def print_sides(self):
print(f"Это прямоугольник {self.width} на {self.height}.")
Теперь можно создать от него дочерний класс «Квадрат». Метод «вычисление площади» потомок унаследует от родителя, а вот конструктор и «вывод размеров» нужно будет переопределить:
class Square(Rectangle):
def __init__(self, side):
super().__init__(side, side)
def print_sides(self):
print(f"Это квадрат со стороной {self.width}.")
square = Square(5)
print(square.calculate_area()) # Вывод: 25
square.print_sides() # Вывод: Это квадрат со стороной 5.
Почему мы можем быть уверены, что «вывод размеров» отработает согласно описанию в дочернем классе? Дело в том, что, согласно логике ООП, в первую очередь метод всегда ищется внутри самого класса и только если не находится — начинается поиск по методам родителя.
_________________________________________
Кстати, знание ООП поможет вам лучше понимать материал продвинутой версии Симулятора A/B-тестов. Курс уже стартовал, но вы можете присоединиться к нему до конца недели!