Keywords: easytut

Далее: Определения функций Наверх: Курс языка Python для начинающих Назад: Выбор Содержание
В этой главе

- Что такое отладка?
- Что должна делать программа?
- Что делает программа?
- Как исправить программу?

# Отладка программ

# Что такое отладка?

> Как только мы начали программировать, к нашему удивлению, мы обнаружили, что оказалось не так просто писать правильные программы, как мы думали. Я помню точный момент, когда я понял, что значительная часть моей жизни, начиная с этого мгновения, будет потрачена на отыскивание ошибок в моих собственных программах.

> - Морис Вилкс открывает для себя отладку программ, 1949г.

К этому времени, если вы пытались программировать самостоятельно, вероятно, вы обнаружили, что иногда программа делает не то, что вы ожидали. Это вполне обычное явление. Отладка – это процесс понимания, что делает компьютер и затем принуждения его делать то, что хотите вы. Это может быть достаточно сложно. Однажды я потратил почти целую неделю, чтобы найти и устранить ошибку, которая произошла из-за того, что кто-то написал `x` вместо `y`.

Эта часть будет более абстрактной, чем предыдущие. Пожалуйста, сообщите мне, была ли она полезна для вас.

# Что должна делать программа?

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

ширина | длина | периметр
3 | 4 | 14
2 | 3 | 10
4 | 4 | 16
2 | 2 | 8
5 | 1 | 12

Я запускаю программу для всех начальных данных и проверяю, делает ли программа то, что я от нее ожидаю. Если нет, то необходимо понять, что же делает компьютер.

Чаще всего, для каких-то данных программа будет работать, а для каких-то – нет. В этом случае вы должны разобраться, что общего между теми начальными данными, для которых программа работает правильно. Например, вот результат работы программы для вычисления периметра (программа будет приведена ниже):

    Height: 3
    Width: 4
    perimeter =  15

    Height: 2
    Width: 3
    perimeter =  11

    Height: 4
    Width: 4
    perimeter =  16

    Height: 2
    Width: 2
    perimeter =  8

    Height: 5
    Width: 1
    perimeter =  8

Заметьте, что программа не работает для первых двух наборов данных, работает для следующих двух и не работает для последнего. Попробуйте понять, что общего между третьим и четвертым случаем. Если вы поймете, в чем проблема, становится легче найти причину. Для ваших программ попробуйте дополнительные данные, если вам это необходимо.

# Что делает программа?

Далее необходимо взглянуть на программу. Одна из самых важных вещей в программировании – умение читать программы. Основной способ для этого – просчет программы вручную.

Этот процесс начинается с первой строки и продолжается до конца программы. Циклы `while` и команды `if` означают, что некоторые команды, возможно, не выполнятся, а некоторые выполнятся много раз. Для каждой команды выясните, что сделал Python.

Начнем с простой программы вычисления периметра. Не набирайте ее, вы будете ее читать, а не запускать. Программа следует:

    height = input("Height: ")
    width = input("Width: ")
    print "perimeter = ",width+height+width+width

Вопрос: Какую команду Python выполняет первой?

Ответ: Первая строка всегда выполняется первой. В данном случае это: `height = input("Height: ")`

Вопрос: Что делает эта команда?

Ответ: Выводит `Height:` , ждет, пока пользователь напечатает число и сохраняет его в переменной height.

Вопрос: Какую команду Python выполняет следующей?

Ответ: Обычно, это следующая строка, которая в данном случае: `width = input("Width: ")`

Вопрос: Что делает эта команда?

Ответ: Выводит `Width:` , ждет, пока пользователь напечатает число и сохраняет его в переменной width.

Вопрос: Какую команду Python выполняет следующей?

Ответ: Если следующая строка начинается с той же позиции, что и предыдущая, то выполняется она. В нашем случае: `print "perimeter = ", width+height+width+width` (возможно, в этой строке произойдет вызов функции, но это мы рассмотрим в последующих главах).

Вопрос: Что делает эта команда?

Ответ: Сначала она выводит `perimeter =`, затем величину `width+height+width+width`.

Вопрос: А правильно ли вычисляет периметр выражение `width+height+width+width`?

Ответ: Периметр прямоугольника равен его нижняя сторона (width) плюс левая сторона (height) плюс верхняя сторона (width) плюс правая сторона (width, вот оно!). Последнее слагаемое должно быть height, а не width.

Вопрос: Понимаете, почему иногда периметр вычислялся правильно?

Ответ: Он вычислялся правильно, если длина и ширина были равны.

Следующая программа, которую мы будем просчитывать вручную, должна выводить пять точек на экран. Однако выводит она следующее:

    . . . .

А вот и программа:

    number = 5
    while number > 1:
        print ".",
        number = number - 1
    print

Эта программа более сложна для просчета вручную, так как в ней есть команды управления (блоки, начинающиеся не с первых позиций в строке). Начинаем.

Вопрос: Какая команда выполнится первой?

Ответ: Первая строка файла: `number = 5`.

Вопрос: Что делает эта команда?

Ответ: Записывает число 5 в переменную number.

Вопрос: Какая команда выполнится следующей?

Ответ: Следующая команда `while number > 1:`

Вопрос: Что делает эта команда?

Ответ: Команда `while` проверяет выражение, содержащееся в ней, и, если оно истинно, выполняет следующую команду в выделенном блоке, в противном случае пропускает весь следующий блок.

Вопрос: Итак, что же делает эта команда сейчас?

Ответ: Если выражение `number > 1` истинно, то будут выполнены следующие две команды.

Вопрос: А `number > 1` истинно?

Ответ: Последняя величина, содержащаяся в `number`, была `5`, `5 > 1`, поэтому да.

Вопрос: Какая команда выполняется следующей?

Ответ: Поскольку `while` истинно, следующая команда: `print ".",`

Вопрос: Что делает эта команда?

Ответ: Выводит одну точку; поскольку команда заканчивается запятой (,), следующая команда print продолжит печатать на той же строке без перехода на новую.

Вопрос: Какая команда выполняется следующей?

Ответ: `number = number – 1`, поскольку не появились никакие новые блоки (начинающиеся с другой позиции строки).

Вопрос: Что делает эта команда?

Ответ: Она вычисляет `number – 1`, то есть от текущего значения `number` (или 5) вычитает 1 и записывает результат в `number`. Иными словами, она меняет значение `number` с 5 на 4.

Вопрос: Какая команда выполняется следующей?

Ответ: Блок закончился (следующая строка начинается с первой позиции), необходимо вернуться к команде управления. Это цикл `while`, который выглядит так: `while number > 1:`

Вопрос: Что происходит в цикле?

Ответ: Величина `number`, то есть 4, сравнивается с 1. Поскольку `4 > 1`, цикл while продолжается.

Вопрос: Какая команда выполняется следующей?

Ответ: Поскольку условие в while было истинным, следующая команда: `print ".",`

Вопрос: Что делает эта команда?

Ответ: Выводит вторую точку на той же строке.

Вопрос: Какая команда выполняется следующей?

Ответ: Блок продолжается, поэтому следующая команда: `number = number – 1`.

Вопрос: А что она делает?

Ответ: Берет текущее значение number (4), вычитает из него 1, получая 3 и, наконец, записывает 3 как новое значение `number`.

Вопрос: Какая команда выполняется следующей?

Ответ: Поскольку мы снова дошли до конца блока (новая строка начинается с первой позиции), следующая команда: `while number > 1:`

Вопрос: Что делает эта команда?

Ответ: Сравнивает текущую величину number (3) с 1. `3 > 1`, поэтому цикл while продолжается.

Вопрос: Какая команда выполняется следующей?

Ответ: Условие в цикле while было истинным, поэтому следующая команда: `print ".",`

Вопрос: А что она делает?

Ответ: Выводит третью точку.

Вопрос: Какая команда выполняется следующей?

Ответ: `number = number – 1`

Вопрос: Что она делает?

Ответ: Берет текущее значение number (3), вычитает из него 1, получая 2 и, наконец, записывает 2 как новое значение `number`.

Вопрос: Какая команда выполняется следующей?

Ответ: Возвращаемся назад к условию цикла: `while number > 1:`

Вопрос: И что происходит далее?

Ответ: Сравнивается текущая величина `number` (2) с 1. `2 > 1`, поэтому цикл while продолжается.

Вопрос: Какая команда выполняется следующей?

Ответ: Поскольку цикл while продолжается: `print ".",`

Вопрос: Что делает эта команда?

Ответ: Она открывает смысл жизни. Я шучу. (Мне было необходимо убедиться, что вы еще не спите). Команда выводит четвертую точку.

Вопрос: Какая команда выполняется следующей?

Ответ: `number = number – 1`

Вопрос: Что делает эта команда?

Ответ: Берет текущее значение number (2), вычитает из него 1, получая 1 и, наконец, записывается 1 как новое значение number.

Вопрос: Какая команда выполняется следующей?

Ответ: Возвращаемся назад к условию цикла: `while number > 1:`

Вопрос: Что делает эта команда?

Ответ: Сравнивает текущую величину `number` (1) с 1. `1 > 1` – ложно (один не больше одного), поэтому цикл заканчивается.

Вопрос: Какая команда выполняется следующей?

Ответ: Поскольку условие цикла while ложно, пропускаем весь блок, следующая команда `print`

Вопрос: Что делает эта команда?

Ответ: Переводит печать на следующую строку.

Вопрос: Почему программа не печатает 5 точек?

Ответ: Цикл закончился на одну точку раньше.

Вопрос: Как это можно исправить?

Ответ: Заканчивать цикл на одну точку позже.

Вопрос: А как это сделать?

Ответ: Существует несколько способов. Один из них – изменить цикл while следующим образом: `while number > 0:` Другой способ изменить условие на `number >= 1:` Существуют и другие варианты.

# Как исправить программу?

Вам нужно понять, что делает программа. Также нужно понять, что программа должна делать. Выясните, в чем разница между этим. Отладка программ – это навык, который приходит с опытом. Если вы не можете сделать это примерно за час, отвлекитесь, обсудите проблему с кем-нибудь или посмотрите на себя в зеркало. Вернитесь к проблеме через некоторое время, скорее всего, у вас появятся новые соображения или идеи. Удачи вам.

Далее: Определения функций Наверх: Курс языка Python для начинающих Назад: Выбор Содержание