ООП на Python

ООП на 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-тестов. Курс уже стартовал, но вы можете присоединиться к нему до конца недели!



Report Page