Пересмотреть решение по дизайну

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом разделе мы пересматриваем решение по дизайну, принятое ранее.

Это Guided Lab, который предоставляет пошаговые инструкции, чтобы помочь вам учиться и практиковаться. Внимательно следуйте инструкциям, чтобы выполнить каждый шаг и получить практический опыт. Исторические данные показывают, что это лабораторная работа уровня начальный с процентом завершения 83%. Он получил 100% положительных отзывов от учащихся.

Имена файлов versus Итерируемые объекты

Сравните эти два программы, которые возвращают один и тот же вывод.

## Предоставьте имя файла
def read_data(filename):
    records = []
    with open(filename) as f:
        for line in f:
         ...
            records.append(r)
    return records

d = read_data('file.csv')
## Предоставьте строки
def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

with open('file.csv') as f:
    d = read_data(f)
  • Какую из этих функций вы предпочитаете? Почему?
  • Какая из этих функций более гибкая?

Глубокая идея: "Duck Typing"

Duck Typing - это концепция компьютерного программирования для определения, может ли объект быть использован для определенной цели. Это приложение теста утки.

Если оно выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это утка.

Во второй версии read_data() выше функция ожидает любого итерируемого объекта. Не только строки файла.

def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

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

## CSV-файл
lines = open('data.csv')
data = read_data(lines)

## Архивированный файл
lines = gzip.open('data.csv.gz','rt')
data = read_data(lines)

## Стандартный ввод
lines = sys.stdin
data = read_data(lines)

## Список строк
lines = ['ACME,50,91.1','IBM,75,123.45',...]
data = read_data(lines)

В этом дизайне есть значительная гибкость.

Вопрос: Следует ли мы принимать или бороться с этой гибкостью?

Лучшие практики по дизайну библиотек

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

Упражнение 3.17: От имен файлов до объектов, подобных файлам

Теперь вы создали файл fileparse.py, в котором содержалась функция parse_csv(). Функция работала так:

>>> import fileparse
>>> portfolio = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>>

В настоящее время функция ожидает, что ей передадут имя файла. Однако вы можете сделать код более гибким. Измените функцию так, чтобы она работала с любым объектом, подобным файлу/итерируемым объектом. Например:

>>> import fileparse
>>> import gzip
>>> with gzip.open('portfolio.csv.gz', 'rt') as file:
...      port = fileparse.parse_csv(file, types=[str,int,float])
...
>>> lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
>>> port = fileparse.parse_csv(lines, types=[str,int,float])
>>>

В этом новом коде что произойдет, если вы передадите имя файла, как раньше?

>>> port = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>> port
... посмотрите на вывод (он должен быть странным)...
>>>

Да, вам нужно быть осторожными. Возможно, вы можете добавить проверку безопасности, чтобы избежать этого?

Упражнение 3.18: Исправление существующих функций

Исправьте функции read_portfolio() и read_prices() в файле report.py, чтобы они работали с модифицированной версией parse_csv(). Это должно потребовать только незначительных изменений. Затем ваши программы report.py и pcost.py должны работать так же, как и всегда.

Резюме

Поздравляем! Вы завершили лабораторную работу по обсуждению дизайна. Вы можете практиковаться в более многих лабораторных работах в LabEx, чтобы улучшить свои навыки.