Объектно-ориентированное программирование в Python (Часть 1)

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

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

Предположим, необходимо создать болид Формулы-1 с помощью инструментов ООП. В первую очередь, необходимо определить реальные объекты в гонке. Какие аспекты этого мероприятия имеют определенные характеристики и способны выполнять определенную задачу?

Первый ответ, который придет в голову, – это гоночный болид. Он может иметь следующие свойства:

  1. Мощность двигателя.
  2. Марка.
  3. Модель.
  4. Производитель.

Возможны и другие особенности. Здесь важно понять логику. С болидом возможно выполнение разнообразных действий: запуска, остановки, ускорения или наоборот, замедления.

Еще один объект – это гонщик. У него есть такие характеристики, как национальность, возраст, пол и другие. Помимо этого, у него есть определенный набор функций, таких как управление болидом, рулевое управление, переключение передач.

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

Учтите то, что ООП – это концепция, которая не зависит от конкретного языка. Подавляющее число языков, таких как Java, C++, Python, являются объектно-ориентированными.

Достоинства и недостатки

Давайте проанализируем ряд положительных сторон объектно-ориентированной разработки приложений:

  1. В объектно-ориентированном программировании один и тот же блок приложения может использоваться многократно. Нет необходимости заново писать код. Достаточно импортировать объект и задать его параметры, после чего можно попросить его выполнить то или иное действие.
  2. Применение модулярного подхода в ООП дает возможность получить код, который будет максимально гибким и доступным к чтению.
  3. Каждый класс в ООП решает конкретную задачу. Если в определенной части кода появляется исключение, его можно обработать без надобности изменять другие части приложения. 
  4. Инкапсуляция позволяет сделать программу более безопасной.

Несмотря на то, что ООП имеет ряд очевидных достоинств, минусы у такого подхода также имеются:

  1. Необходимо иметь полное понимание о той программе, которая разрабатывается.
  2. Не все аспекты ПО – это оптимальное решение по реализации таким способом. Могут возникнуть некоторые дополнительные сложности для новичков.
  3. По мере добавления новых классов в код, программа становится все более сложной. Причем рост происходит не линейно, а экспоненциально.

Далее проанализируем наиболее значимые концепции ООП.

Как понятно из названия этой концепции разработки приложений, ООП – это про объекты. Тем не менее для создания объекта сперва необходимо обозначить его класс.

Что такое класс?

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

Сам по себе класс не представляет ничего. Так, схема – это не дом. Тем не менее она дает понимание того, как он выглядит в норме.

Приведем еще один пример, который позволяет выразить соотношение между классом и объектом нагляднее. Есть машина, и есть Audi. Конечно, последняя тоже является автомобилем. Тем не менее, машины, по факту, нет. Это абстрактная концепция, которая находит свою реализацию в Honda, Toyota, Mercedes и так далее.

Чтобы создать класс, задействуется ключевое слово class. Имя класса идет непосредственно за этим ключевиком, а потом обязательно нужно поставить знак двоеточия. Тело класса стартует с новой строчки, с отступом на одну вкладку влево.

Рассмотрим, как создается наиболее простой класс в Python. Посмотрите на этот фрагмент кода. 

# Создаем класс Car

class Car:




    # создаем атрибуты класса

    name = "c200"

    make = "mercedez"

    model = 2008




    # создаем методы класса

    def start(self):

        print ("Заводим двигатель")




    def stop(self):

        print ("Отключаем двигатель")

В этом примере нами был создан класс под названием Car, у которого есть три атрибута: name, make, model, которые означают имя, марку и модель соответственно.

Также этот класс имеет два метода – start() и stop(), которые выдают сообщения о том, что двигатель заводится или отключается.

Объекты

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

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

В качестве синонима объекта нередко используется слово «экземпляр». При этом, процедура создания объекта класса называется инициализацией. В Python, для создания объекта класса, необходимо лишь вписать его имя со скобками, которые открываются и закрываются.

Сгенерируем экземпляр класса Car, созданного ранее. 

# Создаем объект класса Car под названием car_a

car_a = Car()




# Создаем объект класса Car под названием car_b

car_b = Car()

Здесь было создано два экземпляра класса Car: car_a и car_b. Чтобы узнать тип объектов, которые нами были созданы, возможно использование метода type с дальнейшей передачей ему названий объектов. Давайте вы попробуете выполнить такой код. 

print(type(car_b))

Когда вы это сделаете, в выдаче увидите следующую строку. 

<class '__main__.Car'>

Это указывает на то, что тип объекта car_b – класс Car.

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

Давайте рассмотрим такой пример. 

car_b.start()

В данном скрипте нами был вызван метод start() через объект car_b. Выдача будет следующей.

Заводим двигатель

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

print(car_b.model)

В выдаче отобразится модель.

2008

Атрибуты класса

Ранее мы поняли, как генерировать объекты класса и как они могут использоваться для получения доступа к определенным атрибутам класса.

В Python, каждый из объектов включает определенные атрибуты по умолчанию и методы в дополнение к конкретным атрибутам, созданным разработчиком. Чтобы получить перечень всех атрибутов и методов объекта, используется специальная функция dir()

Попробуем посмотреть на все атрибуты объекта car_b, созданногоранее. Выполните такой скрипт. 

print(dir(car_b))

В выдаче вы увидите такие атрибуты.

[‘__class__’,

 ‘__delattr__’,

 ‘__dict__’,

 ‘__dir__’,

 ‘__doc__’,

 ‘__eq__’,

 ‘__format__’,

 ‘__ge__’,

 ‘__getattribute__’,

 ‘__gt__’,

 ‘__hash__’,

 ‘__init__’,

 ‘__init_subclass__’,

 ‘__le__’,

 ‘__lt__’,

 ‘__module__’,

 ‘__ne__’,

 ‘__new__’,

 ‘__reduce__’,

 ‘__reduce_ex__’,

 ‘__repr__’,

 ‘__setattr__’,

 ‘__sizeof__’,

 ‘__str__’,

 ‘__subclasshook__’,

 ‘__weakref__’,

 ‘make’,

 ‘model’,

 ‘name’,

 ‘start’,

 ‘stop’]

Данная встроенная функция будет очень полезной для изучения атрибутов и функций того или иного экземпляра. Особенно если используется REPL.

Атрибуты класса против атрибутов объектов

В целом, выделяют два типа атрибутов:

  1. Атрибуты класса.
  2. Атрибуты экземпляров.

Атрибуты класса делятся среди всех экземпляров, относящихся к определенному классу. В то же время, атрибуты экземпляров – это собственность экземпляра. 

Не забывайте о том, то «экземпляр» и «объект» – это синонимы.

Атрибуты объекта объявляются внутри какого-угодно метода. В то же время, атрибуты класса объявляются за пределами любого метода.

Более точно понять эту разницу можно с помощью такого примера. 

class Car:

 

    # создаем атрибуты класса

    car_count = 0

 

    # создаем методы класса

    def start(self, name, make, model):

        print("Двигатель заведен")

        self.name = name

        self.make = make

        self.model = model

        Car.car_count += 1

Здесь нами создается класс Car, имеющий один атрибут класса, который называется car_count, а также три атрибута объекта, именуемых name, make, model. Класс включает один метод start(), в который входит три атрибута экземпляров. В свою очередь, значения атрибутов экземпляров передаются в качестве аргументов методу start(). Внутри метода start, атрибут car_count увеличивается на единицу.

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

Давайте попробуем создать объект класса Car, после чего вызовем метод start()

 car_a = Car()  

car_a.start("Corrola", "Toyota", 2015)  

print(car_a.name)  

print(car_a.car_count)

В приведенном ранее скрипте мы вывели название атрибута экземпляра и атрибута класса car_count. В выдаче будет показано, что атрибут car_count будет иметь значение 1, как указано ниже.

Двигатель заведен 

Corrola  

1

Теперь давайте попробуем создать еще один объект класса Car и вызвать метод start()

car_b = Car()  

car_b.start("City", "Honda", 2013)  

print(car_b.name)  

print(car_b.car_count)

Сейчас если вы выведете значение атрибута car_count, то в выдаче увидите цифру 2. Почему это так? Дело в том, что атрибут car_count – это атрибут класса. Следовательно, он разделяется между экземплярами. Объект car_a увеличил значение до единицы, в то время как car_b увеличил значение еще раз таким образом, что результирующее значение получается 2. Выдача выглядит так.

Двигатель заведен 

City  

2

ОфисГуру
Adblock
detector