Темой четвертой лекции курса «Python для журналистов» станут циклы while и for. Циклы позволяют проходить по всем элементам итерируемых объектов. При этом к итерируемым объектам относятся не только различные массивы данных (такие, как, например, списки), но и строки. Учитывая, что мы уже знаем, что такое строки и как с ними работать (а если вы не знаете, то посмотрите и почитайте нашу вторую лекцию), рассмотрим циклы на примере работы со строками. 

Цикл while       

Основной цикл в Python — цикл while (на русский язык переводится как «до тех пор пока...»). Его синтаксис похож на синтаксис условных конструкций (if, elif, else — об этом была наша третья лекция): while не будет выполнено условие: делай что-то.    

Попробуем для начала распечатать каждую букву какой-нибудь строки. Например, начала стихотворения Александра Сергеевича Пушкина «Буря мглою...». Введем имя poem и присвоим ему значение: poem = 'Буря мглою' 

Для того чтобы итерировать эту строку, нам нужно понять, каким должно быть условие остановки цикла. В данном случае таким условием будет конец строки. Иными словами, наш цикл должен печатать каждую букву до тех пор не закончится строка. Условно: while не закончится строка:  print(букву)      

Но как компьютер поймет, что закончилась строка? Все просто: у строк есть длина (функция len), так вот строка заканчивается тогда, когда индекс последней буквы равен длине строки. Давайте проверим длину нашей строки: len(poem). Значение ровно 10. 

Теперь введем новое имя index и присвоим ему значение 0: index = 0. И мы готовы написать наш первый цикл. 

while index != len(poem):

   print(poem[index])

   index += 1

В этой конструкции нужно обратить внимание на несколько вещей. Первая: имя временной переменной index в цикле может быть любым, то есть мы могли написать и так: while i != len(poem) Вторая: знак != в Python означает неравенство. То есть в нашем примере мы как бы говорим: «До тех пор пока index не равен длине строки, печатай каждую букву строки». Это означает, что как только index станет равен 10, цикл завершит свою работу. Третья: у каждого элемента строки есть свой индекс, поэтому мы можем печатать букву под каждым следующим индексом. Четвертая: для того, чтобы условие цикла было выполнено, нам нужно на каждой итерации увеличивать index. В противном случае, цикл окажется вечным и наша программа зависнет. Так вот для того, чтобы index увеличивался на каждой итерации, мы прибавляем к нему единицу: index += 1.  

Конструкция += — это так называемый «синтаксический сахар» языка Python, то есть синтаксис, который позволяет писать более удобный, читаемый и краткий код. Конструкция index += 1 равносильна выражению index = index + 1 

Посчитаем гласные   

Теперь, когда мы знаем, как итерировать строки, попробуем решить простую задачку — посчитать количество гласных в нашей строке. Для этого введем новое имя vowels (что переводится как «гласные» на русский язык) и присвоим ему значение 'аоэеиыуёюя' — это все гласные русского алфавита. 

Когда у нас есть список всех гласных алфавита, мы можем проверить, является ли буква из нашей строки poem гласной. Для этого можно использовать ключевое слово Python — in: poem[0] in vowels — распечатает False, что логично, потому что буква «Б» (первая буква стихотворения) — согласная. А вот poem[1] in vowels распечатает True, потому что буква «у» (вторая в стихотворении) — гласная. 

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

while index != len(poem):

   if poem[index].lower() in vowels:

       print(poem[index])

   index += 1 

Этот цикл проверяет каждую букву строки — относится она к гласным или нет. Если да (if poem[index].lower() in vowels), то эта буква распечатывается. Обратите внимание, что мы также меняем регистр каждой буквы с помощью функции lower(), чтобы проверить в том числе заглавные буквы. 

Но пока мы только распечатываем гласные буквы, а нам бы хотелось их сохранить и посчитать их количество. Сделать это просто. Введем новое имя poem_vowels и присвоим ему значение пустой строки: poem_vowels = '' Теперь немного изменим наш цикл: 

while index != len(poem):

   if poem[index] in vowels:

       poem_vowels += poem[index]

   index += 1

У нас изменилась всего лишь одна строчка: poem_vowels += poem[index] — это изменение основано на том, что строки можно конкатенировать, то есть складывать. И мы как бы говорим циклу: «До тех пор пока index не равен длине строки; если буква гласная, то прибавляй ее к строке poem_vowels». 

Теперь poem_vowels — это строка со всеми гласными из стихотворения. И, чтобы узнать, сколько в ней этих гласных, нужно просто узнать ее длину с помощью функции len: print(len(poem_vowels))    

Цикл for

Цикл for — это тоже «синтаксический сахар» языка Pytnon, благодаря которому проще итерировать объекты, а код становится более читаемым. Например, если бы мы хотели распечатать все буквы того же стихотворения, как мы это делали с циклом while, нам бы потребовалось написать гораздо меньше кода: 

for i in poem:

   print(i)

Обратите внимание, что в цикле for нам даже не нужно помнить об индексе — цикл «проходится» по каждому элементу массива (в данном случае строки), зная, когда она закончится. Таким образом, чтобы решить ту же задачку по поиску гласных в стихотворении, нам нужно написать такой цикл: 

for i in poem:

   if i.lower() in vowels:

       poem_vowels += i

Функция range 

Конструкция цикла for, безусловно, удобна тем, что она позволяет добираться до каждого элемента итерируемого объекта без индекса, но что если мы хотим все-таки знать индекс? Например, мы бы хотели проверить, является ли каждая буква нашего стихотворения гласной, и если да, то распечатать её и её индекс, чтобы понимать, в каком месте строки она находится. Как нам это сделать? Воспользуемся функцией range, которая позволяет создавать любые последовательности чисел. Например, если бы мы хотели создать последовательность чисел от 0 до 10, нам бы потребовалось написать всего лишь одну строчку кода: range(11) 

 Функция range принимает три параметра: range(start, stop, step). Start — это начало (по умолчанию, начинается с 0) последовательности (включительно); stop — это конец (не включительно, и поэтому, чтобы создать последовательность чисел до 10 включительно, нам нужно прибавить единицу); step — это шаг последовательности. Если мы хотим, допустим, распечатать каждый четный элемент последовательности до 10 включительно, то мы можем написать такой цикл: 

for i in range(0, 11, 2):

   print(i)   

   

Теперь вернемся к нашей задаче: как добраться до индекса каждой буквы в строке и, если буква гласная, распечатать её вместе с индексом? Для этого воспользуемся range:

for i in range(len(poem)):

   if poem[i].lower() in vowels:

       print(f'Это гласная буква {poem[i]} находится в позиции {i}')    

Обратите внимание, что в этом цикле for мы уже обращаемся не напрямую к каждому элементу строки, а к их индексам. 

Вложенные циклы 

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

for male_age in male_data:

   for female_age in female_data:

          if male_age > female_age:

                print(f'Возраст мужчины больше возраста женщины на {male_age - female_age}')

          else:

                 print(f'Возраст женщины больше возраста мужчины на {female_age - male_age}')

В этом блоке кода мы сначала берем первый элемент первого массива (male_data), затем проходимся по всем элементам второго массива (female_data) и сравниваем первый элемент первого массива с каждым элементом второго массива. Затем мы берем второй элемент первого массива и снова сравниваем его со всеми элементами второго массива. И так мы делаем до тех пор, пока не закончатся все элементы первого массива.  

Тетрадку Jupyter Notebook с этим уроком можно найти в нашем GitHub здесь.