#6 Python для Data Science — объединение цикла for и инструкции if

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

Это практическое руководство! Желательно повторять те части, где нужно писать код, и решать задачи в конце статьи! Также рекомендуется вернуться к прошлым материалам.

Цикл for внутри цикла for — или просто вложенный цикл for

Чем сложнее проект, над которым ведется работа, тем больше вероятность, что придется работать с вложенным циклом for. Это значит, что будет одна итерация с другой итерацией внутри нее.

Предположим, что есть 9 сериалов в трех категориях: комедии, мультфильмы и драмы. Они представлены во вложенном списке Python («списки в списке»):

my_movies = [['How I Met Your Mother', 'Friends', 'Silicon Valley'],
	    ['Family Guy', 'South Park', 'Rick and Morty'],
	    ['Breaking Bad', 'Game of Thrones', 'The Wire']]

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

"The title [movie_title] is [X] characters long."

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

for sublist in my_movies:
    for movie_name in sublist:
        char_num = len(movie_name)
        print("The title " + movie_name + " is " + str(char_num) + " characters long.")

Примечание: len() — это функция Python, которая выводит целое число. Чтобы сделать его «выводимым», нужно превратить число в строку. О том, как это сделать, говорилось в прошлом руководстве.

Цикл for внутри цикла for

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

И еще кое-что:
Синтаксис! Правила те же, что были при изучении простых циклов for. Единственное, на чем важно сделать акцент — отступы. Только используя корректные отступы в Python, вы сможете сообщить языку, в каком именно блоке цикла (внешнем или внутреннем) нужно применить тот или иной код. Попробуйте сделать следующее и обнаружить отличия в этих примерах:

Цикл for внутри цикла for - синтаксис

Инструкции if в цикле for

Внутри цикла for также можно использовать инструкции if.

В качестве примера можно привести известное упражнение, которое предлагают junior-специалистам в сфере data science:

Переберите числа до 99. Выводите «fizz» для каждого числа, которое делится на 3, «buzz» — для тех, что делятся на 5 и «fizzbuzz» — для тех, что делятся на 3 и на 5! Если число не делится, выводите тире (’-’)

Вот решение:

for i in range(100):
    if i % 3 == 0 and i % 5 == 0:
        print('fizzbuzz')
    elif i % 3 == 0:
        print('fizz')
    elif i % 5 == 0:
        print('buzz')
    else:
        print('-')

Как видно в примере, инструкция if в цикле for отлично подходит, чтобы оценить диапазон чисел (или, например, элементы списка) и разбить их по категориям. Таким же образом к ним можно применить функции или просто вывести.

Важно: при использовании инструкции if в цикле for будьте особенно внимательно с отступами, потому что если что-то упустить, то программа работать не будет.

Break

В Python есть удобный инструмент потока, который идеально подходит для управления инструкциями if в циклах for. Это инструкция break.

Найдете первое 7-значное число, которое делится на 137? (Только одно — первое).

Решение:

for i in range(0, 10000000, 137):
    if len(str(i)) == 7:
        print(i)
        break

Этот цикл берет каждое 137-е число (for i in range (0, 10000000, 137)) и проверяет, используется ли в нем 7 цифр или нет (if len(str(i) == 7). Как только он получит первое 7-значное число, инструкция if станет истинной (True), и произойдут две вещи:

  1. print(i) — число выведется на экран
  2. break прервет цикл, чтобы первое 7-значное число было также и последним на экране.

Узнать больше о break (и его брате близнеце, continue) можно в статье: Синтаксис, возможности и подводные камни цикла for Python 3.

Примечание: эту задачу можно решить еще проще с помощью цикла while. Но поскольку руководства по этому циклу еще нет, здесь был использован подход цикл for + break.

Проверьте себя!

Пришло время узнать, насколько вы разобрались с инструкцией if, циклами for и их объединением. Попробуйте решить следующее задание.

Создайте скрипт на Python, который узнает ваш возраст максимум с 8 попыток. Он должен задавать только один вопрос: угадывать возраст (например, «Вам 67 лет?»). Отвечать же можно одним из трех вариантов:

  • correct
  • less
  • more

Основываясь на ответе, компьютер должен делать новые попытки до тех пор, пока не узнает корректный возраст.

Примечание: для решения задачи нужно изучить новую функцию input(). Больше о ней здесь.

Готовы? Вперед!

Решение

Вот код решения.


Примечание: решить задачу можно и с помощью цикла while. Но поскольку он еще не рассматривался, был выбран вариант с for.

down = 0
up = 100
for i in range(1,10):
    guessed_age = int((up + down) / 2)
    answer = input('Are you ' + str(guessed_age) + " years old?")
    if answer == 'correct':
        print("Nice")
        break
    elif answer == 'less':
        up = guessed_age
    elif answer == 'more':
        down = guessed_age
    else:
        print('wrong answer')

Логика решения следующая:

  • Устанавливаем диапазон от 0 до 100, предполагая, что возраст «игрока» будет где-то посередине.
    down = 0  
    up = 100
    
  • Скрипт всегда спрашивает среднее значение диапазона (первой попыткой будет 50):
    guessed_age = int((up + down) / 2)
    answer = input('Are you ' + str(guessed_age) + " years old?")
    
  • После получения ответа от «игрока» могут быть 4 возможных сценария:
    • Если возраст угадан, скрипт заканчивается и возвращает определенный ответ.
    if answer == 'correct':
      print("Nice")
      break
    
    • Если ответ «меньше», тогда цикл начинается сначала, но перед этим максимальное значение диапазона устанавливается на уровне последнего предположения (Так, вторая итерация будет искать середину между 0 и 50).
      elif answer == 'less':
         up = guessed_age
      
    • То же самое для «больше» — только в этом случае меняется минимум:
      elif answer == 'more':
         down = guessed_age
      
    • И в конце обрабатываются ошибки или опечатки:
      else:
          print('wrong answer')
      

Объединение цикла for и инструкции if задача

Итого

Теперь вы знаете о:

  • Вложенных циклах for в Python
  • Объединении циклов for и инструкций if

Это уже не базовый уровень Python, а переход к среднему. Использование этих инструментов предполагает понимание логики Python 3 и постоянной практики.

В серии этих руководств осталось всего два урока. Продолжайте, чтобы узнать все об основах синтаксиса Python.