Skip to content

Turonk/praktikum_webinar_oop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 

Repository files navigation

ЯндексПрактикум: тема - ООП

Проект для проведения лайва и закрепления теории

Задача

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

Сейчас фирма располагает экскурсионными автомобилями и легкими самолетами.

Принято, что:

  • средний расход автомобилей 12л/100км
  • средний расход самолетов 200кг топлива на час полета

Предполагается — программа будет создана при помощи ООП.

Поскольку парк транспортных средств может (и будет!) расширяться, кажется целесообразным использовать ООП.

Начнем с создания базового класса Transport (https://tatyderb.gitbooks.io/python-express-course/content/chapter_oop_advanced/oop_super.html).

class Transport:
    pass

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

Эти свойства мы будем определять в "конструкторе" (инициализаторе) __init__ (https://younglinux.info/oopython/init.php).

class Transport:
    def __init__(self, fuel):
        self.fuel = fuel
        self.trips = []

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

Примечание: для экземпляра класса название передаваемого параметра def __init__(self, fuel) и название поля self.fuel не обязаны совпадать.

def __init__(self, toplivo):
    self.f = toplivo

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


Да кто такой этот ваш self ?!

Имя для первого аргумента, представляющего текущий объект класса, self — это стандартное имя первого аргумента для методов объекта.

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

https://pythonz.net/references/named/self/


Далее, для регистрации экскурсионных поездок нам необходим метод добавления их в список поездок — add_trip.

class Transport:
    def __init__(self, fuel):
        self.fuel = fuel
        self.trips = []

    def add_trip(self, trip):
        self.trips.append(trip)

Метод add_trip должен получать на вход сведения о поездке (это будет экземпляр класса Trip, который мы создадим ниже) и добавлять ее в наш список self.trips. Добавление в конец списка осуществляется методом .append(добавляемая сущность).

Подробнее: https://pythonworld.ru/tipy-dannyx-v-python/spiski-list-funkcii-i-metody-spiskov.html.


Создадим метод расчета общей пройденной дистанции транспортным средством.

class Transport:
    def __init__(self, fuel):
        self.fuel = fuel
        self.trips = []
    
    def add_trip(self, trip):
        self.trips.append(trip)
    
    def sum_trips_distance(self):
        return sum(trip.distance for trip in self.trips)

Метод sum_trips_distance(self) возвращает нам сумму всех пройденных дистанций из списка экскурсий конкретного транспортного средства.

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

Запись trip.distance for trip in self.trips — это генератор списков в python (https://younglinux.info/python/feature/generators).

На выходе из генератора мы получим последовательность вида [213, 55, 345]. Это будет именно последовательность, а не список, так что работать с генератором как с обычным списком нельзя. Можно превратить результат генератора в список, например, так: list(trip.distance for trip in self.trips). Но функция sum отлично справляется и со списками и с генераторами, поэтому просто применяем ее к генератору (https://pythonz.net/references/named/sum/).

Еще определим метод calculate_reachable_distance, который будем переопределять в дочерних классах. Он будет нужен для определения дистанции, которую сможет пройти транспортное средство на оставшемся количестве топлива.

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

def calculate_reachable_distance(self):
    raise NotImplementedError()

Для нашей задачи такого базового класса будет достаточно.


Перейдем к созданию обозначенного выше класса Trip.

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

class Trip:
    def __init__(self, dist, comment='Не регламентировано'):
        self.distance = dist
        self.comment = comment

Запись comment = 'Не регламентировано' означает, что если мы не указываем при создании экземпляра класса значение для comment, то по умолчанию будет подставлено 'Не регламентировано'.


Перейдем к созданию дочерних классов транспортных средств (автомобилей и самолетов).

class Car(Transport):
    FUEL_CONSUMPTION_CAR = 0.12

    def calculate_reachable_distance(self):
        distance_covered = self.sum_trips_distance()
        result = (self.fuel - (distance_covered * self.FUEL_CONSUMPTION_CAR)) // self.FUEL_CONSUMPTION_CAR
        return f'Топлива осталось на {result} км'
class Airplane(Transport):
    FUEL_CONSUMPTION_AIRPLANE = 200

    def calculate_reachable_distance(self):
        distance_covered = self.sum_trips_distance()
        result = (self.fuel - (distance_covered * self.FUEL_CONSUMPTION_AIRPLANE)) // self.FUEL_CONSUMPTION_AIRPLANE
        return f'Топлива осталось на {result} часов'

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

Переменные FUEL_CONSUMPTION_CAR и FUEL_CONSUMPTION_AIRPLANE — константы обозначающие коэффициенты для расчета.


Пара слов о константах

Константы — переменные, значения которых никогда не меняются.

Их записывают заглавными буквами (https://pythonz.net/references/named/constants/).

В python это договоренность, нежели ограничение языка, поменять можно все :) Но договоренности надо соблюдать.


Запись class Airplane(Transport) свидетельствует о том что мы наследуемся от базового класса Transport, а значит, все свойства и методы базового класса мы можем использовать и в дочерних классах.

Если не добавлять и не переопределять свойства в конструкторе дочерних классов, то конструктор в дочерних классах писать не нужно.

Далее в методах calculate_reachable_distance мы используем вызов self.sum_trips_distance() и свойство self.fuel, которые мы определяли только в родительском классе — это тоже свидетельство того, что все эти свойства и методы унаследованы.


Полный код получившийся программы
class Trip:
    def __init__(self, dist, comment="Не регламентировано"):
        self.distance = dist
        self.comment = comment


class Transport:
    def __init__(self, fuel):
        self.fuel = fuel
        self.trips = []

    def add_trip(self, trip):
        self.trips.append(trip)

    def sum_trips_distance(self):
        return sum(trip.distance for trip in self.trips)

    def calculate_reachable_distance(self):
        raise NotImplementedError()


class Car(Transport):
    FUEL_CONSUMPTION_CAR = 0.12

    def calculate_reachable_distance(self):
        distance_covered = self.sum_trips_distance()
        result = (self.fuel - (distance_covered * self.FUEL_CONSUMPTION_CAR)) // self.FUEL_CONSUMPTION_CAR
        return f'Топлива осталось на {result} км'


class Airplane(Transport):
    FUEL_CONSUMPTION_AIRPLANE = 200

    def calculate_reachable_distance(self):
        distance_covered = self.sum_trips_distance()
        result = (self.fuel - (distance_covered * self.FUEL_CONSUMPTION_AIRPLANE)) // self.FUEL_CONSUMPTION_AIRPLANE
        return f'Топлива осталось на {result} часов'

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

Затем добавим запись об экскурсии.

И наконец, выведем информацию об оставшихся возможностях.

Код проверки работоспособности
jeep = Car(80)
jeep.add_trip(Trip(dist=144, comment='туристический маршрут'))
print(jeep.calculate_reachable_distance())

Должно вывестись следующее:

Топлива осталось на 522.0 км

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages