2.2.3 Абстрактные границы
Прежде чем продолжить рассмотрение примеров с более сложными данными и абстракцией данных, давайте рассмотрим некоторые проблемы, возникающие из-за использования рациональных чисел. Мы определили операции, используя конструктор make_rat
и селекторы numer
и denom
. Обычно базовое понятие абстракции данных заключается в том, как выражаются операции на основе типа значения, и определении набора основных операций для этого типа значений. Затем эти операции используются для работы с данными.
Мы можем представить систему рациональных чисел как серию уровней. Параллельные линии представляют разделение системы на разные уровни. На каждом уровне границы отделяют функции, которые используют абстракцию данных (выше), от функций, реализующих абстракцию данных (ниже). Программы, работающие с рациональными числами, оперируют ими только через арифметические функции: add_rat
, mul_rat
и eq_rat
. Соответственно, эти функции реализуются только конструктором и селекторами make_rat
, numer
и and denom
, которые сами реализованы через кортежи. Как реализованы байты и другие уровни кортежей, не имеет значения, пока кортеж поддерживает реализацию селектора и конструктора.
На каждом уровне функции в коробках принудительно разделяют абстрактные границы, поскольку они зависят только от представления верхнего уровня (через использование) и реализации нижнего уровня (через определение). Таким образом, абстрактные границы могут быть представлены серией функций.
Абстрактные границы имеют много преимуществ. Одно из преимуществ заключается в том, что они делают программу более удобной для обслуживания и модификации. Мало функций зависит от конкретного представления, поэтому при желании изменить представление требуется внести меньше изменений.
2.2.4 Свойства данных
Мы начали реализовывать рациональные числа, реализовав три неспецифические функции: make_rat
, numer
и denom
. Здесь мы можем считать, что операции над дробями, числителями и рациональными числами определены этими тремя функциями.
Но что означает данные? Мы ещё не можем сказать, что «предоставленные селекторы и конструкторы что-то реализовали». Нам нужно убедиться, что эти функции вместе определяют правильное поведение. То есть, если мы создадим рациональное число x
из целых чисел n
и d
, то numer(x)/denom(x)
должно равняться n/d
.
Обычно мы можем рассматривать абстрактный тип данных как набор селекторов и конструкторов с некоторыми условиями поведения. Пока выполняются условия поведения (например, свойство деления, упомянутое выше), эти функции составляют эффективное представление типа данных.
Этот взгляд можно применить к другим типам данных, таким как кортежи, используемые для реализации рациональных чисел. Фактически, мы не будем говорить о том, что такое кортеж, а будем говорить об операторах, предоставляемых языком для управления и создания кортежей. Теперь мы можем описать условия поведения для кортежа, который обычно называют парой, которая имеет отношение к проблеме представления рациональных чисел.
Для реализации рациональных чисел нам нужна форма склеивания двух целых чисел, которая обладает следующим поведением:
p
состоит из x
и y
, то getitem_pair(p, 0)
возвращает x
, а getitem_pair(p, 1)
возвращает y
.Мы можем реализовать make_pair
и getitem_pair
, которые удовлетворяют этому описанию так же, как и кортежи:
>>> def make_pair(x, y):
"""Return a function that behaves like a pair."""
def dispatch(m):
if m == 0:
return x
elif m == 1:
return y
return dispatch
>>> def getitem_pair(p, i):
"""Return the element at index i of pair p."""
return p(i)
Используя эту реализацию, мы можем создавать и работать с парами:
>>> p = make_pair(1, 2)
>>> getitem_pair(p, 0)
1
>>> getitem_pair(p, 1)
2
Использование этих функций отличается от любого интуитивного представления о том, какими должны быть данные. Кроме того, эти функции удовлетворяют представлению составных данных в нашей программе.
Следует отметить одну тонкую деталь: значение, возвращаемое make_pair
, является функцией, называемой dispatch
, которая принимает параметр m
и возвращает x
или y
. Затем getitem_pair
вызывает эту функцию для получения соответствующего значения. Тема этой диспетчеризации функций будет обсуждаться неоднократно в этой главе.
Хотя функция представления пары не является фактическим механизмом работы Python (кортежи обеспечивают более прямой подход по соображениям производительности), она может работать таким образом. Хотя это представление функции не очевидно, оно представляет собой идеальный способ представления пар, потому что оно удовлетворяет единственному условию, которое должна удовлетворять пара. Этот пример также показывает, что способность работать с функциями как со значениями предоставляет нам возможность представлять составные данные.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )