{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python для сбора и анализа данных\n", "\n", "*Алла Тамбовцева, НИУ ВШЭ*\n", "\n", "*Данный ноутбук основан на [лекции](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 для сбора и анализа данных» (НИУ ВШЭ).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Условные конструкции" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Условные конструкции – конструкции с операторами условия. Условная конструкция обычно предполагает «развилку»: если условие выполняется, то должен выполняться один набор действий, если нет – другой набор действий. Давайте напишем программу, которая будет просить пользователя ввести целое число, и если это число менее 10, на экран будет выводиться сообщение \"Мало\", иначе – \"Много\". И заодно познакомимся с конструкцией *if-else*." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Введите число: 3\n" ] } ], "source": [ "x = int(input(\"Введите число: \"))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Мало\n" ] } ], "source": [ "if x < 10:\n", " print(\"Мало\")\n", "else:\n", " print(\"Много\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В части с `if` мы прописываем условие, в зависимости от которого Python будет делать выбор, что выводить на экран, а после двоеточия перечисляем действия, которые будут выполняться в случае, если `x` удовлетворяет условию. В части с `else` мы уже не пишем никакого условия – оператор `else` сам по себе означает «в случае, если условие в выражении с `if` не выполнено».\n", "\n", "Часть с `else` является необязательной: программа может существовать только с условием `if`. Тогда в случае невыполнения условия ничего происходить не будет, Python просто перейдет к следующим строкам кода." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как быть, если условий несколько? Например, мы просим пользователя ввести число, и если число больше 10, на экране должно быть сообщение \"Много\", если ровно 10 – \"В самый раз\", если меньше – \"Мало\". Условные конструкции можно вкладывать друг друга, главное не забывать при этом про отступы:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Мало\n" ] } ], "source": [ "if x < 10:\n", " print(\"Мало\")\n", "else:\n", " if x == 10:\n", " print(\"В самый раз\")\n", " else: \n", " print(\"Много\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Можно воспользоваться оператором `elif`, который по смыслу является сочетанием `else + if`: если предыдущее условие невыполнено, то, нужно проверить следующее условие, и если оно тоже не выполнено, то уже перейти к ветке с `else`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Мало\n" ] } ], "source": [ "if x < 10:\n", " print(\"Мало\")\n", "elif x == 10:\n", " print(\"В самый раз\")\n", "else: \n", " print(\"Много\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ответвлений с `elif` может быть несколько: сколько условий, столько и выражений с `elif`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Законный вопрос: а можно ли обойтись совсем без `elif`, просто записав несколько выражений с `if`? Тут все зависит от ситуации. Иногда решения использовать `elif` и `if`, не меняя остальной код, будут равнозначными. Если мы перепишем код в примере выше, заменив `elif` на `if`, ничего не изменится, так как условия будут проверяться последовательно в любом случае: если число меньше 10, будет выведено слово «Мало», если нет – программа перейдет к следующему условию, и так далее. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В случае, когда условия как-то связаны между собой, нужно быть более внимательными. Рассмотрим такой пример. \n", "\n", "**Случай 1.** " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Введите оценку: 3\n" ] } ], "source": [ "mark = int(input(\"Введите оценку: \"))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Это нормально\n", "Плохо\n" ] } ], "source": [ "if mark < 10:\n", " print(\"Это нормально\")\n", "elif mark == 10:\n", " print(\"Отлично\")\n", "if mark < 6:\n", " print(\"Плохо\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если оценка меньше 10, мы выводим на экран сообщение \"Это нормально\", если нет, то проверяем, равна ли она 10: если да, то выводим \"Отлично\", если нет – ничего не делаем. При этом, *после* всех этих действий делаем дополнительную проверку: если оценка меньше 6, выводим \"Плохо\". " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Случай 2.** " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Это нормально\n" ] } ], "source": [ "if mark < 10:\n", " print(\"Это нормально\")\n", "elif mark == 10:\n", " print(\"Отлично\")\n", "elif mark < 6:\n", " print(\"Плохо\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если оценка меньше 10, мы выводим на экран сообщение \"Это нормально\", если нет, то проверяем, равна ли она 10: если да, то выводим \"Отлично\", если нет – сравниваем ее с 6. Если оценка меньше 6, выводим \"Плохо\". " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Почему во втором случае мы не увидели сообщение \"Плохо\"? Потому что из-за второго `elif` мы попросту до него не дошли! На ветку со вторым `elif` мы попадаем в случае, если предыдущее условие не выполняется, то есть если оценка не равна 10. А на ветку с первым `elif` мы попадем, в случае, если оценка не менее 10. Получается, что мы должны выводить слово \"Плохо\" в случае, когда оценка более 10 и при этом менее 6, чего в природе не бывает. Использовав `elif` необдуманно, мы добавили лишнее условие, которое никогда не будет выполняться! Тут будет полезно вспомнить схемы, которые многие, наверное, видели на уроках информатики в школе. Запоминать их необязательно, просто они хорошо иллюстрируют различия между двумя случаями." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Случай 1**\n", "\n", "![title](1.png)\n", "\n", "**Случай 2**\n", "\n", "![title](2.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Возможно, предыдущее обсуждение `if` и `elif` могло вас чуть-чуть запутать, но это не повод расстраиваться. Важно просто помнить, что разница между этими операторами есть. Остальное можно проверить экспериментально на конкретном примере :) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Чтобы еще немного поиграть с условиями, давайте напишем более содержательный код, который будет выдавать комментарий к оценке в 10-балльной шкале (оценка выше 7 – «отлично», выше 5 и ниже 8 – «хорошо», выше 3 и ниже 6 – «удовлетворительно», ниже 4 – «плохо»." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Решение 1:** несколько вложенных условий с оператором `elif`" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Хорошо\n" ] } ], "source": [ "grade = 7\n", "if grade > 7:\n", " print(\"Отлично\")\n", "elif grade > 5:\n", " print(\"Хорошо\")\n", "elif grade > 3:\n", " print(\"Удовлетворительно\")\n", "else:\n", " print(\"Плохо\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Блок-схема для такого кода:\n", "\n", "![](mark-ex1.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Решение 2:** несколько сложных условий с `if`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Хорошо\n" ] } ], "source": [ "grade = 7\n", "if grade > 7:\n", " print(\"Отлично\")\n", "if (grade > 5) and (grade <= 7):\n", " print(\"Хорошо\")\n", "if (grade > 3) and (grade <= 5):\n", " print(\"Удовлетворительно\")\n", "if grade <= 3:\n", " print(\"Плохо\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Блок-схема для такого кода:\n", "\n", "![](mark-ex2.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Могли бы мы использовать `else` вместо последнего условия с `if`? Давайте проверим!" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Хорошо\n", "Плохо\n" ] } ], "source": [ "grade = 7\n", "if grade > 7:\n", " print(\"Отлично\")\n", "if (grade > 5) and (grade <= 7):\n", " print(\"Хорошо\")\n", "if (grade > 3) and (grade <= 5):\n", " print(\"Удовлетворительно\")\n", "else:\n", " print(\"Плохо\") # что-то пошло не так" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Почему получился такой странный результат? Потому что написанная часть с `else` относится не ко всем условиям с `if` выше, а только в последнему. Давайте посмотрим на блок-схему для такого кода:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](mark-ex3.png)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }