Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Моделирование Python: Составные данные

Абстракции позволяют нам моделировать необходимую предметную область. Попробуем понять это утверждение на конкретном примере. Допустим, мы хотим сделать программу-каталог для управления коллекцией книг. Вы можете сразу кинуться писать код, но так делать не стоит :)

В первую очередь необходимо проанализировать предметную область (книги + каталоги) и сформировать базовую модель. Нужно начать с определения сущностей и операций над ними. В случае нашего каталога у нас есть по крайней мере две сущности: книга и коллекция. Базовыми операциями сделаем добавление книги в коллекцию и удаление её из коллекции.

Напишем код операции для добавления сущности в коллекцию:

book1 = make_book('The Comedy of Errors')
book2 = make_book('The Adventures of Tom Sawyer')
coll = makeColl('Adventures')
updated_Coll_1 = add_Book_To_Coll(coll, book1)
updated_Coll_2 = add_Book_To_Coll(updated_Coll_1, book2)

Мы создаём две книги, одну коллекцию и добавляем эти книги в коллекцию. Что значит "создали книгу"? Что такое "книга"? Книга — это сущность, которая ведёт себя как книга. Что это значит?

Так как мы работаем с языком программирования, то конструктор make_book, создающий книгу, возвращает какие-то данные: примитивные (число, строку) или составные, используя пары. Главное — нам не важно, как они устроены.

Организовать эти данные можно тысячью разных способов, и конкретный способ зависит от разработчика, его предпочтений и данных, которые необходимо хранить. То, что книга является книгой, определяется не её внутренним устройством, а тем, что к ней применим набор операций, созданный для книг. Например, операция «получить имя книги». Сами операции знают, как устроены данные, иначе они не смогли бы ими манипулировать. Запомните: это детали реализации. Не заглянув внутрь операций, мы не узнаем, как они устроены, но нам это и не нужно.

В этом и заключается вся суть абстракции. Мы знаем, как создать сущность и какие операции к ней применимы. Обычно это и называется дизайном кода, а сами операции + конструктор — это API или интерфейс модуля/пакета/библиотеки.

Получаем следующий алгоритм:

  1. Анализируем предметную область. Выделяем сущности.
  2. Реализуем конструктор. Внутреннее представление сущностей выбираем на основе того, что мы планируем в них хранить.
  3. Реализуем необходимые операции.

В примере с книгами видно, что мы храним только название. А это значит, что нам достаточно хранить одну строчку.

Тогда реализация конструктора будет такой:

def make_book(name):
    return name

book = make_book('The Comedy of Errors')
print(to_string(book))  # The Comedy of Errors 

А что, если мы захотим дополнительно хранить версию издания книги? Тогда мы можем использовать пары для хранения составных данных, и у нас уже появляются составные данные, так как нужно хранить два параметра.

def make_book(name, rev):
    return cons(name, rev)

book = make_book('The Adventures of Tom Sawyer', 3)
print(to_string(book))  # (The Adventures of Tom Sawyer, 3)

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

Примеры других абстракций

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

  1. Товар. Всё, что продаётся и покупается. Предположим, что нам интересны только два параметра: цена и название. Саму сущность можно назвать product. Тогда наша абстракция будет содержать как минимум три следующих функции:

    # интерфейсные функции (абстракция)
    def make_product(name, cost):
         return cons(name, cost)
    
    def get_name(product):
        return car(product)
    
    def get_cost(product):
        return cdr(product)
    
    # использование
    product = make_product('parmesan cheese', 100)
    get_name(product)  # parmesan cheese
    get_cost(product)  # 100
    
  2. Текстовый документ. Например, как в Google Docs. В нашем примере он будет состоять из названия и содержимого.

    # интерфейсные функции (абстракция)
    def make_document(name, body):
        return cons(name, body)
    
    def get_name(document):
        return car(document)
    
    def get_body(document):
        return cdr(document)
    
    # использование
    document = make_document('Some words about Hexlet', 'Any test')
    get_name(document)  # some words about hexlet
    get_body(document)  # any test
    
  3. А вот пример, в котором нужно хранить не два значения, а три. Это точка в пространстве.

    # интерфейсные функции (абстракция)
    def make_3d_point(x, y, z):
        return cons(cons(x, y), z)  # альтернатива cons(x, cons(y, z))
    
    def get_x(point):
        return car(car(point))
    
    def get_y(point):
        return cdr(car(point))
    
    def get_z(point):
        return cdr(point)
    
    # использование
    point = make_3d_point(1, 10, -3)
    

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

Предположим, что мы продаём документы как продукты:

document = make_document('Some words about Hexlet', 'Any test')
product = make_product(document, 100)

А дальше всё по аналогии.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

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

Получить доступ
900
упражнения
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 120 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»