LANG·I Язык Глава 1 из 65
Первая программа и первая ошибка
Глава-журнал: пишем первые строки на Python, считаем, ломаем и учимся читать жалобы машины. Начнём с программы 1843 года, в которой уже была ошибка.
Язык
- 01 Первая программа вы здесь
- 02 Переменные
- 03 Условия
- 04 Циклы
- 05 Функции
- 06 Списки
- 07 Строки
- 08 Словари
- 09 Рекурсия
- 10 Функции-значения
- 11 Ошибки и тесты
- 12 Объекты
Опирается на: 00 · Что умеет программа
Что вы унесёте из главы
- печатать текст и числа, считать на Python как на калькуляторе
- читать сообщение об ошибке снизу вверх и находить строку, где всё сломалось
- отличать ошибку, о которой Python кричит, от ошибки, о которой он молчит
В конце прошлой главы мы обещали красный текст. Он появится уже на этой странице, и не раз. Чтобы он не пугал, заведём привычку инженеров, которые работали с первыми вычислительными машинами: всё, что пошло не так, записываем в журнал. Глава так и устроена, запись за записью.
Внизу страницы есть и ваш собственный журнал. Он заполняется сам: каждая ошибка, которую вы встретите в ячейках этой главы, попадает туда с временем и номером строки. К концу главы в нём наверняка наберётся несколько записей, и это хороший знак.
Запись первая. 1843 год: ошибка в первой программе
Ниже — первые семь операций программы Лавлейс. Колонны машины обозначены $V_1, V_2, \ldots$, по-нынешнему это переменные. Программа считает число Бернулли для $n = 4$; первые операции готовят дробь $-\frac12 \cdot \frac{2n-1}{2n+1}$. Нажимайте «Шаг» и следите, как числа переходят из колонны в колонну.
В четвёртой операции делимое и делитель стоят наоборот: напечатано $V_5 \div V_4$, то есть $\frac{2n+1}{2n-1}$, а нужно $V_4 \div V_5$. Машина, будь она построена, не заметила бы подвоха. Она послушно поделила бы девять на семь вместо семи на девять и дальше считала бы с неверным числом, не моргнув ни одной шестерёнкой.
Похоже на опечатку: в соседнем столбце той же таблицы, где расписан ожидаемый результат, дробь записана правильно. Только машина пояснений не читает, она исполняет таблицу. Урок первой записи: машина делает то, что написано, а не то, что вы имели в виду.
Запись вторая. Машина говорит
Нашу машину, к счастью, построили, и она понимает язык Python. Простейшая программа на нём просит машину что-нибудь сказать:
Слово print — это команда «напечатай», в скобках — что именно. Текст берут в кавычки, двойные или одинарные, лишь бы одинаковые с двух сторон: так Python понимает, где текст начинается и где кончается. Текст в кавычках программисты называют строкой.
Команд может быть много. Python выполняет их сверху вниз, строку за строкой, как вы читаете эту страницу. Нажмите «Шаги» под следующей программой и проследите, как он идёт по ним.
Во второй команде print получил несколько значений через запятую и напечатал их в одну строку через пробел. А 4 там без кавычек, и для Python это число. Скоро мы об эту разницу споткнёмся.
Запись третья. Калькулятор
Python считает лучше калькулятора: в целых числах он не теряет ни одной цифры. Знаки привычные: +, -, * (умножить), / (разделить), ** (степень). Есть ещё два, которых нет на калькуляторе: // — деление нацело, сколько раз помещается, и % — остаток от деления.
Дробная часть отделяется точкой, а не запятой: 3.5. Запятая в Python разделяет значения — вспомните print("Два", "три", 4). Если написать print(3,5), Python напечатает два числа, три и пять.
Порядок действий — школьный: сначала степень, потом умножение и деление, потом сложение и вычитание; скобки меняют порядок. Проверьте себя.
Что напечатает print(2 + 3 * 4 ** 2)?
Сначала степень: $4^2 = 16$. Потом умножение: $3 \cdot 16 = 48$. Потом сложение: $2 + 48 = 50$. Проверьте разбор в машине ниже — она показывает каждый шаг.
+ - * / // % **. Машина покажет, в каком порядке Python его вычисляет.Попробуйте в машине порядка 2 ** 3 ** 2 и -2 ** 2. Оба ответа удивляют: степени считаются справа налево (сначала $3^2 = 9$, потом $2^9 = 512$), а минус перед числом слабее степени, поэтому -2 ** 2 — это $-(2^2) = -4$. Когда сомневаетесь, ставьте скобки: лишние ничего не стоят.
Запись четвёртая. Красный текст
Теперь сломаем что-нибудь нарочно. В этой программе не закрыта кавычка. Запустите её.
Python даже не начал выполнять программу: он не смог её прочитать. Это SyntaxError, синтаксическая ошибка: нарушены правила записи, как в предложении, которое из-за опечатки потеряло смысл. Python показывает строку, где споткнулся, и ставит под ней значок ^. Строка подсвечена и в самом коде.
Одно правило сэкономит вам много времени: если в отмеченной строке всё выглядит правильно, смотрите на строку перед ней. Python отмечает место, где перестал понимать текст, а ошибиться можно и раньше. Про незакрытую скобку Python 3.13 обычно говорит прямо, '(' was never closed, и показывает строку, где она открылась. Python до версии 3.10 замечал её только на следующей строке, когда понимал, что выражение так и не кончилось.
Поиск ошибок по-русски называют отладкой, а по-английски — debugging, «обезжучивание». Наши ошибки обычно не летают, но ищут их тем же методом: смотрят, где именно машина сломалась, и думают почему.
Запись пятая. Анатомия трейсбека
Не все ошибки видны при чтении. Бывает, что программа записана правильно, Python начинает её выполнять — и спотыкается на полпути. Тогда он печатает трейсбек — отчёт о том, где и почему остановилась программа.
Первые две строки выполнились — их результат в выводе. На третьей программа упала. Сообщение об ошибке читают снизу вверх: в последней строке — что случилось, выше — где.
Вот ошибки, которые чаще всего встречаются в начале пути. Заучивать их не нужно. Достаточно знать, что у каждой есть имя и оно подсказывает, где искать.
| Ошибка | Что случилось | Пример |
|---|---|---|
SyntaxError | Программа записана с нарушением правил | print("а) |
IndentationError | Лишний или недостающий отступ в начале строки | print(1) |
NameError | Python не знает такого имени: опечатка или его ещё нет | prnt(1) |
TypeError | Действие не подходит к типу: текст плюс число | "год " + 1843 |
ZeroDivisionError | Деление на ноль | 1 / 0 |
Коварнее всех TypeError со сложением строки и числа. Для Python "1843" в кавычках и 1843 без кавычек — разные вещи: первое состоит из четырёх символов, второе — число. Сложить их он отказывается, потому что не знает, чего вы хотите: склеить тексты или сложить числа. Подробнее о типах — в следующей главе.
Запись шестая. Ошибка, о которой Python молчит
Красный текст — хорошая новость: машина нашла проблему и показала на неё пальцем. Хуже, когда программа отрабатывает без единой жалобы и выдаёт неправильный ответ. Ошибка Лавлейс была из таких: машина спокойно посчитала бы неверное число.
Вот программа, которая должна найти среднее двух чисел, 4 и 6. Ответ, очевидно, 5. Запустите.
Python напечатал 7.0 и ничуть не смутился. Он сделал то, что написано: по правилам порядка действий сначала разделил b на два, потом прибавил a. Исправьте программу сами — вы уже знаете как.
Трейсбека здесь не будет. Выручает привычка проверять ответ на примере, который вы знаете заранее: среднее четырёх и шести должно быть пять, минут в сутках — 1440. В главе 11 эта привычка превратится в инструмент, автоматические тесты. Так же работает сервер, который проверяет задачи этого курса: он запускает вашу программу на примерах с известным ответом.
Ваш журнал
Вот что накопилось в вашем журнале, пока вы читали. Ниже — пять сломанных программ. У каждой своя поломка: четыре Python покажет сам, одну придётся найти без его помощи. Пока будете чинить, журнал пополнится.
Программа должна напечатать Привет, мир!, но Python её даже не читает.
Посмотрите, где начинается строка и где она должна кончаться.
Не хватает закрывающей кавычки: print("Привет, мир!").
Программа должна напечатать Здравствуйте, Ада.
Последняя строка трейсбека называет имя, которого Python не знает. Сравните его с именем в первой строке.
В имени переставлены буквы: nmae вместо name. Подсказки Did you mean, как в трейсбеке с greting, здесь не будет: для короткого имени две переставленные буквы — для Python уже слишком большая разница, и сравнивать имена приходится самим.
Программа должна напечатать Программа Ады опубликована в 1843 году.
Python не складывает текст с числом. Как напечатать несколько значений в одну строку, не склеивая их плюсом?
Вспомните print("Два", "три", 4) — запятые.
Проще всего поставить запятые: print("Программа Ады опубликована в", year, "году"), print сам поставит пробелы. Можно и превратить число в текст: str(year) — об этом в следующей главе.
Программа должна напечатать две строки: Начало и Конец.
Пробелы в начале строки для Python не украшение. Где им здесь не место?
Вторая строка начинается с четырёх пробелов. В Python отступ означает «эта строка вложена в предыдущую команду», а print ничего в себя не вкладывает. Уберите пробелы. Зачем нужны отступы, вы узнаете в главе 3.
Программа должна напечатать, сколько минут в сутках. Python ни на что не жалуется, но ответ неверный.
Сколько минут в одном часе?
В часе 60 минут, а не 6: print(24 * 60) печатает 1440. Такие ошибки находят, только сверяя ответ с тем, что знаешь заранее.
Куда дальше
Наши программы пока похожи на шарманку: каждый раз играют одну и ту же мелодию. Они не запоминают посчитанное, чтобы пустить его в дело позже, и ничего не спрашивают у человека. Чтобы программа запомнила число и узнала, как вас зовут, нужны имена для значений. Тут нас ждёт первый фокус: имя в Python устроено совсем не так, как кажется. Об этом глава 2.