#!/usr/bin/env python # coding: utf-8 # # Программирование и анализ данных # # *Алла Тамбовцева, НИУ ВШЭ* # # *Данный ноутбук основан на [лекции](http://nbviewer.math-hse.info/github/ischurov/pythonhse/blob/master/Lecture%203.ipynb#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D0%B9) Щурова И.В., курс «Программирование на языке Python для сбора и анализа данных» (НИУ ВШЭ).* # ## Условные конструкции и цикл `while` # ### Условные конструкции # Условные конструкции – конструкции с операторами условия. Условная конструкция обычно предполагает «развилку»: если условие выполняется, то должен выполняться один набор действий, если нет – другой набор действий. Давайте напишем программу, которая будет просить пользователя ввести целое число, и если это число менее 10, на экран будет выводиться сообщение "Мало", иначе – "Много". И заодно познакомимся с конструкцией *if-else*. # In[10]: x = int(input("Введите число: ")) # In[11]: if x < 10: print("Мало") else: print("Много") # В части с `if` мы прописываем условие, в зависимости от которого Python будет делать выбор, что выводить на экран, а после двоеточия перечисляем действия, которые будут выполняться в случае, если `x` удовлетворяет условию. В части с `else` мы уже не пишем никакого условия – оператор `else` сам по себе означает «в случае, если условие в выражении с `if` не выполнено». # # Часть с `else` является необязательной: программа может существовать только с условием `if`. Тогда в случае невыполнения условия ничего происходить не будет, Python просто перейдет к следующим строкам кода. # Как быть, если условий несколько? Например, мы просим пользователя ввести число, и если число больше 10, на экране должно быть сообщение "Много", если ровно 10 – "В самый раз", если меньше – "Мало". Условные конструкции можно вкладывать друг друга, главное не забывать при этом про отступы: # In[12]: if x < 10: print("Мало") else: if x == 10: print("В самый раз") else: print("Много") # Можно воспользоваться оператором `elif`, который по смыслу является сочетанием `else + if`: если предыдущее условие невыполнено, то, нужно проверить следующее условие, и если оно тоже не выполнено, то уже перейти к ветке с `else`. # In[13]: if x < 10: print("Мало") elif x == 10: print("В самый раз") else: print("Много") # Ответвлений с `elif` может быть несколько: сколько условий, столько и выражений с `elif`. # Законный вопрос: а можно ли обойтись совсем без `elif`, просто записав несколько выражений с `if`? Тут все зависит от ситуации. Иногда решения использовать `elif` и `if`, не меняя остальной код, будут равнозначными. Если мы перепишем код в примере выше, заменив `elif` на `if`, ничего не изменится, так как условия будут проверяться последовательно в любом случае: если число меньше 10, будет выведено слово «Мало», если нет – программа перейдет к следующему условию, и так далее. # В случае, когда условия как-то связаны между собой, нужно быть более внимательными. Рассмотрим такой пример. # # **Случай 1.** # In[16]: mark = int(input("Введите оценку: ")) # In[17]: if mark < 10: print("Это нормально") elif mark == 10: print("Отлично") if mark < 6: print("Плохо") # Если оценка меньше 10, мы выводим на экран сообщение "Это нормально", если нет, то проверяем, равна ли она 10: если да, то выводим "Отлично", если нет – ничего не делаем. При этом, *после* всех этих действий делаем дополнительную проверку: если оценка меньше 6, выводим "Плохо". # **Случай 2.** # In[18]: if mark < 10: print("Это нормально") elif mark == 10: print("Отлично") elif mark < 6: print("Плохо") # Если оценка меньше 10, мы выводим на экран сообщение "Это нормально", если нет, то проверяем, равна ли она 10: если да, то выводим "Отлично", если нет – сравниваем ее с 6. Если оценка меньше 6, выводим "Плохо". # Почему во втором случае мы не увидели сообщение "Плохо"? Потому что из-за второго `elif` мы попросту до него не дошли! На ветку со вторым `elif` мы попадаем в случае, если предыдущее условие не выполняется, то есть если оценка не равна 10. А на ветку с первым `elif` мы попадем, в случае, если оценка не менее 10. Получается, что мы должны выводить слово "Плохо" в случае, когда оценка более 10 и при этом менее 6, чего в природе не бывает. Использовав `elif` необдуманно, мы добавили лишнее условие, которое никогда не будет выполняться! Тут будет полезно вспомнить схемы, которые многие, наверное, видели на уроках информатики в школе. Запоминать их необязательно, просто они хорошо иллюстрируют различия между двумя случаями. # **Случай 1** # # ![title](1.png) # # **Случай 2** # # ![title](2.png) # Возможно, предыдущее обсуждение `if` и `elif` могло вас чуть-чуть запутать, но это не повод расстраиваться. Важно просто помнить, что разница между этими операторами есть. Остальное можно проверить экспериментально на конкретном примере :) # Чтобы еще немного поиграть с условиями, давайте напишем более содержательный код, который будет выдавать комментарий к оценке в 10-балльной шкале (оценка выше 7 – «отлично», выше 5 и ниже 8 – «хорошо», выше 3 и ниже 6 – «удовлетворительно», ниже 4 – «плохо». # **Решение 1:** несколько вложенных условий с оператором `elif` # In[1]: grade = 7 if grade > 7: print("Отлично") elif grade > 5: print("Хорошо") elif grade > 3: print("Удовлетворительно") else: print("Плохо") # Блок-схема для такого кода: # # ![](mark-ex1.png) # **Решение 2:** несколько сложных условий с `if` # In[4]: grade = 7 if grade > 7: print("Отлично") if (grade > 5) and (grade <= 7): print("Хорошо") if (grade > 3) and (grade <= 5): print("Удовлетворительно") if grade <= 3: print("Плохо") # Блок-схема для такого кода: # # ![](mark-ex2.png) # Могли бы мы использовать `else` вместо последнего условия с `if`? Давайте проверим! # In[6]: grade = 7 if grade > 7: print("Отлично") if (grade > 5) and (grade <= 7): print("Хорошо") if (grade > 3) and (grade <= 5): print("Удовлетворительно") else: print("Плохо") # что-то пошло не так # Почему получился такой странный результат? Потому что написанная часть с `else` относится не ко всем условиям с `if` выше, а только в последнему. Давайте посмотрим на блок-схему для такого кода: # ![](mark-ex3.png) # ### Цикл `while` # С циклом `for` мы уже знакомы. Сейчас мы познакомимся с циклом `while`, логика которого отличается от `for`. Конструкции с циклом `while` устроены следующим образом: действия, которые указаны в теле цикла, должны выполняться до тех пор, пока верно условие, прописанное после `while` (отсюда и название). Если в цикле `for` мы указывали некоторый промежуток, по которому в ходе цикла мы будем "пробегаться", то в случае с циклом `while` мы просто фиксируем стартовую точку, а конечную точку никак не указываем: программа сама остановится, когда условие в цикле перестанет выполняться. # In[33]: nums = [1, 0, 9, 10, -1, 8] # Давайте, используя цикл `while`, будем выводить на экран элементы списка `nums` до тех пор, пока не столкнемся с отрицательным значением. # In[34]: i = 0 # начинаем с индекса i=0 while nums[i] >= 0: # пока элемент nums[i] >= 0 print(nums[i]) # выводим элемент на экран i = i + 1 # переходим к следующему элементу # На значении 10 мы остановились: за ним идет значение -1, для которого условие `nums[i] > = 0` не выполняется. # # Давайте теперь попробуем переписать код так, чтобы он работал точно так же, но только чтобы в нем использовался цикл `for`, а не `while`. Вообще почти любой код с `while` можно переписать через `for`, и иногда это полезно: код с циклом `while` обычно более медленный, плюс, склонен к зацикливанию. # In[35]: for n in nums: if n >= 0: print(n) else: break # выходим из цикла # В коде выше мы использовали оператор `break`, который позволяет выйти из цикла, то есть закончить исполнение строк кода в теле цикла и перейти к коду дальше. # # А теперь напишем маленькую игру-угадайку. Программа будет загадывать целое число от 1 до 100, а пользователь его угадывать. Как программа будет загадывать число? Выбирать случайным образом из интервала [1, 100] (на самом деле псевдослучайным образом, так как абсолютной случайности не получится, генерирование чисел происходит по фиксированным алгоритмам). # In[36]: from random import randrange # импортируем функию randrange # In[37]: n = randrange(1, 101) # n и есть загаданное число # Осталось написать цикл. До тех пор, пока пользователь не угадает число, программа не будет останавливаться, но зато она будет давать подсказки: если введенное пользователем число больше загаданного, то будет выводиться сообщение "Вы ввели слишком большое число.", если меньше – "Вы ввели слишком маленькое число." # In[38]: while True: guess = int(input("Ваша попытка: ")) if guess == n: print("Вы выиграли!") break elif guess > n: print("Вы ввели слишком большое число.") else: print("Вы ввели слишком маленькое число.") # В коде выше в `while` мы не написали никакого условия явно, вместо этого мы написали `while True`. Это выражение означает «до тех пор, пока мы не вышли из цикла». В нашем случае это равносильно «до тех пор, пока не столкнулись с `break`», то есть пока наш ответ не совпал с загаданным числом.