ПРОГРАММИРОВАНИЕ

Объектно-ориентированное программирование (ООП) на Python

Демистификация классов, объектов, наследования и т. Д.

Что такое ООП?

Объектно-ориентированное программирование - это метод организации программы путем группировки связанных свойств и поведения в отдельные объекты. Основными строительными блоками ООП являются объекты и классы.

класс - это шаблон кода для создания объектов, мы можем рассматривать его как план. Он описывает возможные состояния и поведение, которые может иметь каждый объект определенного типа. Например, если мы говорим, что «у каждого сотрудника будет имя и зарплата, и ему можно будет повысить зарплату», то мы просто определили класс!

объект - это структура данных, хранящая информацию о состоянии и поведении определенной сущности, и является экземпляром класса. Например, объект, представляющий сотрудника, может иметь определенные атрибуты, такие как зарплата и должность, связанные с ним, а также поведение, такое как повышение.

Объект = состояние + поведение

Информация о состоянии объекта содержится в атрибутах, а информация о поведении - в методах. Кроме того, атрибуты или состояния объекта представлены переменными, такими как числа, строки или кортежи. В то время как методы объекта или поведения представлены функциями.

Отличительной особенностью ООП является то, что состояние и поведение связаны вместе. Это означает, что вместо того, чтобы рассматривать данные о сотрудниках отдельно от, например, действий сотрудников, мы рассматриваем их как одну единицу, представляющую сотрудника. Это называется инкапсуляцией и является одним из основных принципов объектно-ориентированного программирования.

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

Как мы уже говорили ранее, классы - это схемы для создания объектов. Теперь давайте воплотим в жизнь наш первый план.

class Employee:
   pass

Класс Employee сейчас не имеет большой функциональности. Мы начнем с добавления некоторых свойств, которые должны быть у всех Employee объектов. Для простоты мы просто добавим атрибуты name и salary.

Назначение атрибутов классу

Свойства, которые должны иметь все Employee объекты, определены в методе .__init__() или в методе конструктора. Каждый раз, когда создается новый объект Employee, автоматически вызывается метод конструктора.

Давайте обновим класс Employee с помощью .__init__() метода, который создает атрибуты .name и .salary:

class Employee:
    def __init__(self, name, salary=0):
        self.name = name
        self.salary = salary

Обратите внимание, чтоself используется как 1-й аргумент в любом определении метода, включая наш метод конструктора. Кроме того, self.name = name создает атрибут с именем name и присваивает ему значение параметра name. То же самое происходит с атрибутом salary, за исключением того, что мы устанавливаем salary по умолчанию равным 0.

Атрибуты экземпляра и атрибуты класса

Атрибуты, созданные в .__init__(), называются атрибутами экземпляра. Значение атрибута экземпляра зависит от конкретного экземпляра класса. Все объекты Employee имеют имя и зарплату, но значения атрибутов name и salary будут различаться в зависимости от экземпляра Employee.

С другой стороны, атрибуты класса - это атрибуты, которые имеют одинаковое значение для всех экземпляров класса. Вы можете определить атрибут класса, присвоив значение имени переменной вне .__init__() следующим образом:

class Employee:
   #Class attribute
   organization = "xxx"
    def __init__(self, name, salary=0):
        self.name = name
        self.salary = salary

Подводя итог, атрибуты класса используются для определения характеристик, которые должны иметь одинаковое значение для каждого экземпляра класса, в то время как атрибуты экземпляра используются для определения свойств, которые отличаются от одного экземпляра к другому.

Назначение методов классу

Методы экземпляра

Это функции, которые определены внутри класса и могут быть вызваны только из экземпляра этого класса. Как и в случае с методом конструктора, первым параметром метода экземпляра всегда является self. Давайте продемонстрируем, как мы можем написать метод экземпляра, опираясь на наш пример Employee класса, сделанный ранее.

class Employee:
   organization = "xxx"
   def __init__(self, name, salary=0):
        self.name = name
        self.salary = salary
    #Instance method
    def give_raise(self, amount):
        self.salary += amount
        return f"{self.name} has been given a {amount} raise"

Как видите, методы экземпляра похожи на обычные функции с той разницей, что в качестве первого параметра используется self.

Методы класса

Метод класса - это метод, который привязан к классу, а не к объекту класса. У них есть доступ к состоянию класса, поскольку он принимает параметр класса вместо обычного self, который указывает на класс, а не на экземпляр объекта.

Чтобы определить метод класса, вы начинаете с декоратора метода класса, за которым следует определение метода. Единственное отличие состоит в том, что теперь первым аргументом является не self, а cls, относящийся к классу, точно так же, как аргумент self был ссылкой на конкретный экземпляр. Затем вы пишете ее как любую другую функцию, помня, что вы не можете ссылаться ни на какие атрибуты экземпляра в этом методе.

Поскольку метод класса имеет доступ только к этому cls аргументу, он не может изменять состояние экземпляра объекта. Для этого потребуется доступ к self. Однако методы класса по-прежнему могут изменять состояние класса, которое применяется ко всем экземплярам класса.

class MyClass:
   # instance method 
   def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod(cls):
        return 'class method called', cls

Идея метода класса очень похожа на метод экземпляра, с той лишь разницей, что вместо передачи экземпляра в качестве первого параметра мы теперь передаем сам класс в качестве первого параметра. Поскольку мы передаем методу только класс, экземпляр не задействован. Это означает, что нам вообще не нужен экземпляр, и мы вызываем метод класса, как если бы он был статической функцией:

MyClass.classmethod()

Тогда как если бы мы хотели вызвать метод экземпляра, нам нужно было бы сначала создать экземпляр объекта, а затем вызвать функцию следующим образом:

object = MyClass()
object.method()

Если вы не знаете, что означает создание экземпляра объекта, мы поговорим об этом позже.

Создать экземпляр объекта

Создание нового объекта из класса называется созданием экземпляра объекта. Мы можем создать новые Employee объекты с указанными ниже атрибутами как таковые:

e1 = Employee("yyy", 5000)
e2 = Employee("zzz", 8000)

Вы можете получить доступ к атрибутам, используя точечную нотацию, следующим образом:

# access first employee's name attribute
e1.name
# access second employee's salary attribute
e2.salary

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

Наследование классов - это механизм, с помощью которого один класс перенимает атрибуты и методы другого. Вновь сформированные классы называются дочерними классами, а классы, производные от которых являются дочерними классами, называются родительскими классами. У дочернего класса есть все родительские данные.

Атрибуты и методы родительских классов могут быть переопределены или расширены дочерними классами. Другими словами, дочерние классы наследуют все атрибуты и методы своих родителей, но они также могут определять свои собственные атрибуты и методы.

Объявить дочерний класс, наследующий от родительского, очень просто.

class Manager(Employee):
   pass

Теперь мы можем создать Manager объект, даже если мы не определили конструктор.

m1 = Manager("aaa", 13000)

Настройка функциональности через наследование

Допустим, мы хотим добавить дополнительные атрибуты к нашему дочернему классу. Мы можем легко сделать это, настроив конструкторы специально для нашего дочернего класса и вызвав конструктор родительского класса.

class Manager(Employee):
   def __init__(self, name, salary=0, department):
        Employee.__init__(self, name, salary=0)
        self.department = department

Лучшие практики

При работе с классами и объектами следует помнить о нескольких рекомендациях.

  • Для именования классов используйте верблюжий регистр, что означает, что если имя вашего класса содержит несколько слов, они должны быть написаны без разделителей, и каждое слово должно начинаться с заглавной буквы.
  • Для методов и атрибутов все наоборот - слова должны быть разделены подчеркиванием и начинаться с строчных букв.
  • Имя «я» - условность. Фактически вы можете использовать любое имя для первой переменной метода, оно всегда будет рассматриваться как ссылка на объект независимо. Хотя это так, всегда лучше использовать self.
  • Не забудьте написать строки документации для своих классов, чтобы ваш код был более понятным для потенциальных соавторов и будущих вас.

Заключение

Подводя итог, мы рассмотрели, что такое ООП, классы и объекты. Мы также рассмотрели разницу между методами экземпляра и методами класса, и мы сделали то же самое для атрибутов экземпляра, а также атрибутов класса. Мы также кратко рассмотрели, что такое наследование классов и каковы некоторые из лучших практик при работе с классами.

На этом мы завершаем наше руководство. Надеюсь, эта статья оказалась для вас полезной! Если да, то это тоже может вас заинтересовать. Как всегда, я хотел бы услышать любые комментарии или вопросы, которые могут у вас возникнуть. Удачного обучения!