Перед вами часть пакета, который предоставляет сценарий командной строки, позволяющий найти в Интернете (по умолчанию на сайте 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 определит последующую возможность взаимодействовать с функцией. Аргументы можно передавать в функции четырьмя разными способами.
Позиционные аргументы обязательны и не имеют значений по умолчанию.
Аргументы с ключевым словом необязательны и имеют значения по умолчанию.
Список с произвольным количеством аргументов необязателен и не имеет значений по умолчанию.
Словарь с произвольным количеством аргументов с ключевым словом необязателен и не имеет значений по умолчанию.
Рассмотрим, когда можно использовать каждый метод передачи аргументов.
• Позиционные аргументы. Применяйте этот метод, когда у вас всего несколько аргументов для функции, которые являются частью ее значения и имеют правильный порядок. Например, пользователь без труда вспомнит, что у функций send(message, recipient) или point(x, y) должны быть два аргумента, а также порядок этих аргументов.
Антишаблон: при вызове функций можно поменять местами имена аргументов, например так: send(recipient="World", message="The answer is 42.") и point(y=2, x=1). Это снижает читаемость. Используйте более понятные вызовы send("The answer is 42", "World") и point(1, 2).
• Аргументы с ключевым словом. Когда функция имеет более двух или трех позиционных параметров, ее сигнатуру сложнее запомнить. В этом случае можно применить аргументы с ключевым словом, которые имеют значения по умолчанию. Например, более полная версия функции send может иметь сигнатуру send(message, to, cc=None, bcc=None). Здесь параметры cc и bcc являются необязательными и равны None, если для них не получено значение.
Антишаблон: можно отправить аргументы в правильном порядке, но не указывать их имена явно, например send("42", "Frankie", "Benjy", "Trillian"), переслав скрытую копию пользователю с именем Триллиан. Можно также передать именованные аргументы в неправильном порядке, например send("42", "Frankie", bcc="Trillian", cc="Benjy"). Если у вас нет веской причины делать это, лучше всего использовать вариант, приближенный к определению функции: send("42", "Frankie", cc="Benjy", bcc="Trillian").
Никогда лучше, чем сейчас