{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Базовые типы: логический тип #"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "На этой лекции мы поговорим о ещё одном базовом типе, который есть в Python, а именно о логическом типе, он же тип `bool`.\n",
    "\n",
    "В Python'е тип `bool` представлен двумя значениями, как и в других языках — это `True` и это `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что важно отметить, что в Python тип `bool` является подтипом целого числа, и, по большому счету `True` — это `True` соответствует единице, а `False` соответствует нулю. Если мы присвоим переменной `result` `True`, то, посмотрев на тип переменной, мы увидим, что это как раз тип `bool`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'bool'>\n"
     ]
    }
   ],
   "source": [
    "result = True\n",
    "print(type(result))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Когда нужны логические типы? По большому счету они нужны тогда, когда нужно проверить на истинность какое-то выражение — является выражение истинным либо является выражение ложью.\n",
    "\n",
    "Например, в Python'е мы можем проверить, что значения двух объектов равны. Это делается с помощью оператора «равно». Это два знака равно, идущие друг за другом."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "13 == 13"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Также есть оператор «не равно», который позволяет сделать противоположное действие, то есть сравнить то, что значения не равны. Обратите внимание, что результатом выполнения обоих выражений являются логические типы — либо `True`, либо `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 != 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Операторы сравнения ##\n",
    " - `>` больше;\n",
    " - `>=` больше или равно;\n",
    " - `<` меньше;\n",
    " - `<=` меньше или равно."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(3 >  3)\n",
    "print(3 >= 3)\n",
    "print(6 <  7)\n",
    "print(6 <= 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "И также интересной особенностью является наличие в Python'е множественного сравнения."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "x = 2\n",
    "print(1 < x < 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Мы объявляем переменную `x`, которая равна целому числу 2. Дальше записываем множественное сравнение, которое в итоге выдает результат `True`, потому что `x > 1`, и в то же время `x < 3`. Это очень удобно бывает на практике."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Конвертация типов ##\n",
    "\n",
    "Если мы попробуем преобразовать целое число к типу `bool`, то есть к логическому типу, то если число не равняется нулю, то получим в результате `True`, если 0, то `False`. То же самое верно для вещественных чисел."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool(12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool(-4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool(.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Поговорим о логических выражениях.\n",
    "\n",
    "Логические выражения — это выражения, которые содержат в себе один или больше логических операторов. Какие мы знаем логические операторы? Это может быть логическое «и», логическое «или» или, например, логическое отрицание.\n",
    "\n",
    "В Python'е представлены все эти операторы и, например, логическое «и» записывается с помощью слова `and`.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "x, y = True, False\n",
    "print(x and y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Также есть логическое «или» — это оператор `or`. И есть логическое отрицание — это оператор `not`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "x, y = True, False\n",
    "print(x or y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "y = False\n",
    "print(not y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Мы можем составлять сложные логические выражения, в которые будут входить несколько логических операторов. При этом в этом логическом выражении у операторов есть свой приоритет, порядок исполнения, как и в математических операциях. Стоит отметить, что этот порядок мы также можем задавать, используя круглые скобки, как и в случае с математическим выражением."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "x, y, z = True, False, True\n",
    "result = x and y or z\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Следующая особенность Python — это то, что логические выражения ленивые. Давайте подробно разберем это на примере. У нас есть переменная `x`, которая равняется 12 и переменная `y`, которая равняется `False`. И есть логическое выражение `x or y`. В результате работы этого выражения мы видим, что на экране не `True`, как мы могли бы ожидать, а число 12."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12\n"
     ]
    }
   ],
   "source": [
    "x = 12\n",
    "y = False\n",
    "\n",
    "print(x or y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что здесь происходит? Python начинает интерпретировать логическое выражение, видит, что `x` является истинным, и понимает, что ему не нужно выполнять оставшуюся часть логического выражения. Поэтому он y уже не будет проверять, `x` — это истина, оператор `or` стоит, значит нас устраивает то, что мы можем остановиться в этот момент и результатом выполнения выражения будет как раз значение `x`. На другом примере у нас есть переменная `x`, которая равна 12, и переменная `z`, которая равна строке `boom`. В результате работы логического выражения `x and z` мы получаем как результат работы логического выражения строку `boom`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "boom\n"
     ]
    }
   ],
   "source": [
    "x = 12\n",
    "z = \"boom\"\n",
    "\n",
    "print(x and z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Происходит все то же самое. Python выполняет логическое выражение, до тех пор, пока оно имеет смысл, и результатом является последнее значение.\n",
    "\n",
    "Посмотрим небольшой пример — задачу, определить високосный год или нет. Существует такое правило, которое позволяет понять, является ли год високосным или нет. Год является високосным, если он кратен 4, но при этом не кратен 100, либо кратен 400. Звучит достаточно запутанно, однако решение всего в три строчки и как раз с помощью логических выражений. Мы объявляем переменную, которая содержит в себе год и далее составляем сложное логическое выражение, включающее в себя несколько логических операторов. При этом задаем порядок выполнения операторов скобками, обратите внимание. И что стоит отметить — то, что это то, о чем я говорил. Если год не кратен четырем, то есть первое выражение не является истинным, то логическое выражение не будет выполняться дальше, Python в этот момент остановится. Если же оно истинное, то выполнение логического выражения продолжится. Ну и мы получаем ответ. В данном случае 2017 год не является високосным."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "year = 2017\n",
    "\n",
    "is_leap = year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)\n",
    "\n",
    "print(is_leap)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что стоит отметить — это то, что эту задачку мы могли бы решить ещё короче, всего в две строчки, используя модуль стандартной библиотеки `calendar`. Как принято говорить, Python — это «батарейки включены», то есть это язык, который предоставляет очень много возможностей в своей стандартной библиотеке. Так что библиотеку языка ставят в пример многим другим языкам программирования. Соответственно, есть модуль «календарь», который мы можем импортировать, и внутри модуля календарь есть функция `isleap`, которая делает как раз то, что нам нужно. Мы, например, можем убедиться, что 1980-й год был високосным. Про импорты мы ещё с вами будем говорить в дальнейшем."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "from calendar import isleap\n",
    "\n",
    "print(isleap(1980))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "На этой лекции мы поговорили про логический тип в Python, тип `bool`, рассмотрели логические операторы, а также посмотрели на составные логические выражения.\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
}
