1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-sicp-py-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
2.2.md 8.3 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 03:42 9c9d71c

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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-sicp-py-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-sicp-py-zh.git
oschina-mirror
wizardforcel-sicp-py-zh
wizardforcel-sicp-py-zh
master