Введение в Python. Часть 4
Циклы while, for — как итерировать строки
Темой четвертой лекции курса «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 здесь.