Выбрать главу

Повышение читаемости кода среди питонистов ценится гораздо выше, чем увеличение объема на несколько байт (в случае двух-выражений-print-в-одной-строке) или увеличение времени вычисления на несколько миллисекунд (в случае нескольких-условий-в-отдельных-строках). Кроме того, когда группа разработчиков вносит изменения в открытый код, историю изменений хорошего кода проще расшифровать, поскольку изменение в одной строке может воздействовать только на одно выражение.

Ошибки никогда не должны замалчиваться/Если не замалчиваются явно

Обработка ошибок в Python выполняется с помощью выражения try. Пример из пакета HowDoI (более подробно описывается в разделе «HowDoI» в главе 5) Бена Глейтсмана (Ben Gleitzman) показывает, когда замалчивать ошибки приемлемо:

def format_output(code, args):

····if not args['color']:

········return code

····lexer = None

····# попробуем отыскать лексеры с помощью тегов Stack Overflow

····# или аргументов query

····for keyword in args['query'].split() + args['tags']:

········try:

············lexer = get_lexer_by_name(keyword)

············break

········except ClassNotFound:

············pass

····# лексер не найден, пробуем угадать

····if not lexer:

········lexer = guess_lexer(code)

····return highlight(code,

····················lexer,

····················TerminalFormatter(bg='dark'))

Перед вами часть пакета, который предоставляет сценарий командной строки, позволяющий найти в Интернете (по умолчанию на сайте Stack Overflow) способ выполнить задачу по программированию. Функция format_output() подсвечивает синтаксис, просматривая теги вопроса на предмет строки, которую смог разобрать лексер (также он называется токенайзером; теги python, java или bash позволят определить лексер, который нужно использовать для разбиения и подсвечивания кода), а затем, если он даст сбой, пробует определить язык по самому коду. Когда программа достигает оператора try, она может пойти по одному из трех путей:

• поток выполнения входит в блок try (весь код, расположенный между try и except), лексер успешно определяется, цикл прерывается, и функция возвращает код, подсвеченный с помощью выбранного лексера;

• лексер не найден, генерируется и обрабатывается исключение ClassNotFound — и ничего не происходит. Цикл продолжит выполнение до тех пор, пока не завершится самостоятельно или не будет найден лексер;

• генерируется какое-то другое исключение (например, KeyboardInterrupt), которое не обрабатывается и поднимается на верхний уровень, останавливая выполнение.

Часть афоризма «не замалчиваются» препятствует чрезмерному выявлению ошибок. Рассмотрим пример (можете попробовать запустить его в отдельном окне консоли — так будет проще прервать выполнение, когда вы во все вникнете):

>>> while True:

… ····try:

… ········print("nyah", end=" ")

… ····except:

… ········pass

Или не пробуйте запускать его. Поскольку для блока except не указано конкретное исключение, он будет отлавливать все исключения, в том числе KeyboardInterrupt (Ctrl+C в консоли POSIX), и игнорировать их. Соответственно, он проигнорирует множество ваших попыток прервать его работу. Это не просто проблема с прерываниями — блок except также может скрывать ошибки, что вызовет проблемы в будущем (их станет трудно диагностировать). Поэтому не замалчивайте ошибки: всегда явно указывайте имена исключений, которые хотите поймать, и обрабатывайте только их. Если вы хотите просто записать в журнал или как-то еще убедиться в наличии исключения и вызвать его повторно, как в следующем сниппете, тогда все в порядке. Только не замалчивайте ошибки (не обрабатывая их и не вызывая повторно):

>>> while True:

… ····try:

… ········print("ni", end="-")

… ····except:

… ········print("An exception happened. Raising.")

… ········raise

Аргументы функций должны быть интуитивно понятными

Ваш выбор при дизайне API определит последующую возможность взаимодействовать с функцией. Аргументы можно передавать в функции четырьмя разными способами.

Позиционные аргументы обязательны и не имеют значений по умолчанию.

Аргументы с ключевым словом необязательны и имеют значения по умолчанию.