2023-06-03
584

ООП в Python

Классы, объекты, методы

  • Класс - это прототип объекта, в котором описаны все его свойства и методы;
  • Объект - это конкретный экземпляр данного класса;
  • Методы - это функции конкретного класса;
  • Конструктор - это метод (функция), вызываемая при создании объекта. Передает значения аргументов свойствам создаваемого объекта.

Описание класса

class ClassName:

Создание объекта

ObjectName = ClassName()

Описание метода

def name (self, param1, param2, param2):
К параметрах метода обязательно должен быть self, это ссылка на текущих экземпляр класса, который передается при вызове метода, то есть это ключевое слово, отсылающее на сам класс.

Описание конструктора

Метод __init__ является инициализатором класса (его конструктором), выполняется при создании объекта.
def __init__ (self, param1, param2, param2):
К параметрах метода обязательно должен быть self, это ссылка на текущих экземпляр класса, который передается при вызове метода, то есть это ключевое слово, отсылающее на сам класс.

Примеры

class Human:
    def __init__ (self, gender, name, age, height, weight):
        self.gender = gender
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

A = Human('male', 'A', 25, 176, 67)
Можно указать стандартное значение параметра, тогда его передача при создании объекта будет необязательной, если значение указано - оно будет переопределено
class Human:
    def __init__ (self, gender, name, age = 25, height, weight = None):
        self.gender = gender
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

A = Human('male', 'A', 35, 176)

Атрибуты

Значения присваиваемые через self., называются атрибутами экземпляра класса, например self.name = name. Атрибуты можно прочитать обратившись к его имени после указания имени объекта через точку, например A.name.
Атрибуты могут быть не только принадлежащими конкретному объекту, но и принадлежащими классу, например
class Human:
    human_count = 0
    def __init__ (self, gender, name, age, height, weight):
        self.gender = gender
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
        Human.human_count += 1
При создании объекта значение human_count увеличится. Доступ к атрибуту можно получить как и внутри класса так и снаружи.
Функция vars() выводит все атрибуты экземпляра класса в виде словаря, но не самого класса, например
A = Human('male', 'Tom', 25, 176, 67)
print(vars(A))
Будет выведено
{'gender': 'male', 'name': 'Tom', 'age': 25, 'height': 176, 'weight': 67}
Функция dir() отображает кроме атрибутов экземпляра еще и атрибуты класса, а так же прочие встроенные методы. То есть все то к чему можно обратится через точку, но без значений
A = Human('male', 'Tom', 25, 176, 67)
print(dir(A))
Будет выведено
[__class__, __init__, 'gender', 'name', 'age, 'height, 'weight', 'human_count']

Наследование

Наследование - повторное использование компонентов класса-родителя классом-потомком. Потомкам становятся доступны атрибуты и методы родительского класса. Чтобы инициализировать значения, которые есть в родительском классе, нужно обратиться к нему через super(), при этом выполняется конструктор родительского класса.

Пример
class Worker(Human):    # Worker наследуется от Human
  def __init__ (self, gender, name, age, height, weight, company, position, income):
    super().__init__ (gender, name, age, height, weight)
      self.company = company
      self.position = position
      self.income = income
  def work(self):
    print('I am worker')
Дочерний класс может использовать методы родительского, например
Tom = Worker('male', 'Tom', 25, 176, 67, 'Microsoft', 'Programmer', 1000)
Tom.work()
Tom.say()

Инкапсуляция

Инкапсуляция - ограничение доступа к элементам объекта (сокрытие элементов). В Python нет инкапсуляции на уровне языка, она действует на уровне соглашения между программистами. Есть два варианта: одно или два подчеркивания перед название переменной или метода. Если стоит одно подчеркивание это говорит другим программистам не использовать этот элемент, но они все равно смогут это использовать.

Два подчеркивания говорят о том, что строго запрещается использование этого элемента, но при этом его все равно можно использовать обратившись через название класса и одно нижнее подчеркивание перед названием класса, например
Tom._Human__ secret
Tom._Human__say()

Полиморфизм

Полиморфизм - разное поведение одного и того же метода в разных классах. В python нет возможности определить несколько методов с одинаковым именем, но с разными аргументами в одном классе.

Перегрузка операторов - в дочерних классах можно можно задать свою реализацию какого-либо метода.

В классе можно написать свою реализацию магических методов
Tom._Human__ secret
  x.__eq__(y)   # сравнение

staticmethod и classmethod

В классе могут присутствовать методы с предопределенными декораторами.
@staticmethod - обозначает обычную функцию, определенную внутри класса, не привязанная к данным конкретного объекта. Статические методы не знают о состоянии текущего экземпляра. Помогают в достижении инкапсуляции в классе.

В классе можно написать свою реализацию магических методов
class Human:
  human_count = 0
  def __init__ (self, gender, name, age, height, weight):
    self.gender = gender
    self.name = name
    self.age = age
    self.height = height
    self.weight = weight
    Human.human_count += 1
  @staticmethod
  def is_adult(age):
    adult = True if age >= 18 else False
    return print('Сотрудник совершеннолетний?', adult)
  
# Можно вызывать как по названию класса так и по названию экземпляра
Human.is_adult(Tom.age)
Tom.is_adult(18)
@classmethod - это обычный метод имеющий доступ ко всем атрибутам класса (не объекта), то есть этот метод привязан к классу, а не к конкретному экземпляру
class Human:
  human_count = 0
  def __init__ (self, gender, name, age, height, weight):
    self.gender = gender
    self.name = name
    self.age = age
    self.height = height
    self.weight = weight
    Human.human_count += 1
  @classmethod
  def get_human_count(cls):
    print('всего сотрудников', cls.human_count)
    
# Вызов метода осуществляется через имя класса
Human.get_human_count()