Основы языка

Что это такое

Основы Python — это части, из которых сделана любая программа: значения нескольких встроенных типов, имена, которые просто указывают на них, условия, циклы, функции, отступы, которые задают блоки, и аргументы со значениями по умолчанию. Типы здесь привязаны к значениям, а не к именам, и проверяются во время выполнения; этого достаточно, чтобы написать законченную программу, а всё дальнейшее строится на этом.

Почему это важно

Проектные решения языка проявляются именно здесь и определяют всё остальное: отступы — часть синтаксиса, поэтому форматирование не вопрос вкуса, а код читается одинаково везде. Типы привязаны к значениям, поэтому одно имя может хранить строку, а позже целое число; однако за гибкость приходится платить — ошибки типов всплывают во время выполнения, а не при сборке; имена же — не коробки, а ссылки, поэтому два имени могут указывать на один изменяемый объект, и отсюда берётся целое семейство ошибок, которые становятся очевидны, как только модель понята.

Ключевые идеи

Имена указывают на значения

Присваивание привязывает имя к объекту, а не копирует объект, поэтому два имени могут ссылаться на один список, и изменение через одно видно через другое. Типы принадлежат объектам, а не именам: одно имя можно переиспользовать для значений разных типов, и именно поэтому проверяющему типы нужны аннотации в помощь.

a = [1, 2]
b = a          -> b — тот же список, что и a
b.append(3)    -> теперь a равно [1, 2, 3]

Неизменяемые и изменяемые значения ведут себя по-разному

Числа, строки и кортежи после создания изменить нельзя, а списки, словари и множества можно. Одни значения поэтому безопасно делить между частями программы и брать в качестве ключей словаря, а другие опасно передавать в функции, которые могут изменить их на месте. Там, где данные меняться не должны, выбор неизменяемого значения убирает целый класс неожиданностей.

Отступы — это структура блоков

Фигурных скобок нет: блок задаёт согласованный отступ, а смешивать табуляции с пробелами интерпретатор не разрешает и проверяет это сам. Отсюда следствие, которое действительно помогает читать незнакомый код: любой файл на Python отформатирован похожим образом.

Функции — объекты, а у аргументов две конвенции

Функция — такое же значение, как любое другое, и её можно передавать: на этом держатся ключи сортировки, обратные вызовы и декораторы. Аргументы передают по позиции или по имени, и им можно задавать значения по умолчанию — с известной ловушкой: изменяемое значение по умолчанию создаётся один раз и делится между вызовами, поэтому накапливается.

Исключения — канал ошибок, и они должны быть конкретными

Пока исключение не поймают, оно распространяется вверх по стеку вызовов, и обработчику нужна прежде всего информация о его типе. Перехват всего подряд скрывает и ошибки программиста, и ожидаемые отказы, поэтому ловите самый узкий возможный тип — тогда неожиданные проблемы остаются видны.

Контекстный менеджер — стандартный шаблон работы с ресурсами

Файлы, блокировки и соединения поддерживают блок with, который гарантирует очистку даже при исключении. Закрывать ресурс вручную на каждом пути тогда не нужно, и потому это ожидаемая форма, а не украшение.

Практика

Покажите модель ссылок

Создайте список, присвойте его второму имени, измените через второе имя, а затем повторите опыт с кортежем.

Готово, когда: вы можете объяснить, почему список изменился, а кортеж вызвал ошибку.

Напишите функцию с безопасным значением по умолчанию

Напишите функцию с необязательным аргументом-списком, вызовите её дважды без аргумента и посмотрите на накопившийся результат; затем исправьте значение по умолчанию.

Готово, когда: два последовательных вызова без аргумента дают одинаковый результат.

Частые ошибки

  • Изменяемое значение по умолчанию — значение разделяется между вызовами и накапливается; исправить: используйте по умолчанию None и создавайте значение внутри.
  • Уверенность, что присваивание копирует — два имени делят один объект; исправить: копируйте намеренно, когда копия нужна.
  • Перехват всех исключений — ошибки программиста скрываются вместе с ожидаемыми отказами; исправить: ловите самый узкий полезный тип.
  • Открытие файла без контекстного менеджера — на пути ошибки закрытие пропускается; исправить: используйте with.
  • Расчёт на то, что у переменной есть тип — ошибка появляется только при исполнении этой строки; исправить: аннотируйте типы и проверяйте их на границах.

Что читать дальше