§8. Цикл for. Функция range(). Модуль random. Вложенные циклы

Цикл итераций по последовательности for

Цикл for в python не является универсальным (по сравнению с подобными инструкциями в других языках, например, в С++). Но, по задумке создателей языка, он на это и не претендует, его задача в другом – он предназначен для итераций по последовательностям, таким как список (с которым мы познакомимся уже на следующем уроке). Отсюда его необычный синтаксис.
Тем не менее, цикл for в python реализует туже алгоритмическую структуру – цикл с параметром (или со счетчиком), что и реализации for в других языках. В виде блок схемы эта структура изображается так:

На этом рисунке: I – параметр (счетчик) цикла, A начальное значение параметра, B – его конечное значение, а N – шаг цикла (приращение счетчика). Особенность реализации цикла for в python в том, что в качестве модифицирующего выражения используется функция range(). Синтаксис цикла for:

for target_list in expression_list:
    Тело цикла
[else:
    Выражение]

Где target_list – параметр цикла, а expression_list – имя последовательности (например, списка) или вызов функции range(). Также как и цикл while, for имеет необязательный блок else.
Помимо обхода элементов коллекции, цикл for может применяться и в тех задачах, когда, прежде выполнения инструкций тела цикла, становится известным (или заранее определено) количество шагов этого цикла.

Функция range()

Формально range – это класс создающий числовые целочисленные последовательности (арифметические прогрессии). Хотя range() и причисляют к коллекциям в python, но, фактически, значения элементов последовательности в памяти не сохраняются. Поскольку выражение с range() является всего-лишь правилом для создания определенной последовательности. Как превратить последовательность, созданную range(), в список мы обсудим на следующем уроке.
Функция может применяться с одним, двумя или тремя аргументами:

  • range(A) – создается последовательность от 0 до A - 1[0, A-1];
  • range(A, B) – создается последовательность от A до B[A, B), B - не входит;
  • range(A, B, N) – создается последовательность от A до B[A, B) с шагом N, шаг может быть отрицательным;
Примеры показаны в программе ниже.
Программа 8.1

for j in range(10):
    print(j, end=' ')
print()
for j in range(10, 100, 10):
    print(j, end=' ')
print()
for j in range(100, 50, -5):
    print(j, end=' ')
0 1 2 3 4 5 6 7 8 9 
10 20 30 40 50 60 70 80 90 
100 95 90 85 80 75 70 65 60 55 

Рассмотрим несколько задач по созданию рядов натуральных чисел.
Программа 8.2 Создать последовательность нечетных чисел от 1 до n, включительно, если n нечетное.

n = int(input('n = '))
for j in range(1, n, 2):
    print(j, end=' ')
else:
    if n % 2:
        print(n)

Программа 8.3 Вывести n чисел Фибоначчи. Числа Фибоначчи: f1 = 1, f2 = 1, fn = fn-1 + fn-2

f = None
f1, f2 = 1, 1
n = int(input('n = '))
print('1 =>', f1)
print('2 =>', f2)
for j in range(3, n + 1):
	f  = f1 + f2
	f1, f2 = f2, f
	print(j, '=>', f)

Вывод программы 8.2

n = 50
1 => 1
2 => 1
3 => 2
4 => 3
5 => 5
6 => 8
7 => 13
8 => 21
9 => 34
...
47 => 2971215073
48 => 4807526976
49 => 7778742049
50 => 12586269025

Случайные числа

Существует несколько классов задач (например, игровые программы, криптография, метод Монте-Карло, имитационное моделирование) для решения которых необходимо применять случайные числа. “Случайные числа”, на самом деле, не являются действительно случайными (поэтому их правильнее называть псевдослучайными), а подчиняются правилам математической теории вероятности и соответствующим функциям распределения из этой теории. [Вики] В python генератор случайных чисел реализован в модуле random.
Примечание. Генераторы псевдо-случайных чисел этого модуля не должны использоваться в целях обеспечения безопасности (криптография).

Методы класса random
Метод Описание
random.seed(a=None, version=2) Инициализация генератора, если параметры отсутствуют, то берется текущее системное время
random.randrange(start, stop[, step]) Возвращает целое случайное число из интервала [start, stop)
random.randint(A, B) Возвращает целое из отрезка [A, B]
random.random() Возвращает случайное действительное число из интервала [0, 1). Используется без аргументов.
random.uniform(a, b) Возвращает случайное действительное число N такое, что a <= N <= b для a <= b и b <= N <= a для b < a
random.choice(seq) Случайный элемент из последовательности seq
random.shuffle(seq[, random]) Перетасовывание элементов последовательности seq. Нельзя применять к неизменяемым коллекциям (например, строки)
random.sample(seq, k) Возвращает список (новый, без замены) длиной k из последовательности seq, в котором элементы будут перетасованы

Программа 8.4 С помощью модулей turtle и random построить гистограмму из 10 столбцов, в которой высота столба и цвет заливки столба определяются случайным образом. (Вспомним работу с черепашкой ;-))

import turtle
from random import randint, random
#################################################
#  Установки окна и черепахи                    #
#################################################
window = turtle.Screen() 
window.title('Гистограмма')
window.bgcolor('black')
window.setup(width=800, height=800)

t = turtle.Turtle() 
t.speed(10)
t.hideturtle()
t.up()
t.goto(350, -350)
t.down()
t.color('red')
t.pensize(2)
t.bk(700)  # Чертим ось x
t.lt(90)
t.up()
t.fd(1)
t.rt(90)
t.down()
t.pensize(1)

#################################################
#  Установки гистограммы                        #
#################################################
l = 52     # Толщина столбца
m = 20     # Дистанция между столбцами
d = None   # Подготовим высоту

#################################################
#  Функция тик гистограммы                      #
#################################################
def tic():
    R = random()
    G = random()
    B = random()
    d = randint(10, 600)
    t.color(R, G, B)
    t.begin_fill()
    t.lt(90)
    t.fd(d)
    t.rt(90)
    t.fd(l)
    t.rt(90)
    t.fd(d)
    t.lt(90)
    t.end_fill()
    t.up()
    t.fd(m)
    t.down()    
    
for j in range(10):
    tic()
    
window.exitonclick()


Программа 8.5 Разработать программу игры "Угадай число". Компьютер "загадывает" число, которое пользователь должен угадать за известное количество шагов.

from random import randint, seed
n = 10
a = None
seed()
# Компьютер загадал число:
k = randint(1, 100);
print('У вас', n, 'попыток')
for j in range(1, n + 1):
    print('Попытка', j, 
          "\nКакое число загадал компьютер? -> ",
          end='')
    a = int(input())
    if a > k:
        print('много')
    elif a < k:
        print('мало')
    else:
        print('Вы выиграли!')
        break
    if n == j:
        print('Вы проиграли!')
        break

Вывод программы 8.5

У вас 10 попыток
Попытка 1 
Какое число загадал компьютер? -> 50
много
Попытка 2 
Какое число загадал компьютер? -> 40
много
Попытка 3 
Какое число загадал компьютер? -> 30
много
Попытка 4 
Какое число загадал компьютер? -> 20
Вы выиграли!

Циклы for вложенные друг в друга

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

Рассмотрим класс таких задач.
Программа 8.6 Вывести таблицу Пифагора (таблицу умножения в виде матрицы)

for j in range(1, 11):
    for k in range(1, 11):
        print('{:>4}'.format(j * k), end='')
    print()

Вывод программы 8.6

   1   2   3   4   5   6   7   8   9  10
   2   4   6   8  10  12  14  16  18  20
   3   6   9  12  15  18  21  24  27  30
   4   8  12  16  20  24  28  32  36  40
   5  10  15  20  25  30  35  40  45  50
   6  12  18  24  30  36  42  48  54  60
   7  14  21  28  35  42  49  56  63  70
   8  16  24  32  40  48  56  64  72  80
   9  18  27  36  45  54  63  72  81  90
  10  20  30  40  50  60  70  80  90 100

Программа 8.7 Составить программу выводящую числовой треугольник вида:

 1
 2   2
 3   3   3
 4   4   4   4
 5   5   5   5   5
 6   6   6   6   6   6
 7   7   7   7   7   7   7
 8   8   8   8   8   8   8   8
 9   9   9   9   9   9   9   9   9
10  10  10  10  10  10  10  10  10  10
for j in range(1, 11):
    for k in range(1, j + 1):
        print('{:>2}'.format(j), end='')
    print()

Как видно изменений в программе не много, а результат совсем иной. В программе 8.7 мы поставили в зависимость количество шагов вложенного цикла от значения параметра внешнего.
Программа 8.8 Дано целое n. Вывести все тройки чисел x, y и z для которых x2 + y2 + z2 = n

from math import sqrt
n = int(input('n = '))
m = int(sqrt(n)) + 1
for x in range(m):
    for y in range(m):
        for z in range(m):
            if x * x + y * y + z * z == n:
                print('{:4}{:4}{:4}'.format(x, y, z))
n = 200
   0   2  14
   0  10  10
   0  14   2
   2   0  14
   2  14   0
   6   8  10
   6  10   8
   8   6  10
   8  10   6
  10   0  10
  10   6   8
  10   8   6
  10  10   0
  14   0   2
  14   2   0

В заключение отметим, что один тип цикла (например, while) может быть вложен в цикл другого типа (for) и наоборот.
Программа 8.9 Найти натуральное число от 1 до 10000 с максимальной суммой делителей

max = 0
for j in range(1, 10001):
    s = 0
    i = 2
    while i < j // 2:
        if j % i == 0:
            s += i
        i += 1
    if s > max:
        max = s
        k = j
print(k)
9240

Примечание. Время выполнения программы будет ок. 10 с.!

Print Friendly, PDF & Email

Comments are closed.