Программирование и научные вычисления на языке Python/§3

В следующих двух уроках мы познакомимся с основными конструкциями программирования: циклами while и for, if-else-ветвлениями и функциями, определяемыми самими пользователями. Все это будет использоваться практически в любой программе. Цель нашей следующей программы - развить наш предыдущий пример о двух температурных шкалах и напечатать на экране таблицу с градусами Цельсия в первом столбце и соответствующими им градусами Фаренгейта во втором столбце:

-20 -4.0 -15 5.0 -10 14.0 -5 23.0 0 32.0 5 41.0 10 50.0 15 59.0 20 68.0 25 77.0 30 86.0 35 95.0 40 104.0

## Наивный подход

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

```
C = -20; F = 9.0/5*C + 32; print C, F
C = -15; F = 9.0/5*C + 32; print C, F
C = -10; F = 9.0/5*C + 32; print C, F
C = -5; F = 9.0/5*C + 32; print C, F
C = 0; F = 9.0/5*C + 32; print C, F
C = 5; F = 9.0/5*C + 32; print C, F
C = 10; F = 9.0/5*C + 32; print C, F
C = 15; F = 9.0/5*C + 32; print C, F
C = 20; F = 9.0/5*C + 32; print C, F
C = 25; F = 9.0/5*C + 32; print C, F
C = 30; F = 9.0/5*C + 32; print C, F
C = 35; F = 9.0/5*C + 32; print C, F
C = 40; F = 9.0/5*C + 32; print C, F
```

и после запуска получить:

`
-20 -4.0
-15 5.0
-10 14.0
-5 23.0
0 32.0
5 41.0
10 50.0
15 59.0
20 68.0
25 77.0
30 86.0
35 95.0
40 104.0
`

Форматирование выглядит криво, но его собственно как такого и не осуществлялось и ситуацию легко изменить с помощью printf-форматирования, что мы покажем далее. Но основная проблема заключается в другом - в том, что нам приходится множество раз повторять идентичные выражения, в то время как компьютер создан как раз для автоматизации скучной работы. В общем, нам пора узнать о циклах (loops) и их двух реализациях в Python: циклах while и циклах for.



## Цикл while

Цикл while используется для того, чтобы повторять заданные наборы инструкций столько раз, сколько условие сохраняет истину. Проиллюстрируем это на примере. Задача состоит в создании строк таблицы из значений C и F. Первое значение C равно -20 и с шагом 5 оно движется в сторону роста С пока С ≤ 40. Для каждого C считается соответствующее значение F и так записываются две температуры. Записать все сказанное словами в виде кода можно, например, так:



```
print '------------------' # верхняя линия таблицы
C = -20 # начальное значение C
dC = 5 # инкремент для C в цикле
while C <= 40: # заголовок цикла с условием
F = (9.0/5)*C + 32 # 1ая инструкция цикла
print C, F # 2ая инструкция цикла
C = C + dC # 3ья инструкция цикла
print '------------------' # нижняя линия (после цикла)
```


Уже сейчас стоит рассмотреть в прямом смысле слова незаметную, но очень важную часть языка Python - отступы. Как мы видим, после того как мы объявили блок while, задали условие и поставили двоеточие, весь следующий текст записан с определенным отступом. Ширина этого отступа, которой следует придерживаться, равна четырем пробелам.

Многие начинающие программисты Python забывают ставить двоеточие в конце строки с while - это двоеточие существенно и показывает, что начинается блок инструкций цикла. Немногим позже мы увидим, что имеется множество схожих конструкций, открывающихся двоеточием.

Программисты должны полностью понимать, что происходит в программе и быть готовы дать тот же ответ, что и программа еще до того как она запущена. Давайте обсудим, что происходит в этом коде. Вначале, мы определяем начальное значение температуры в градусах Цельсия: С = -20. Также мы определяем инкремент dC, чтобы добавлять его к C в цикле. Затем мы начинаем цикл с условием С ≤ 40. В первый момент C = -20, -20 ≤ 40, условие выполняется. Пока условие выполняется, цикл выполняет заложенные в нем действия. То есть считает соответствующее F, печатает две температуры и добавляет dC к C.

После этого совершается второй проход по циклу. Вначале мы проверяем правило цикла: теперь С = -15, но выражение все еще остается истинным: -15 ≤ 40. Поэтому выполняются все те же инструкции, следующие после двоеточия. И так до тех пор пока выражение С ≤ 40 истинно. А ложным оно может стать лишь тогда, когда С > 40.



### Немного об инкременте

Новичков в программировании иногда смущает следующее выражение:

```
C = C + dC
```

Эта строка выглядит некорректно с точки зрения математики, но как программный код не вызывает никаких нареканий, поскольку вначале происходят какие-то действия с правой стороны от знака равенства, а потом уже они присваиваются переменной слева. В нашем случае складываются C и dC, два объекта типа int. Эта операция дает тоже объект типа int и уже он присваивается переменной C. А объект, связанный с этим именем ранее в памяти освобождается, поскольку на него более не ссылается ни одно имя.

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



```
C += dC # то же, что C = C + dC
C -= dC # то же, что C = C - dC
C *= dC # то же, что C = C * dC
C /= dC # то же, что C = C / dC
```



### Логические выражения

В нашем примере с циклом while мы использовали условие записанное как C <= 40, которое принимает значения True (истина) или False (ложь). В зависимости от задачи, вы можете использовать и другие условия проверки:



```
C == 40 # C равно 40
C != 40 # C не равно 40
C <> 40 # второй вариант записи C не равно 40
C >= 40 # C больше или равно 40
C > 40 # C больше 40
C < 40 # C меньше 40
```


Сравниваться могут не только числа. Возможно любое *логическое* (*булево*) сравнение. Также перед выражением может быть поставлено слово not для изменения True на False и наоборот. Также возможно комбинировать булеву логику, как например:



```
while x > 0 and y <= 1:
print x, y
```


Здесь, только пока оба выражения истинны, будут печататься x, y. В любом обратном случае цикл завершается. Эта функция называется "логическое и". Более "мягкий" подход - "логическое или" (or), для которого выражение принимает истинное значение, когда хотя бы одно из сравнений дает истину:



```
while x > 0 or y <= 1:
print x, y
```


Вот несколько примеров в интерактивном режиме, чтобы потренироваться на логических выражениях и быть с ними более аккуратными, чем это бывает обычно:



```
>>> x = 0; y = 1.2
>>> x >= 0 and y < 1
False
>>> x >= 0 or y < 1
True
>>> x > 0 or y > 1
True
>>> x > 0 or not y > 1
False
>>> -1 < x <= 0 # -1 < x and x <= 0
True
>>> not (x > 0 or y > 0)
False
```

## Списки

До этого момента все наши переменные могли содержать только одно число, будь оно хоть целым (int), хоть с плавающей точкой (float), хоть комплексным (complex) объектом. Но иногда числа естественным образом группируются. Например, градусы шкалы Цельсия в нашем первом столбце вполне представляют из себя группу. Для групп в Python есть специальный тип объектов - list (список), который позволяет организовывать эти группы в последовательности. При этом, с помощью списков мы можем работать как с группой целиком, так и с членами этой группы по отдельности. При этом список может состоять из объектов разного типа, в том числе и из самих списков, что как мы увидим далее, может быть очень удобным.

Для того чтобы создать список чисел из первого столбца нашей таблицы, нам следует записать их через запятую в квадратных скобках, вот так:



```
C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
```


Есть, кстати, и более элегантный способ, но не будем забегать вперед. Теперь наша переменная C ссылается на объект типа list, который содержит последовательность 13 элементов. Все элементы в этом случае являются int-объектами.

Любой элемент в списке связан со своим индексом, который определяет позицию элемента в списке. Первый элемент имеет индекс 0, второй элемент - индекс 1 и так далее. Таким образом в списке C имеется 13 элементов с индексами от 0 до 12. Для того, чтобы вызвать какой-то элемент списка, достаточно вызвать его по индексу, например C[3], если мы хотим вызывать -5.

Элементы в списках можно удалять, добавлять, изменять, вставлять и так далее. Делается это с помощью методов. Обратите внимание на эту концепцию, она встретится нам не раз. Методы определяются через точку. Например метод append для нашего списка C запишется как C.append(v), и этот метод добавит элемент *v* в конец списка С. А метод C.insert(i,v) вставит новый элемент *v* на позицию *i*. В интерактивном режиме выглядит это так:



```
>>> C = [-10, -5, 0, 5, 10, 15, 20, 25, 30] # создаем список
>>> C.append(35) # добавляем в конец новый элемент
>>> C # смотрим список
[-10, -5, 0, 5, 10, 15, 20, 25, 30, 35]
>>> C = C + [40, 45] # способ соединения списков
>>> C
[-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
```


Но заметим, что, как мы уже знаем, в последнем случае был создан новый список. Сами элементы можно было вставить куда угодно, как мы сейчас сделаем с помощью метода C.insert():



```
>>> C.insert(0, -15) # вставить новый элемент -15 с индексом 0
>>> C
[-15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
```


С помощью del C[i] мы можем удалять любые элементы, с помощью len(C) считать число элементов. Метод C.index(v) позволяет определить под каким индексом расположен интересующий нас элемент.



```
>>> del C[2] # удалить третий элемент
>>> C
[-15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
>>> del C[2] # удалить то, что теперь третий элемент
>>> C
[-15, -10, 5, 10, 15, 20, 25, 30, 35, 40, 45]
>>> len(C) # длина списка
11
>>> C.index(10)
3
```


Для того, чтобы просто узнать имеется ли какой-то элемент в списке используется команда in:



```
>>> 10 in C # есть ли среди элементов C число 10?
True
```


Кроме всего прочего Python поддерживат отрицательные индексы. Например, в списке C последний элемент может быть обозначен как С[-1], предпоследний как C[-2] и так далее:



```
>>> C[-1]
45
>>> C[-2]
40
```


Также с помощью списков можно сделать компактное присвоение элементов переменным. Например:



```
>>> somelist = ['book.tex', 'book.log', 'book.pdf']
>>> texfile, logfile, pdf = somelist
>>> texfile
'book.tex'
>>>' logfile
'book.log'
>>> ' pdf
'book.pdf'
```


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

Заметим, напоследок, различие в *функциях* и *методах*. Например, C.append(e) является методом, а len(C) - функцией. Как можно заметить просто визуально, методы записываются через точку. Эта их "префиксность" показывает, что они относятся только к объекту такого типа и производятся только над конкретным экземпляром. Функции же как правило, могут быть использованы для различных типов объектов. При этом каких-то особенных различий в действиях нет. То есть методы по сути те же функции, но записываемые привязано к объекту.



## Цикл for

Обычно действия, которые мы производим над одним элементом какой-то последовательности, мы хотели бы произвести и над всеми элементами. Для этого в языках программирования имеется специальная конструкция, называемая цикл for (for loop). Давайте сразу начнем с примера:



```
degrees = [0, 10, 20, 40, 100]
for C in degrees:
print 'list element: ', C
print 'The degrees list has', len(degrees), 'elements'
```


Предложение for C in degrees создает цикл для всех элементов списка degrees. При каждом проходе по циклу переменная C действует как курсор - берет соответствующий элемент из списка degrees, начиная с degrees[0] и подставляет в инструкцию цикла. Потом то же делает с degrees[1] и так далее до degrees[n-1], где n - число элементов в списке, которое мы можем определить функцией len(degrees), что и делаем по окончании цикла.

Заголовок цикла for аналогично заголовку цикла while заканчивается двоеточием, после которого следует тело цикла с отступами в 4 пробела. В данном случае в теле цикла всего одна инструкция.

В итоге на экране видим:



```
list element: 0
list element: 10
list element: 20
list element: 40
list element: 100
The degrees list has 5 elements
```



### Делаем таблицу

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



```
Cdegrees = [-20, -15, 10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
for C in Cdegrees:
F = (9.0 / 5) * C + 32
print C, F
```


Инструкция print C, F просто печатает значения C и F, а мы бы хотели создать форматированный вывод. Тогда, используя printf-форматирование, запишем окончательный вариант:



```
Cdegrees = [-20, -15, 10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
print ' C F'
for C in Cdegrees:
F = (9.0 / 5) * C + 32
print '%5d %5.1f' % (C, F)
```



## Альтернативные возможности

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

### for как while

Любой for цикл может быть записан как цикл while. В общем случае for-цикл:



```
for element in somelist:
<process element>
```


может быть преобразован в while:



```
index = 0
while index < len(somelist):
element = somelist[index]
<process element>
index += 1
```


В том числе и наш пример:

```
Cdegrees = [-20, -15, 10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
index = 0
print ' C F'
while index < len(Cdegrees):
C = Cdegrees[index]
F = (9.0 / 5) * C + 32
print '%5d %5.1f' % (C, F)
index += 1
```



### Столбцы в виде списков

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

```
Cdegrees = [-20, -15, 10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
Fdegrees = 
for C in Cdegrees:
F = (9.0 / 5) * C + 32
Fdegrees.append(F)
```


И если мы после этого распечатаем список Fdegrees, то получим:

```
[-4.0, 5.0, 14.0, 23.0, 32.0, 41.0, 50.0, 59.0, 68.0, 77.0, 86.0, 95.0, 104.0]
```

### Циклы со списком индексов

Вместо цикла for по заданным элементам списка мы можем использовать цикл for с генерированным списком индексов. Для этого в Python есть функция range, возвращающая список по порядку идущих чисел:

- range(n) возвращает список [0, 1, 2, ..., n-1]
- range(start, stop, step) возвращает список [start, start+step, start+2*step, ..., start+(n-1)*step], то есть число stop не включается в список, как и ранее. Например, range(2, 8, 3) дает [2, 5]; range(1, 11, 2) возвращает [1, 3, 5, 7, 9].
- range(start, stop) то же самое, что range(start, stop, 1).

Таким образом, рассмотренный цикл for может быть записан и так:



```
Cdegrees = range(-20, 45, 5)
Fdegrees = [0.0]*len(Cdegrees) # list of 0.0 values
for i in range(len(Cdegrees)):
Fdegrees[i] = (9.0/5)*Cdegrees[i] + 32
```


Заметим, что в этом примере мы инициализировали Fdegrees списком длиной len(Cdegrees), в котором все элементы равны нулю. Иначе, если бы мы создали пустой список Fdegrees = [], обращение Fdegrees[i] дало бы ошибку, поскольку список пуст, и мест нет.



## Еще о списках

### Изменение

Сейчас мы могли бы предложить два способа того как можно изменять элементы списка, например:



```
for c in Cdegrees:
c += 5
```


и этот цикл ничего не изменяет, в то время как



```
for i in range(len(Cdegrees)):
Cdegrees[i] += 5
```


работает исправно. Что же не так с первым циклом? Проблема в том, что *с* в первом случае это всего лишь переменная, которая ссылается на элемент списка, и когда мы к этой переменной применяем выражение c += 5, мы изменяем переменную, но не цикл. То есть, как говорилось ранее, можно представлять такого рода переменные как курсоры, а действие над указателем не изменяет объект. Показать, что происходит, можно на примере первых двух проходов по циклу:



```
c = Cdegrees[0]
c += 5
c = Cdegrees[1]
c += 5
```


Как видно отсюда, переменная *c* может быть использована только для чтения элементов, но не для их изменения. Только присваивание вида:



```
Cdegrees[i] = ...
```


изменяет элемент списка. Существует возможность совмещения действий с индексами и элементами, например, цикл



```
for i, c in enumerate(Cdegrees):
Cdegrees[i] = c + 5
```


добавляет число 5 к каждому элементу списка.



### Генерация

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



```
newlist = [E(e) for e in list]
```


где E(e) представляет собой выражение с элементом e. Вот три примера:



```
Cdegrees = [-5 + i*0.5 for i in range(n)]
Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees]
C_plus_5 = [C+5 for C in Cdegrees]
```



### Двойной проход (zip)

Мы можем использовать списки Cdegrees и Fdegrees для того, чтобы получить таблицу. Для этого мы должны пройти по обеим последовательностям. Конструкция for element in list в этом случае уже не очень удобна, поскольку она извлекает элементы только из одного списка. Поскольку мы знаем, что в каждом списке одно и то же число элементов, можно поступить например так:



```
for i in range(len(Cdegrees)):
print '%5d %5.1f' % (Cdegrees[i], Fdegrees[i])
```


Такая задача - о том как одновременно пройти по двум и более спискам встречается довольно часто. В Python для этого есть свое элегантное решение:



```
for e1, e2, e3, ... in zip(list1, list2, list3, ...):
# работаем с e1 из list1, e2 из list2 и т.д.
```


Функция zip собирает из n списков (list1, list2, list3, ...) один список из n-последовательностей (*кортежей*). Теперь каждая переменная e1, e2, e3 и т. д. служит своеобразным курсором для своей последовательности и двигаются параллельно. Цикл останавливается как только достигается конец самого короткого списка. Разъясним применение zip на нашем примере с таблицей из двух списков Cdegrees и Fdegrees:



```
for C, F in zip(Cdegrees, Fdegrees):
print '%5d %5.1f' % (C, F)
```


Заметно, что этот подход более естественен, чем конструкции вида for i in range(len(Cdegrees)).

### Вложение

В нашей таблице мы используем отдельный список для каждого столбца. Если нам будет нужно n столбцов, то потребуется и n списков. Однако, обычно мы представляем себе какую-то таблицу как единое целое, а не как ряд столбцов или строк. Значит, будет и более естественно использовать единый аргумент для всей таблицы. Для этого можно использовать вложенные списки:



```
Cdegrees = range(-20, 41, 5) # -20, -15, ..., 35, 40
Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees]
table = [Cdegrees, Fdegrees]
```


Стоит заметить, что индексация к определенному элементу организуется также. То есть, чтобы обратиться к первому списку, мы напишем table[0], а чтобы обратиться к третьему элементу этого списка, мы приставляем следующий индекс table[0][2]. Все это органично входит в концепцию объектов - table[0] это тоже объект и его можно индексировать как любой объект, содержащий последовательность элементов.

Если идти дальше, то с помощью zip можно организовать и более естественное заполнение таблицы:



```
table = 
for C, F in zip(Cdegrees, Fdegrees):
table.append([C, F])
```


а с генерацией списков можно получить совсем короткое:



```
table = [[C, F] for C, F in zip(Cdegrees, Fdegrees)]
```



### Срезы

В Python имеется прекрасный синтаксис для вырезания частей списков, который называется срез (sublist или slice). Срезы никогда не изменяют исходный список, создавая новый. Теперь примеры. A[i:] это срез, который вырезает список из исходного списка A, начиная с индекса i до конца:

```
>>> A = [2, 3.5, 8, 10]
>>> A[2:]
[8, 10]
```


A[i:j] вырезает начиная с элемента i до j-1:

```
>>> A[1:3]
[3.5, 8]
```


A[:i] вырежет из старого списка новый список, забрав все элементы вплоть до i:

```
>>> A[:3]
[2, 3.5, 8]
```


A[1:-1] вырезает все элементы кроме первого и последнего (заметьте, что можно использовать отрицательную индексацию), а A[:] копирует весь список:

```
>>> A[1:-1]
[3.5, 8]
>>> A[:]
[2, 3.5, 8, 10]
```


Покажем, что срезы всего лишь копии. Доказательство 1:

```
>>> l1 = [1, 4, 3]
>>> l2 = l1[:-1]
>>> l2
[1, 4]
>>> l1[0] = 100
>>> l1
[100, 4, 3]
>>> l2
[1, 4]
```


Доказательство 2:

```
>>> B = A[:]
>>> C = A
>>> B == A
True
>>> B is A
False
>>> C is A
True
```

Равенство, которое записывается ==, как мы помним является сравнением значений элементов - если они равны, то возвращается True. Выражение is сравнивает сами объекты, если переменные ссылаются на один и тот же объект в памяти (а не на копию), то возвращается True, в обратном случае False.

Зачем же нужны срезы? Покажем на примере нашей "табличной" программы:



```
>>> for C, F in table[Cdegrees.index(10):Cdegrees.index(35)]:
... print ’%5.0f %5.1f’ % (C, F)
...
10 50.0
15 59.0
20 68.0
25 77.0
30 86.0
```


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

### Больше примеров

a = [] | создание пустого списка |

a = [1, 4.4, ’run.py’] | создание списка |

a.append(elem) | добавить элемент elem в конец списка |

a + [1,3] | сложение двух списков |

a.insert(i, e) | вставить элемент e перед элементом с индексом i |

a[3] | вызов элемента с индексом 3 |

a[-1] | вызов последнего элемента |

a[1:3] | срез: создание копии из элементов с индексами 1, 2 |

del a[3] | удалить элемент с индексом 3 |

a.remove(e) | удалить элемент со значением e |

a.index('run.py') | индекс, соответствующий строковому элементу со значением 'run.py' |

'run.py' in a | узнать, содержится ли элемент в списке a |

a.count(v) | сосчитать сколько элементов списка a имеют значение v |

len(a) | число элементов в списке a |

min(a) | наименьший элемент в a |

max(a) | наибольший элемент в a |

sum(a) | сумма всех элементов a |

sorted(a) | возвращает сортированный список a |

reverse(a) | возвращает "перевернутый" список a |

b[3][0][2] | вызов элемента вложенного списка |

isinstance(a, list) | возвращает True, если объект a является списком |


## Кортежи

Кортежи (tuples) очень похожи на списки, но кортежи нельзя изменять. В отличие от списков, кортежи записываются в круглых скобках:

```
>>> t = (2, 4, 6, ’temp.pdf’)
```

Но во многих случаях скобки можно отбросить:

```
>>> t = 2, 4, 6, ’temp.pdf’
>>> for element in ’myfile.txt’, ’yourfile.txt’, ’herfile.txt’:
... print element,
...
myfile.txt yourfile.txt herfile.txt
```


Большинство возможностей из списков доступно и в кортежах:



```
>>> t = t + (-1.0, -2.0)
>>> t
(2, 4, 6, ’temp.pdf’, -1.0, -2.0)
>>> t[1]
4
>>> t[2:]
(6, ’temp.pdf’, -1.0, -2.0)
>>> 6 in t
True
```


Но любая попытка изменить содержание кортежа приводит к неудаче:



```
>>> t[1] = -1
...
TypeError: object does not support item assignment
>>> t.append(0)
...
AttributeError: ’tuple’ object has no attribute ’append’
>>> del t[1]
...
TypeError: object doesn’t support item deletion
```


Возникает вопрос — зачем нужны кортежи, если списки могут делать большее? Во-первых, из того, что кортеж нельзя изменить, вытекает что их можно использовать в таких случаях — когда нельзя изменять какую-то последовательность. Во-вторых, работа с кортежами происходит быстрее, чем со списками — для неизменяемых объектов требуется меньше памяти. В-третьих, кортежи часто используются в Python в качестве ключей в таком типе объектов как словари, где не могут использоваться списки.

## Чему мы научились

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