{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Конструкции управления потоком #" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Когда вы пишете программу, у вас постоянно возникает необходимость выполнить то или иное действие, тот или иной блок кода в зависимости от выполнения условия. Также может возникнуть необходимость какой-то блок кода выполнить несколько раз. Для этого существуют конструкции управления потоком. Об этих конструкциях мы и будем говорить в этой лекции." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Первое, на что мы посмотрим — это оператор `if`. Оператор `if` используется для выполнения каких-то действий при выполнении условия. Давайте посмотрим на пример." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Условие выполнено!\n" ] } ], "source": [ "company = \"vniitf.ru\"\n", "\n", "if \"vniitf\" in company:\n", " print(\"Условие выполнено!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В данном примере мы определяем переменную `company` со значением `vniitf.ru` и далее используем оператор `if` и проверяем наличие подстроки `vniitf` в нашей строке. Если условие выполняется, а условие выполняется в том случае, если оно интерпретируется как `True`, то блок кода под `if` выполняется. В данном случае подстрока `vniitf` есть в строке `vniitf.ru` и наше условие выполняется.\n", "\n", "Иногда может быть так, что условие у вас сложное. Никаких проблем, вы можете записывать сложные условия в блоке оператора `if`, то есть вы можете выполнять различные bool'евские выражения, разделенные `or`, `and` и так далее. На втором примере как раз это показано." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Условие выполнено!\n" ] } ], "source": [ "company = \"chelaxe.ru\"\n", "\n", "if \"vniitf\" in company or company.endswith(\".ru\"):\n", " print(\"Условие выполнено!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В некоторых случаях нужно выполнить какие-либо действия, когда условие не выполняется. Для этого существует оператор `else`. Оператор `else` в блоке `if…else` позволяет выполнить какой-то код, если условие не выполнилось. Посмотрим на примере." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "company = \"google.com\"\n", "\n", "if \"vniitf\" in company:\n", " print(\"Условие выполнено!\")\n", "else:\n", " print(\"Условие не выполнено!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "У нас в данном случае строка `google.com`, мы проверяем условие — наличие подстроки `vniitf` в строке `google.com` Оно, конечно же, не выполняется, но благодаря оператору `else` мы можем это отловить и выполнить код, который печатает нам на экран то, что условие не выполнено. Также есть возможность использовать выражение `if…elif…else`, в котором добавился оператор `elif`. Он используется тогда, когда нужно проверить друг за другом какие-то условия, не связанные друг с другом. Опять же на примере посмотрим." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Подстрока google найдена\n" ] } ], "source": [ "company = \"google.com\"\n", "\n", "if \"vniitf\" in company:\n", " print(\"Подстрока vniitf найдена\")\n", "elif \"google\" in company:\n", " print(\"Подстрока google найдена\")\n", "else:\n", " print(\"Подстрока не найдена\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы определяем переменную со значением `google.com` строковый, и дальше у нас в данном случае срабатывает блок `elif`, который выполняется тогда, когда подстрока `google` была найдена в нашей строке.\n", "\n", "Также во многих языках программирования вы могли встречать тернарный оператор. В Python'е есть его аналог, и он записывается вот таким вот образом, который вы видите на примере." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Argentina\n" ] } ], "source": [ "score_1 = 5\n", "score_2 = 0\n", "\n", "winner = \"Argentina\" if score_1 > score_2 else \"Jamaica\"\n", "\n", "print(winner)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "То есть переменной будет присвоена строка `Argentina` в том случае, если условие выполнено, иначе будет присвоена строка `Jamaica`. Все это записывается в одну строчку, как вы можете видеть. В некоторых случаях это удобно.\n", "\n", "Перейдем к другому оператору, оператору `while`. `While` позволяет выполнять блок до тех пор, пока выполняется какое-то условие. Опять же давайте посмотрим на пример." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100\n" ] } ], "source": [ "i = 0\n", "while i < 100:\n", " i += 1\n", " \n", "print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы определяем переменную, `i = 0`, и будем прибавлять к переменной `i` единичку до тех пор, пока она меньше 100. Достаточно всё просто, мы пишем `while i < 100`, прибавляем единичку." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "i = 3\n", "\n", "while i >= 0:\n", " i -= 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сколько раз выполнится блок кода внутри цикла while?\n", "\n", "Дальше.\n", "\n", "Иногда вам нужно проитерироваться по какой-то последовательности. Для этого в Python существует выражение `for…in`. Мы на данный момент знаем две последовательности, о которых уже рассказывали — это строка и это байтовая строка В примере на слайде мы итерируемся по строке. Строка содержит значение Alex, и мы итерируемся с помощью выражения `for…in`, `for letter in name`, мы принтим буковку. Каждый юникодный символ друг за другом попадает в тело нашего for-цикла и с помощью функции `print` попадает в дальнейшем на экран." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A\n", "l\n", "e\n", "x\n" ] } ], "source": [ "name = \"Alex\"\n", "\n", "for letter in name:\n", " print(letter)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Встроенный объект `range` позволяет итерироваться по целым числам. Что это значит? Если мы напишем `for i in range(3)`, то в теле блока `for` мы сначала получим ноль, потом один, потом два, но не три. Когда мы определяем объект `range`, он не включает в себя последнее значение." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n" ] } ], "source": [ "for i in range(3):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Давайте посмотрим на чуть более сложный пример." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5050\n" ] } ], "source": [ "result = 0\n", "\n", "for i in range(101):\n", " result += i\n", "\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Это задачка. Может быть, многие слышали историю про Фридриха Гаусса, который решил ее на уроке школьной математики очень быстро. Уверен, что на Python'е мы решим ее не менее быстро и суть ее в том, чтобы получить сумму чисел от 0 до 100. С помощью цикла `for` мы очень просто можем это сделать.\n", "\n", "Объект `range` также может инициализироваться с двумя аргументами, для того чтобы проитерироваться по последовательности чисел, начиная с какого-то числа и заканчивая каким-то числом. Но опять же последнее число не будет включено в последовательность." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "6\n", "7\n" ] } ], "source": [ "for i in range(5, 8):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Также есть возможность проинициализировать `range` с тремя аргументами, и последним аргументом будет шаг. В данном случае это проще всего понять на примере. Мы итерируемся по числам от одного до десяти с шагом два, и на экран выводятся только нечетные числа, потому что мы перескакиваем по два." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "3\n", "5\n", "7\n", "9\n" ] } ], "source": [ "for i in range(1, 10, 2):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Также есть возможность итерироваться по числам в обратном порядке. Для этого в качестве шага объекту range нужно передать −1. На примере видно, что мы от десяти до пяти, опять же пять не включительно, в обратном порядке прогулялись." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "9\n", "8\n", "7\n", "6\n" ] } ], "source": [ "for i in range(10, 5, -1):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Перейдем к оператору `pass`. Оператор `pass` — это оператор, определяющий пустой блок, который ничего не делает. В основном на практике вы будете использовать этот оператор в качестве заглушки на время, пока вам не нужно писать код в каком-то блоке, но потом вы к нему вернетесь и замените оператор `pass` на что-то более полезное. Однако иногда для создания простых классов-наследников оператор `pass` может играть и полезную роль. Об этом вам ещё будет рассказываться в следующих лекциях. На примере мы можем посмотреть, `for i in range(100)`, `pass`, то есть мы итерируемся по числам и не делаем ничего в блоке цикла." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "for i in range(100):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Следующий оператор, на который мы посмотрим — это оператор `break`. Оператор `break` позволяет выйти из цикла досрочно. Что это значит? Давайте посмотрим на простом примере.\n", "\n", "У нас есть цикл `while True`, это бесконечный цикл, потому что условие всегда `True`, и он работал бы бесконечно, потребляя ресурсы процессора, если бы не наш оператор `break`, который мы вставили в код. Он отработает тогда, когда переменная `result` становится больше 100. Это позволяет выйти из цикла `while`, и выполнение программы достигает выражения `print(result)` и мы видим результат выполнения. " ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100\n" ] } ], "source": [ "result = 0\n", "\n", "while True:\n", " result += 1\n", " if result >= 100:\n", " break\n", "\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Оператор `break` также работает и в циклах `for`, то есть если мы используем `break` внутри `for`, мы выходим из `for`." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for i in range(10):\n", " if i == 5:\n", " break\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Также давайте посмотрим на оператор `continue`. Оператор `continue` позволяет перейти к следующей итерации в блоке цикла, не выполняя оставшиеся инструкции. Что это значит? Например, у нас есть задача сложить все числа от нуля до девяти, и при этом сложить только четные числа. С помощью `continue` мы можем реализовать это вот так, как вы видите на примере, то есть тогда, когда переменная `i` является нечетным числом, мы пишем `continue` и переходим к следующей итерации цикла `for`. Тем самым в `result` суммируются только четные числа, и мы получаем правильный ответ." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20\n" ] } ], "source": [ "result = 0\n", "\n", "for i in range(10):\n", " if i % 2 != 0:\n", " continue\n", " result += i\n", "\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выберите варианты, в которых цикл будет работать бесконечно:\n", "\n", "- [x] Вариант первый:\n", "\n", "```python\n", "while True:\n", " continue\n", "```\n", "\n", "- [x] Вариант второй:\n", "\n", "```python\n", "while True:\n", " pass\n", "```\n", "\n", "- [ ] Вариант третий:\n", "\n", "```python\n", "while True:\n", " break\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Так же для `for` и `while` есть `else` который срабатывает по окончанию, но не сработает если был использован `break`." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "while\n", "else\n" ] } ], "source": [ "flag = True\n", "\n", "while flag:\n", " print(\"while\")\n", " flag = False\n", " \n", "else:\n", " print(\"else\")" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "while\n" ] } ], "source": [ "flag = True\n", "\n", "while flag:\n", " print(\"while\")\n", " break\n", " \n", "else:\n", " print(\"else\")" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "for\n", "else\n" ] } ], "source": [ "for i in range(1):\n", " print(\"for\")\n", " \n", "else:\n", " print(\"else\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "for\n" ] } ], "source": [ "for i in range(1):\n", " print(\"for\")\n", " break\n", " \n", "else:\n", " print(\"else\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь, когда мы рассмотрели все основные конструкции управления потоком, мы можем попробовать применить их на практике и написать небольшую программу, которая будет содержать их в себе. Давайте это сделаем.\n", "\n", "[Далее...](Пример%20на%20управление%20потоком.ipynb)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.12" } }, "nbformat": 4, "nbformat_minor": 4 }