Основы ООП#

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

  • Экземпляр класса (instance) - объект, который является представителем класса.

  • Метод (method) - функция, которая определена внутри класса и описывает какое-то действие, которое поддерживает класс

  • Переменная экземпляра (instance variable, а иногда и instance attribute) - данные, которые относятся к объекту

  • Переменная класса (class variable) - данные, которые относятся к классу и разделяются всеми экземплярами класса

  • Атрибут экземпляра (instance attribute) - переменные и методы, которые относятся к объектам (экземплярам) созданным на основании класса. У каждого объекта есть своя копия атрибутов.

Пример из реальной жизни в стиле ООП:

  • Проект дома - это класс

  • Конкретный дом, который был построен по проекту - экземпляр класса

  • Такие особенности как цвет дома, количество окон - переменные экземпляра, то есть конкретного дома

  • Дом можно продать, перекрасить, отремонтировать - это методы

Например, при работе с netmiko первое, что нужно было сделать создать подключение:

from netmiko import ConnectHandler

device = {
    "device_type": "cisco_ios",
    "host": "192.168.100.1",
    "username": "cisco",
    "password": "cisco",
    "secret": "cisco",
}

ssh = ConnectHandler(**device)

Переменная ssh - это объект, который представляет реальное соединение с оборудованием. Благодаря функции type, можно выяснить экземпляром какого класса является объект ssh:

In [3]: type(ssh)
Out[3]: netmiko.cisco.cisco_ios.CiscoIosSSH

У ssh есть свои методы и переменные, которые зависят от состояния текущего объекта. Например, переменная экземпляра ssh.host доступна у каждого экземпляра класса netmiko.cisco.cisco_ios.CiscoIosSSH и возвращает IP-адрес или имя хоста, в зависимости от того что указывалось в словаре device:

In [4]: ssh.host
Out[4]: '192.168.100.1'

Метод send_command выполняет команду на оборудовании:

In [5]: ssh.send_command("sh clock")
Out[5]: '*10:08:50.654 UTC Tue Feb 2 2021'

Метод enable переходит в режим enable и при этом объект ssh сохраняет состояние: до и после перехода видно разное приглашение:

In [6]: ssh.find_prompt()
Out[6]: 'R1>'

In [7]: ssh.enable()
Out[7]: 'enable\r\nPassword: \r\nR1#'

In [8]: ssh.find_prompt()
Out[8]: 'R1#'

В этом примере показаны важные аспекты ООП: объединение данных и действия над данными, а также сохранение состояния.

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

Например, в экзепляре класса str, все методы относятся к работе с этой строкой:

In [10]: s = 'string'

In [11]: s.upper()
Out[11]: 'STRING'

In [12]: s.center(20, '=')
Out[12]: '=======string======='

Выше, при обращении к атрибутам экземпляра (переменным и методам) используется такой синтаксис: objectname.attribute. Эта запись s.lower() означает: вызвать метод lower у объекта s. Обращение к методам и переменным выполняется одинаково, но для вызова метода, надо добавить скобки и передать все необходимые аргументы.

Всё описанное неоднократно использовалось в книге, но теперь мы разберемся с формальной терминологией.