{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Базовые типы: объект None #"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Еще один важный объект, который стоит рассмотреть, это объект `None`.\n",
    "\n",
    "Объект `None` по большому счету является единственным значением специального типа `NoneType`, который используется для того, чтобы подчеркнуть отсутствие значения. Если вы знаете язык С, то вы можете рассматривать `None` как эквивалент нулевому указателю.\n",
    "\n",
    "В программах на Python'е вы будете часто видеть `None` как в чужом коде, так и будете использовать его в своем. Для того чтобы присвоить переменной `None`, мы можем написать просто `answer = None`. Ничего нового для вас в этом нет. Если мы посмотрим на тип `None`, то мы увидим, что это как раз класс `NoneType`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'NoneType'>\n"
     ]
    }
   ],
   "source": [
    "answer = None\n",
    "print(type(None))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Однако обратите внимание, что с классом `NoneType` вам работать не придется, по большому счету вы работаете только с единственным значением, которое представляет собой объект `None`. Важно отметить, что при преобразовании `None` к типу `bool` всегда получается `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool(None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Поэтому если переменная равна `None` и мы используем условный оператор, `if not answer` всегда будет выполняться, потому что `if not answer` будет всегда `True`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ответ не получен\n"
     ]
    }
   ],
   "source": [
    "answer = None\n",
    "\n",
    "if not answer:\n",
    "    print(\"Ответ не получен\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте посмотрим на примере, когда `None` может потребоваться в коде. Предположим, у нас есть программа, в которой мы рассчитываем какой-то доход, доход от продаж чего-либо, неважно чего. Предположим, у нас доход, который лежит в переменной `income`, равен нулю. Тогда в коде мы могли бы написать `if not income` и напечатать на экран \"Ничего не заработали\". Если у нас доход ноль, то мы ничего не заработали."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ничего не заработали\n"
     ]
    }
   ],
   "source": [
    "income = 0\n",
    "\n",
    "if not income:\n",
    "    print(\"Ничего не заработали\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Однако предположим, что нам нужно подчеркнуть такую ситуацию, что мы еще даже не начинали продавать. Конечно же, до начала продаж доход всегда будет равен нулю. В этот момент может пригодится `None`. Мы присваиваем переменной `income` значение `None`, и после этого в условиях сравнения мы можем проверять, что если `income` является объектом `None`, то тогда печатаем на экран что мы еще даже не начинали продавать. Иначе — `elif not income`, — иначе если у нас в переменной `income` ноль, то мы и печатаем доход ноль, мы ничего не заработали. В данном случае важно отметить, что мы проверяем равенство переменной `income` объекту `None` с помощью оператора `is`. Это идиоматичный способ проверки соответствия переменной объекту `None` в Python'е. Мы могли бы, конечно, написать `if income == None`, но это неидиоматично в Python, потому что в Python'е оператор `==` можно переопределить с помощью магических методов, и мы это увидим в дальнейшем, что такое магические методы у классов."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Еще не начинали продавать\n"
     ]
    }
   ],
   "source": [
    "income = None\n",
    "\n",
    "if income is None:\n",
    "    print(\"Еще не начинали продавать\")\n",
    "elif not income:\n",
    "    print(\"Ничего не заработали\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что еще можно сделать с `None`? `None` будет часто использоваться как значение именованного аргумента в функции, для того чтобы подчеркнуть, что аргумент функции является опциональным. Также значение `None` присваивается при инициализации классом всевозможным атрибутам, которые в дальнейшем могут быть перезаписаны каким-то полезным значением. Также `None` по умолчанию возвращается из функции, если вы самостоятельно явным образом ничего из функции не вернули с помощью конструкции `return`. Все эти слова про функции и про классы могут звучать для вас по-новому, но мы про все это расскажем в следующих лекциях нашего курса. Ну а пока вы познакомились с объектом `None`, который теперь вас не испугает, когда вы его увидите.\n",
    "\n",
    "[Далее...](Конструкции%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
}
