мета-данные страницы
  •  
Загрузка не удалась. Возможно, проблемы с правами доступа?

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
python:week22 [21/01/2019 01:18] – [Наследование] ybezrukovpython:week22 [21/01/2019 12:02] (текущий) – [Процедурные языки] ybezrukov
Строка 4: Строка 4:
  
 Чтобы понять что такое объектно-ориентированное программирование (ООП) нужно сначала понять что оно заменяет. Ранние языки были процедурными: программисту требовалось описать конкретный набор процедур которые выполнял компьютер. Чтобы понять что такое объектно-ориентированное программирование (ООП) нужно сначала понять что оно заменяет. Ранние языки были процедурными: программисту требовалось описать конкретный набор процедур которые выполнял компьютер.
- 
- 
- 
-To understand what an object-oriented programming language is, you need to understand what it replaced. Early programming languages were procedural—so-called because the programmer would define a very specific set of procedures that the computer would undertake. 
  
 В те времена процедуры записывались на перфокартах. На каждом шаге данные читались, обрабатывались и сохранялись. Этот подход хорошо работал тогда, да и сейчас в общем-то свою функцию выполняет. Однако, когда нам требуется написать программу, которая сложнее чем набор простых шагов - то в этом случае решение с помощью процедурного подход становится сложным для работы. Одним из вариантов преодоления результирующей сложности программы является ООП. В те времена процедуры записывались на перфокартах. На каждом шаге данные читались, обрабатывались и сохранялись. Этот подход хорошо работал тогда, да и сейчас в общем-то свою функцию выполняет. Однако, когда нам требуется написать программу, которая сложнее чем набор простых шагов - то в этом случае решение с помощью процедурного подход становится сложным для работы. Одним из вариантов преодоления результирующей сложности программы является ООП.
Строка 56: Строка 52:
  
 В этом случае, когда программист выполнит метод move() и передаст ему фигуру в качестве аргумента, программа будет точно знать как эта фигура должна двигаться. Это сэкономит кучу времени, которое ушло бы на попытки определить какой из кучи методов (например, move_horizontally(), move_vertically(), move_horizontally_one_step() и т.д.) нам потребуется использовать. В этом случае, когда программист выполнит метод move() и передаст ему фигуру в качестве аргумента, программа будет точно знать как эта фигура должна двигаться. Это сэкономит кучу времени, которое ушло бы на попытки определить какой из кучи методов (например, move_horizontally(), move_vertically(), move_horizontally_one_step() и т.д.) нам потребуется использовать.
 +
 +===== Резюме =====
 +
 +Прочитанное наверняка вызывает больше вопросов об ООП чем дает ответов. Перечислим кратко основное:
 +
 +  * ООП собирает информацию в единую сущность, именуемую объектом.
 +  * Каждый объект это конкретный экземпляр класса.
 +  * Абстракция скрывает внутренние механизмы объекта, когда нам не нужно о них знать.
 +  * Инкапсуляция хранит и защищает соответствующие переменные и методы внутри объекта.
 +  * Наследование позволяет подклассам использовать атрибуты родительских классов.
 +  * Полиморфизм позволяет объектам и методам работать с разными ситуациями с помощью одного интерфейса.
 +
 +Если запомните эти пункты, то этого будет достаточно чтобы иметь представление об ООП. Сущности довольно туманные, но понимание придет с практикой. Мы обсудили только очень общие свойства ООП, каждый ООП язык имеет свои особенности, подходы и способы как заставить все работать. Рассмотрим ООП на примере Питона.
 +
 +====== ООП в Питоне ======
 +
 +===== Классы =====
 +
 +Класс это базовый строительный блок в ООП. Можно считать класс шаблоном или чертежом объекта, который описывает характеристики объекта. Предположим что у нас есть класс Автомобиль. Он может содержать такие параметры: четыре колеса, двигатель и как минимум одно кресло.
 +
 +<code python> 
 +class Vehicle:
 +  """ Этот класс описывает средство передвижения """
 +  pass
 +</code>
 +
 +Комментарий в начале класса это специальный вид комментария, который называется докстринг в переводе, строка документации. Он должен содержать краткое описание того что делает код. Использование тройных кавычек и говорит Питону о том, что это докстринг. 
 +
 +Ключевое слово ''pass'' говорит интерпретатору Питона ничего не делать. Требуется так как синтаксис Питона не допускает пустоты после :. 
 +
 +Если мы этот код запустим, то ничего не произойдет. Сначала требуется создать экземпляр класса. Что буквально означает: построить объект используя план, описанный в классе. Можно сделать сколько угодно копий, каждую со своими свойствами.
 +
 +<code python>
 +red_car = Vehicle()
 +green_car = Vehicle()
 +blue_car = Vehicle()
 +</code>
 +
 +И все равно, если мы запустим код ничего не произойдет. Он работает корректно, но мы нигде не сказали программе сделать что-то заметное. Класс Vehicle описывает шаблон средства передвижения, а дальше создаются объекты с именами red_car, greed_car, blue_car.
 +
 +Дополним наш код. Добавим в класс Vehicle метод ''__init__'':
 +
 +<code python>
 +class Vehicle:
 +  """ Этот класс описывает средство передвижения """
 +
 +  def __init__(self, color='plain'):
 +    """ задает параметры средства передвижения """
 +    print('Сделали машину!')
 +    self.color = color
 +
 +red_car = Vehicle()
 +green_car = Vehicle()
 +blue_car = Vehicle()
 +</code>
 +
 +Обратите особое внимание на метод ''__init__''. Это специальный метод в Питоне и должен начинаться и заканчиваться двумя символами подчеркивания. Он автоматически вызывается всякий раз, когда создается новый объект. Теперь, если мы запустим этот код, то на экране будет три раза написана строка ''Сделали машину!''
 +
 +Так же метод ''__init__'' имеет аргумент с именем ''color''. Запись ''color='plain''' в описании аргументов функции задает значение аргумента по-умолчанию (т.е. значение, которое получит переменная color если мы не укажем никакого аргумента. Добавим цвета:
 +
 +<code python>
 +red_car = Vehicle(color='red')
 +green_car = Vehicle(color='green')
 +blue_car = Vehicle(color='blue')
 +</code>
 +
 +Если напечатать на экран значение переменной, можно заметить, что у каждого экземпляра цвет свой, хотя созданы они были по одному описанию (классу).
 +
 +<code python>
 +print(red_car.color)
 +print(green_car.color)
 +print(blue_car.color)
 +</code>
 +
 +
 +Так вышло потому, что мы присвоили значение переменной ''self.color''. ''self'' это еще одно ключевое слово в Питоне, оно ссылается на конкретный экземпляр класса (объект). Всякий раз когда мы используем ''self'', мы можем изменить или прочитать данные, уникальные для объекта: красная машина - красная.
 +
 +Расширим метод ''__init__'' и добавим в него 
 +
 +<code python>
 +self.noise = 'Дрыннь!'
 +</code>
 +
 +Можно, конечно, просто напечатать на экран значение этой переменной. Сделаем немного иначе, пусть мы хотим чтобы машина ехала, и в будущем используем это в коде. Или изменим метод передвижения. Заведем функцию (метод) чтобы иметь контроль над тем как все работает. Добавим его сразу после метода ''__init__'':
 +
 +<code python>
 +def drive(self):
 +  print(self.noise)
 +</code>
 +
 +Вызвать этот метод можно написав:
 +
 +<code python>
 +red_car.drive()
 +</code>
 +
 +Всякий раз когда мы будем вызывать метод Питон будет печатать на экран звук движения машины. Вся наша программа сейчас должна выглядеть вот так:
 +
 +<code python>
 +class Vehicle:
 +  """ Этот класс описывает средство передвижения """
 +
 +  def __init__(self, color='plain'):
 +    """ задает параметры средства передвижения """
 +    print('Сделали машину!')
 +    self.color = color
 +    self.noise = 'Дрыннь!'
 +    
 +  def drive(self):
 +    print(self.noise)
 +    
 +red_car = Vehicle(color='red')
 +green_car = Vehicle(color='green')
 +blue_car = Vehicle(color='blue')
 +
 +print(red_car.color)
 +print(green_car.color)
 +print(blue_car.color)
 +
 +red_car.drive()
 +</code>
 +
 +===== Наследование =====
 +
 +Наследование это способ уменьшить дублирование и переиспользовать код. В терминах предков-потомков, наследование позволяет потомку делить общий код с предком. Создадим новый класс ElectricCar
 +
 +<code python> 
 +class ElectricCar(Vehicle):
 +  """ Электромобиль. """
 +  def charge(self):
 +    print('⚡🔋')
 +
 +electric_car = ElectricCar()
 +electric_car.charge()
 +electric_car.noise = 'Вжух!'
 +electric_car.drive()
 +
 +</code>
 +
 +Во время описания класса электромобиля мы указали имя класса Vehicle в скобках. Это инструкция Питону считать класс ElectricCar потомком или подклассом класса Vehicle. Это дает доступ до данных и методов, существующим в Vehicle.
 +
 +Электромобиль имеет так же свои методы. Он может заряжаться (этого другие машины не умеют). И издает другой звук при движении. Обратите внимание, мы не описывали метод drive() в новом классе, однако он работает и выдает верный результат.