{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Объектно-ориентированное программирование и информационная безопасность\n",
    "\n",
    "*Валерий Семенов, Самарский университет*\n",
    "\n",
    "<div style=\"text-align:center\"><img src=\"Python.png\" width=\"200\"></div>\n",
    "\n",
    "\n",
    "<h1 style=\"text-align:center; margin-top:60px\">Функции</h1>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\"><strong>Функции</strong> в Python — это один из основных инструментов для создания удобного и структурированного кода. Они позволяют группировать набор инструкций, которые выполняют определенную задачу, и использовать их многократно в вашей программе. </div>\n",
    "\n",
    "<div style=\"text-align:center\"><img src=\"fun.png\" width=\"600\"></div>\n",
    "\n",
    "<h2 style=\"text-align:center; margin-top:60px\">Создание функции</h2>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Для создания функции используется ключевое слово <strong>def</strong>, за которым следует <strong><i>имя функции</i></strong> и круглые скобки <strong>()</strong>. В скобках указываются <strong><i>параметры функции</i></strong> (если они есть), а после скобок ставится двоеточие <strong>:</strong>. Тело функции записывается с отступом.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Пример простой функции без параметров:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greet():\n",
    "    print(\"Hello, world!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"text-align:center; margin-top:20px\">Вызов функции</h2>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Чтобы вызвать функцию, достаточно написать ее имя с круглыми скобками <strong>()</strong> в любом месте кода:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, world!\n"
     ]
    }
   ],
   "source": [
    "greet()   # Выведет \"Hello, world!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Функция, которая ничего не делает\n",
    "# Определение функции\n",
    "def do_nothing(): \n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Вызов функции\n",
    "do_nothing()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"text-align:center; margin-top:20px\">Функция с параметрами</h2>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Функция в Python - объект, принимающий аргументы и возвращающий значение. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Пример функции с параметрами:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Определение функции\n",
    "def func(a, b):\n",
    "    print(a+b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "func(2,3)  # Вызов функции"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "string\n"
     ]
    }
   ],
   "source": [
    "func('str', 'ing') # Вызов функции"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x,y):\n",
    "    if x > y: print(x)\n",
    "    else: print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "f(3,4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Функция может и не заканчиваться инструкцией <strong>return</strong>, при этом функция вернет значение <strong>None</strong>:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(f(3,4))  # Эта функция возвращает значение None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "a = f(3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "print(a) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"text-align:center; margin-top:20px\">Возвращение значения</h2>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Функция может возвращать значение (значения) с помощью ключевого слова <strong>return</strong>. Значение, следующее после <strong>return</strong>, будет результатом работы функции.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Инструкция <strong>return</strong> осуществляет выход из функции и передает управление и полученное значение в то место, откуда она была вызвана.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!).</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "def add(a, b):\n",
    "    return a + b\n",
    " \n",
    "result = add(2, 3)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x,y):\n",
    "    if x > y: return x\n",
    "    else: return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "a = f(3,4)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def func(a,b):\n",
    "    return a**b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func(2,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"text-align:center; margin-top:20px\">Аргументы функции</h2>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Функция может принимать произвольное количество аргументов или не принимать их вовсе. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\">Также распространены функции с произвольным числом аргументов, функции с позиционными и именованными аргументами, обязательными и необязательными.</div>\n",
    "\n",
    "\n",
    "<h3 style=\"text-align:center; margin-top:20px\">Позиционные аргументы</h3>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Все ранее написанные нами функции имели <i>позиционные</i> аргументы. Такие аргументы передаются без указания имен. Они называются <strong><i>позиционными</i></strong>, потому что именно по позиции, расположению аргумента, функция понимает, какому параметру он соответствует.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим следующий код: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "def diff(x, y):\n",
    "    return x - y\n",
    "\n",
    "res = diff(10, 3)    # Используем позиционные аргументы\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">При вызове функции <strong>diff()</strong> первому параметру <strong>x</strong> будет соответствовать первый переданный аргумент = <strong>10</strong>, а второму параметру <strong>y</strong>  — второй аргумент = <strong>3</strong>.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">В Python можно использовать не только позиционные, но и именованные аргументы.</div>\n",
    "\n",
    "<h3 style=\"text-align:center; margin-top:20px\">Именованные аргументы</h3>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Аргументы, передаваемые с именами, называются <strong><i>именованными</i></strong>. При вызове функции можно использовать имена параметров из ее определения. Исключение составляют списки аргументов неопределенной длины, где используются аргументы со звездочкой (об этом чуть позже).</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим следующий код: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "def diff(x, y):\n",
    "    return x - y\n",
    "\n",
    "res = diff(x=10, y=3)   # Используем именованные аргументы\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Такой код по-прежнему выведет число 7. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\">При вызове функции <strong>diff()</strong> мы явно указываем, что параметру <strong>x</strong> соответствует аргумент <strong>10</strong>, а параметру <strong>y</strong> — аргумент <strong>3</strong>. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\"><strong>Использование именованных аргументов позволяет нарушать их позиционный порядок при вызове функции.</strong> </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\"><strong>Порядок упоминания именованных аргументов не имеет значения!</strong></div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Мы можем вызвать функцию <strong>diff()</strong> и так: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "res = diff(y=3, x=10)   # Используем именованные аргументы\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"border:groove; margin-top:20px; margin-left:80px; margin-right:80px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"margin-left:30px; font-size:larger; line-height:26px\"><img alt=\"\" src=\"nerd-face.png\" style=\"float: left; ; margin-right:20px\" width=\"30\"; height=\"30\"><strong>Возможность использования именованных аргументов — еще один повод давать параметрам значащие, а не однобуквенные имена.</strong> </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center; margin-top:20px\"><u>Когда стоит применять именованные аргументы?</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Каких-то строгих правил на этот счет не существует. Однако широко практикуется такой подход: если функция принимает больше трех аргументов, желательно хотя бы часть из них указать по имени. Особенно важно именовать значения аргументов, когда они относятся к одному типу, ведь без имен очень трудно понять, что делает функция с подобным вызовом.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции <strong>make_circle()</strong> для рисования круга:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_circle(x, y, radius, line_width, fill):\n",
    "    # Тело функции\n",
    "    return"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Вызвать такую функцию можно так:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(200, 300, 17, 2.5, True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Тут непросто понять, какие параметры круга задают числа <strong>200</strong>, <strong>300</strong> или <strong>17</strong>.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Сравните:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(x=200, y=300, radius=17, line_width=2.5, fill=True)  # Используем именованные аргументы"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Такой код читать значительно проще!</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Когда значение аргументов очевидно, можно их не именовать. Да, очевидность относительна, но обычно легко понять, что скрывается за значениями при вызове функции <strong>point3d(7, 50, 13)</strong> или <strong>rgb(7, 255, 45)</strong>. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\">В первом случае переданные аргументы – координаты точки в трехмерном пространстве, во втором – значения компонент <strong>red</strong>, <strong>green</strong>, <strong>blue</strong> некоторого цвета. Тут можно ориентироваться только на здравый смысл, жестких правил нет.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Мы уже сталкивались с именованными аргументами, когда вызывали функцию <strong>print()</strong>.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Приведенный ниже код, использует именованные аргументы <strong>sep</strong> и <strong>end</strong>:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "aaa*bbb##ccc()ddd\n",
      "eee123fffpython"
     ]
    }
   ],
   "source": [
    "print('aaa', 'bbb', sep='*', end='##')\n",
    "print('ccc', 'ddd', sep='()')\n",
    "print('eee', 'fff', sep='123', end='python')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Используя именованные аргументы <strong>sep</strong> и <strong>end</strong> можно не беспокоиться, какой из них указать первым.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Напомним, что значение по умолчанию для <strong>sep=' '</strong> (символ пробела),  а для <strong>end='\\n'</strong> (символ перевода строки).</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center; margin-top:20px\"><u>Комбинирование позиционных и именованных аргументов</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Мы можем вызывать функции, используя именованные и позиционные аргументы одновременно. Но <strong>позиционные значения должны быть указаны до любых именованных!</strong></div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Для вызова функции <strong>diff()</strong> используем следующий код:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res = diff(10, y=3)   # Используем сначала позиционный, затем именованный аргумент\n",
    "\n",
    "res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Работает как полагается, при этом параметру <strong>x</strong> соответствует значение <strong>10</strong>.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Зато приведенный ниже код:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (1182158178.py, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  Cell \u001b[1;32mIn[26], line 1\u001b[1;36m\u001b[0m\n\u001b[1;33m    res = diff(x=10, 3)   # Используем сначала именованный, затем позиционный аргумент\u001b[0m\n\u001b[1;37m                      ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "res = diff(x=10, 3)   # Используем сначала именованный, затем позиционный аргумент"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">приводит к возникновению ошибки <strong><i>SyntaxError: positional argument follows keyword argument</i></strong>.</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center; margin-top:20px\"><u>Необязательные аргументы</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Бывает, что какой-то параметр функции часто принимает одно и то же значение. Например, для функции <strong>print()</strong> создатели языка Python установили значения параметров <strong>sep</strong> и <strong>end</strong> равными символу пробела и символу перевода строки, поскольку эти значения используют наиболее часто.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Другим примером служит функция <strong>int()</strong> , преобразующая строку в число.</div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\">Она принимает два аргумента:</div>\n",
    "\n",
    "<div style=\" margin-left:50px\">\n",
    "<li style=\"text-align:justify\">первый аргумент - строка, которую нужно преобразовать в число;</li>\n",
    "<li style=\"text-align:justify\">второй аргумент - основание <a href=\"https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D1%81%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F\"><strong>системы счисления</strong></a>.</li>\n",
    "</div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify\">Это позволяет ей считывать числа в различных системах счисления.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Приведенный ниже код, преобразует двоичное число <strong>101</strong>:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num = int('101', 2)     # Аргумент 2 указывает на то, что число 101 записано в двоичной системе\n",
    "\n",
    "num"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Но чаще всего эта функция используется для преобразования строки чисел, записанных в десятичной системе счисления. Утомительно каждый раз писать <strong>10</strong> вторым аргументом. В таких ситуациях Python позволяет задавать некоторым параметрам значения по умолчанию. У функции <strong>int()</strong> второй параметр по умолчанию равен <strong>10</strong>, и потому можно вызывать эту функцию с одним аргументом. Значение второго подставится автоматически.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Чтобы задать значение параметра по умолчанию, в списке параметров функции достаточно после имени переменной написать знак равенства и нужное значение.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Параметры со значением по умолчанию идут последними, ведь иначе интерпретатор не смог бы понять, какой из аргументов указан, а какой пропущен, и для него нужно использовать значение по умолчанию.</div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим все то же определение функции <strong>make_circle()</strong>, которая рисует круг:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_circle(x, y, radius, line_width, fill):\n",
    "    # тело функции\n",
    "    return"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Предположим, что чаще всего нам нужно рисовать круг с шириной линии, равной 2, и с заливкой. </div>\n",
    "<div style=\"text-indent:30px; text-align:justify\">Поэтому логично установить данные значения в качестве значений по умолчанию:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_circle(x, y, radius, line_width=2, fill=True):\n",
    "    # тело функции\n",
    "    return"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Теперь для того, чтобы нарисовать стандартный круг, то есть круг имеющий ширину линии, равную 2 с заливкой, мы вызываем функцию так:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(100, 50, 20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">или так:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(x=100, y=50, radius=20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Если же вам захочется поменять ширину линии и заливку, то вы легко можете это сделать:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(x=100, y=50, radius=20, fill=False)                   # line_width=2, fill=False\n",
    "make_circle(x=100, y=50, radius=20, line_width=3)                 # fill=True, line_width=3\n",
    "make_circle(x=100, y=50, radius=20, line_width=5, fill=False)     # line_width=5, fill=False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center; margin-top:20px\"><u><strong>Примечания</strong></u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\"><u><strong>Примечание 1.</strong></u> При написании функций стоит указывать более важные параметры первыми. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\"><u><strong>Примечание 2.</strong></u> Именованные аргументы часто используют вместе со значениями по умолчанию. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\"><u><strong>Примечание 3.</strong></u> При вызове функции позиционные аргументы должны обязательно идти перед именованными аргументами. </div>\n",
    "\n",
    "<div style=\"text-indent:30px\"><u><strong>Примечание 4.</strong></u> Параметр в программировании — принятый функцией аргумент. Термин «аргумент» подразумевает, что конкретно и какой конкретной функции было передано, а параметр — в каком качестве функция применила это принятое. То есть вызывающий код передает аргумент в параметр, который определен в описании (заголовке) функции.</div>\n",
    "\n",
    "<table style=\"border:groove; margin-top:20px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"text-indent:30px; font-size:larger; line-height:26px\"><strong>Параметр</strong> - <i>формальное значение</i>, которое принадлежит функции и используется в теле функции. </div>\n",
    "            <div style=\"text-indent:30px; font-size:larger\"><strong>Аргумент</strong> - <i>фактическое значение</i>, которое передается при вызове функции. </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3 style=\"text-align:center; margin-top:40px\">Функции с переменным количеством аргументов</h3>\n",
    "\n",
    "<table style=\"border:groove; margin-top:20px; margin-left:80px; margin-right:80px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"margin-left:30px; font-size:larger; line-height:26px\"><img alt=\"\" src=\"nerd-face.png\" style=\"float: left; ; margin-right:20px\" width=\"30\"; height=\"30\">В программировании функции с переменным числом аргументов называются <strong>вариативными</strong>. </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>\n",
    "\n",
    "\n",
    "<h4 style=\"text-align:center\"><u>Переменное количество аргументов</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Вспомним функцию <strong>print()</strong>, которой мы пользуемся почти в каждой задаче. </div>\n",
    "<div style=\"text-indent:30px; text-align:justify\">Функция <strong>print()</strong> принимает столько аргументов, сколько ей передано. Причем эта функция делает полезную работу, даже когда вызывается вообще без аргументов. В этом случае она переносит каретку печати на новую строку. </div>\n",
    "                                                                                                                        \n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Пример:</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "a b\n",
      "a b c\n",
      "a b c d\n"
     ]
    }
   ],
   "source": [
    "print('a')\n",
    "print('a', 'b')\n",
    "print('a', 'b', 'c')\n",
    "print('a', 'b', 'c', 'd')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Было бы полезно научиться писать свои собственные функции, способные принимать переменное количество аргументов. Для этого потребуется специальный, совсем не сложный во всех смыслах, синтаксис. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции <strong>my_func()</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'tuple'>\n",
      "()\n",
      "<class 'tuple'>\n",
      "(1, 2, 3)\n",
      "<class 'tuple'>\n",
      "('a', 'b')\n"
     ]
    }
   ],
   "source": [
    "def my_func(*args):\n",
    "    print(type(args))\n",
    "    print(args)\n",
    "\n",
    "\n",
    "my_func()\n",
    "my_func(1, 2, 3)\n",
    "my_func('a', 'b')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">В заголовке функции <strong>my_func()</strong> указан всего один параметр <strong>args</strong>, но со звездочкой перед ним. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\"><strong>Звездочка в определении функции означает, что переменная (параметр) <strong>args</strong> получит в виде кортежа все аргументы.</strong></div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">При описании функции можно использовать только один параметр помеченный звездочкой, причем располагаться он должен в конце списка параметров, иначе последующим параметрам не достанется значений. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Приведенный ниже код, не является рабочим, так как параметр со звездочкой в заголовке функции указан раньше позиционного <strong>num</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "my_func() missing 1 required keyword-only argument: 'num'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[35], line 5\u001b[0m\n\u001b[0;32m      2\u001b[0m     \u001b[38;5;28mprint\u001b[39m(args)\n\u001b[0;32m      3\u001b[0m     \u001b[38;5;28mprint\u001b[39m(num)\n\u001b[1;32m----> 5\u001b[0m my_func(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m, \u001b[38;5;241m3\u001b[39m)\n",
      "\u001b[1;31mTypeError\u001b[0m: my_func() missing 1 required keyword-only argument: 'num'"
     ]
    }
   ],
   "source": [
    "def my_func(*args, num):  # Неправильная запись заголовка функции!\n",
    "    print(args)\n",
    "    print(num)\n",
    "\n",
    "my_func(1, 2, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Другой пример: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('Python', 2, 'C#')\n",
      "17\n"
     ]
    }
   ],
   "source": [
    "def my_func(num, *args):\n",
    "    print(args)\n",
    "    print(num)\n",
    "\n",
    "my_func(17, 'Python', 2, 'C#')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Приведенный выше код связывает с переменной <strong>num</strong> значение <strong>17</strong>, а с переменной <strong>args</strong> значение кортежа <strong>('Python', 2, 'C#')</strong>.\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; text-align:justify; margin-top:20px\">Помеченный звездочкой параметр <strong>*args</strong> нормально переживает и отсутствие аргументов, в то время как позиционные параметры всегда обязательны. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Вот пример вызова функции, который связывает с переменной <strong>num</strong> значение <strong>17</strong>, а с переменной <strong>*args</strong> значение пустого кортежа <strong>()</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "()\n",
      "17\n"
     ]
    }
   ],
   "source": [
    "my_func(17)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\"><i><u>Обратите внимание:</u></i> функция <strong>my_func()</strong> принимает несколько аргументов, но как минимум один аргумент должен быть передан обязательно. Этот первый аргумент станет значением переменной <strong>num</strong>, а остальные аргументы сохранятся в переменной <strong>args</strong>. Подобным образом можно делать любое количество обязательных аргументов. </div>\n",
    "\n",
    "\n",
    "<table style=\"border:groove; margin-top:20px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"font-size:larger; line-height:26px\"><img alt=\"\" src=\"nerd-face.png\" style=\"float: left;\" width=\"30\"; height=\"30\">&nbsp;&nbsp;&nbsp;Параметр <strong>args</strong> в определении функции пишется после позиционных параметров перед первым параметром со значением по умолчанию. </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center\"><u>Передача аргументов в форме списка и кортежа</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Иногда хочется сначала сформировать набор аргументов, а потом передать их функции. Тут поможет оператор распаковки коллекций, который также обозначается звездочкой <strong>*</strong>. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Вспомним, что встроенная функция <strong>sum()</strong> принимает на вход коллекцию чисел (список, кортеж, и т.д). </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим пример: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10 100\n"
     ]
    }
   ],
   "source": [
    "sum1 = sum([1, 2, 3, 4])        # Считаем сумму чисел в списке\n",
    "sum2 = sum((10, 20, 30, 40))    # Считаем сумму чисел в кортеже\n",
    "\n",
    "print(sum1, sum2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Однако функция <strong>sum()</strong> не может принимать переменное количество аргументов. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Приведенный ниже код приводит к возникновению ошибки: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "sum() takes at most 2 arguments (5 given)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[39], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28msum\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m, \u001b[38;5;241m3\u001b[39m, \u001b[38;5;241m4\u001b[39m, \u001b[38;5;241m5\u001b[39m)\n",
      "\u001b[1;31mTypeError\u001b[0m: sum() takes at most 2 arguments (5 given)"
     ]
    }
   ],
   "source": [
    "sum(1, 2, 3, 4, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Напишем свою версию функции <strong>sum()</strong>, функцию <strong>my_sum()</strong>, которая принимает переменное количество аргументов и вычисляет их сумму: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "3\n",
      "6\n",
      "10\n"
     ]
    }
   ],
   "source": [
    "def my_sum(*args):\n",
    "    return sum(args)    # args - это кортеж\n",
    "\n",
    "print(my_sum())\n",
    "print(my_sum(1))\n",
    "print(my_sum(1, 2))\n",
    "print(my_sum(1, 2, 3))\n",
    "print(my_sum(1, 2, 3, 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Мы также можем вызывать нашу функцию функцию <strong>my_sum()</strong>, передавая ей списки или кортежи, предварительно распаковав их. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Например: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "print(my_sum(*[1, 2, 3, 4, 5]))   # Распаковка списка\n",
    "print(my_sum(*(1, 2, 3)))         # Распаковка кортежа"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Более того, часть аргументов можно передавать непосредственно и даже коллекции подставлять не только по одной. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Например: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "49\n"
     ]
    }
   ],
   "source": [
    "print(my_sum(1, 2, *[3, 4, 5], *(7, 8, 9), 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"border:groove; margin-top:20px; margin-left:80px; margin-right:80px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"margin-left:30px; font-size:larger; line-height:26px\"><img alt=\"\" src=\"nerd-face.png\" style=\"float: left; ; margin-right:20px\" width=\"30\"; height=\"30\">По соглашению, параметр, получающий подобный кортеж значений, принято называть <strong>args</strong> (от слова <i>arguments</i>). Старайтесь придерживаться этого соглашения. </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center\"><u>Получение именованных аргументов в виде словаря</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Позиционные аргументы можно получать в виде <strong>*args</strong>, причем произвольное их количество. Такая возможность существует и для именованных аргументов. Только именованные аргументы получаются в виде словаря, что позволяет сохранить имена аргументов в ключах. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции <strong>my_func()</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n",
      "{}\n",
      "<class 'dict'>\n",
      "{'a': 1, 'b': 2}\n",
      "<class 'dict'>\n",
      "{'name': 'Timur', 'job': 'Teacher'}\n"
     ]
    }
   ],
   "source": [
    "def my_func(**kwargs):\n",
    "    print(type(kwargs))\n",
    "    print(kwargs)\n",
    "\n",
    "my_func()\n",
    "my_func(a=1, b=2)\n",
    "my_func(name='Timur', job='Teacher')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">По соглашению параметр, получающий подобный словарь, принято называть <strong>kwargs</strong> (от словосочетания <strong><i>keyword arguments</i></strong>). Старайтесь придерживаться этого соглашения. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\">Параметр  <strong>**kwargs</strong> пишется в самом конце списка параметров, после последнего параметра со значением по умолчанию. При этом функция может содержать и <strong>*args</strong> и <strong>**kwargs</strong> параметры. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции, которая принимает все виды аргументов. </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2\n",
      "(3, 4)\n",
      "Timur 28\n",
      "{'job': 'Teacher', 'language': 'Python'}\n",
      "1 2\n",
      "()\n",
      "Timur 28\n",
      "{'job': 'Teacher', 'language': 'Python'}\n",
      "1 2\n",
      "(3, 4)\n",
      "Gvido 17\n",
      "{'job': 'Teacher', 'language': 'Python'}\n"
     ]
    }
   ],
   "source": [
    "def my_func(a, b, *args, name='Gvido', age=17, **kwargs):\n",
    "    print(a, b)\n",
    "    print(args)\n",
    "    print(name, age)\n",
    "    print(kwargs)\n",
    "\n",
    "my_func(1, 2, 3, 4, name='Timur', age=28, job='Teacher', language='Python')\n",
    "my_func(1, 2, name='Timur', age=28, job='Teacher', language='Python')\n",
    "my_func(1, 2, 3, 4, job='Teacher', language='Python')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Не нужно пугаться, в реальном коде функции редко используют все эти возможности одновременно. Но понимать, как каждая отдельная форма объявления параметров работает, и как такие формы сочетать — очень важно. </div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center\"><u>Передача именованных аргументов в форме словаря</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Как и в случае позиционных аргументов, именованные можно передавать в функцию \"пачкой\" в виде словаря. Для этого нужно перед словарём поставить две звёздочки. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции <strong>my_func()</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n",
      "{'name': 'Timur', 'age': '28', 'job': 'teacher'}\n"
     ]
    }
   ],
   "source": [
    "def my_func(**kwargs):\n",
    "    print(type(kwargs))\n",
    "    print(kwargs)\n",
    "\n",
    "info = {'name':'Timur', 'age':'28', 'job':'teacher'}\n",
    "\n",
    "my_func(**info)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим еще один пример определения функции <strong>print_info()</strong>, распечатывающей информацию о пользователе: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Имя: Меган\n",
      "Фамилия: Фокс\n",
      "Возраст: 34\n",
      "Город проживания: Ок-Ридж\n",
      "Дети: Бодхи Рансом Грин, Ноа Шэннон Грин, Джорни Ривер Грин\n",
      "{'height': 163, 'job': 'actress'}\n"
     ]
    }
   ],
   "source": [
    "def print_info(name, surname, age, city, *children, **additional_info):\n",
    "    print('Имя:', name)\n",
    "    print('Фамилия:', surname)\n",
    "    print('Возраст:', age)\n",
    "    print('Город проживания:', city)\n",
    "    if len(children) > 0:\n",
    "        print('Дети:', ', '.join(children))\n",
    "    if len(additional_info) > 0:\n",
    "        print(additional_info)\n",
    "\n",
    "children = ['Бодхи Рансом Грин', 'Ноа Шэннон Грин', 'Джорни Ривер Грин']\n",
    "additional_info = {'height':163, 'job':'actress'}\n",
    "\n",
    "print_info('Меган', 'Фокс', 34, 'Ок-Ридж', *children, **additional_info)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">При подстановке аргументов \"разворачивающиеся\" наборы аргументов вроде *positional и **named можно указывать вперемешку с аргументами соответствующего типа: *positional с позиционными, а **named — с именованными. И, конечно, же, все именованные аргументы должны идти после всех позиционных! </div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center\"><u>Keyword-only аргументы</u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">В Python 3 добавили возможность пометить именованные аргументы функции так, чтобы вызвать функцию можно было, только передав эти аргументы по именам. Такие аргументы называются keyword-only и их нельзя передать в функцию в виде позиционных. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Рассмотрим определение функции <strong>make_circle()</strong>: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_circle(x, y, radius, *, line_width=1, fill=True): pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify\">Здесь <strong><i>звездочка</i> (*)</strong> выступает разделителем - отделяет обычные аргументы (их можно указывать по имени и позиционно) от строго именованных. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">То есть аргументы <strong>x</strong>, <strong>y</strong> и <strong>radius</strong> могут быть переданы как в качестве позиционных, так и именованных аргументов. При этом аргументы <strong>line_width</strong> и <strong>fill</strong> могут быть переданы только как именованные аргументы. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Приведенный ниже код работает как и полагается (ничего не делает, не вызывает ошибку): </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "make_circle(10, 20, 5)                                     # x=10, y=20, radius=5,  line_width=1, fill=True\n",
    "make_circle(x=10, y=20, radius=7)                          # x=10, y=20, radius=7,  line_width=1, fill=True\n",
    "make_circle(10, 20, radius=10, line_width=2, fill=False)   # x=10, y=20, radius=10, line_width=2, fill=False\n",
    "make_circle(x=10, y=20, radius=17, line_width=3)           # x=10, y=20, radius=17, line_width=3, fill=True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Зато следующий код приводит к возникновению ошибок: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (22430930.py, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  Cell \u001b[1;32mIn[49], line 2\u001b[1;36m\u001b[0m\n\u001b[1;33m    make_circle(x=10, y=20, 15, True)\u001b[0m\n\u001b[1;37m                                    ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "make_circle(10, 20, 15, 20)\n",
    "make_circle(x=10, y=20, 15, True)\n",
    "make_circle(10, 20, 10, 2, False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Этот пример неплохо демонстрирует подход к описанию аргументов. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Первые три аргумента — координаты центра круга и радиус. Координаты центра и радиус присутствуют у круга всегда, поэтому обязательны и их можно не именовать. А вот <strong>line_width</strong> и <strong>fill</strong> — необязательные аргументы, ещё и получающие ничего не говорящие значения. Вполне логично ожидать, что вызов вида <strong>make_circle(10, 20, 5, 3, False)</strong> мало кому понравится! Поэтому ради ясности необязательные аргументы <strong>line_width</strong> и <strong>fill</strong>  и объявлены так, что могут быть указаны только явно через имя. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Мы также можем объявить функцию, у которой будут только <u>строго именованные аргументы</u>, для этого нужно поставить <strong><i>звездочку</i> (*)</strong> в самом начале перечня аргументов: </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\">Теперь для вызова функции <strong>make_circle()</strong> нам нужно передать значения всех аргументов явно через их имя: </div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_circle(*, x, y, radius, line_width=1, fill=True): pass\n",
    "\n",
    "make_circle(x=10, y=20, radius=15)                              # line_width=1, fill=True\n",
    "make_circle(x=10, y=20, radius=15, line_width=4, fill=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"border:groove; margin-top:20px; margin-left:80px; margin-right:80px\">\n",
    "    <tr>\n",
    "        <td style=\"background:LightCyan; height:60px\">\n",
    "            <div style=\"margin-left:30px; font-size:larger; line-height:26px\"><img alt=\"\" src=\"nerd-face.png\" style=\"float: left; ; margin-right:20px\" width=\"30\"; height=\"30\">Такой разделитель можно использовать только один раз в определении функции. Его нельзя применять в функциях с неограниченным количеством позиционных аргументов <strong>*args</strong>. </div>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4 style=\"text-align:center; margin-top:20px\"><u><strong>Примечания</strong></u></h4>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\"><u><strong>Примечание 1.</strong></u> Специальный синтаксис <strong>*args</strong> и <strong>**kwargs</strong> в определении функции позволяет передавать функции переменное количество позиционных и именованных аргументов. При этом <strong>args</strong> и <strong>kwargs</strong> просто имена. Вы не обязаны их использовать, можно выбрать любые, однако среди Python программистов приняты именно эти. </div>\n",
    "\n",
    "<div style=\"text-indent:30px; text-align:justify\"><u><strong>Примечание 2.</strong></u> Вы можете использовать одновременно <strong>*args</strong> и <strong>**kwargs</strong> в одной строке для вызова функции. В этом случае порядок имеет значение. Как и аргументы, не являющиеся аргументами по умолчанию, <strong>*args</strong> должны предшествовать и аргументам по умолчанию, и <strong>**kwargs</strong>. </div>\n",
    "    \n",
    "<div style=\"text-indent:30px; text-align:justify; margin-top:20px\"><u>Правильный порядок параметров: </u></div>\n",
    "\n",
    "<ol style=\" margin-left:20px\">\n",
    "<li style=\"text-align:justify\">Позиционные аргументы без значений по умолчанию.</li>\n",
    "<li style=\"text-align:justify\">Позиционные аргументы со значениями по умолчанию.</li>\n",
    "<li style=\"text-align:justify\">Позиционные аргументы, указанные как <strong>*args</strong>.</li>\n",
    "<li style=\"text-align:justify\">Именованные аргументы.</li>\n",
    "<li style=\"text-align:justify\">Именованные аргументы, указанные как <strong>**kwargs</strong>.</li>\n",
    "</ol>"
   ]
  }
 ],
 "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.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
