From c16234dc07ba4091774dc3035c8acf9c1ad84495 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 5 Jan 2026 03:40:56 +0500 Subject: [PATCH 01/24] Add log1 notebook and scripts, update pre-commit config --- .pre-commit-config.yaml | 2 +- log1.ipynb | 40 +++++++ log1.py | 9 ++ std out | 223 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 log1.ipynb create mode 100644 log1.py create mode 100644 std out diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6341a1aa..5c83b8cf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - --warn-only exclude: '.*\.md$' - repo: https://github.com/PyCQA/docformatter - rev: "eb1df347edd128b30cd3368dddc3aa65edcfac38" + rev: "v1.7.7" hooks: - id: docformatter args: [--in-place, --wrap-descriptions=120, --style=google] diff --git a/log1.ipynb b/log1.ipynb new file mode 100644 index 00000000..c128217b --- /dev/null +++ b/log1.ipynb @@ -0,0 +1,40 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a5c7f761", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Module for logging experiment results.\n", + "\n", + "This notebook contains utilities for logging and analysis.\n", + "\"\"\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "33ff615f", + "metadata": {}, + "source": [ + "04/01\n", + "1. Закончила выполнение intro, c Cursor разобралась\n", + "2. Начала проходить курс по Python\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/log1.py b/log1.py new file mode 100644 index 00000000..982cf884 --- /dev/null +++ b/log1.py @@ -0,0 +1,9 @@ +"""Module for logging experiment results. + +This notebook contains utilities for logging and analysis. +""" + +# 04/01 +# 1. Закончила выполнение intro, c Cursor разобралась +# 2. Начала проходить курс по Python +# diff --git a/std out b/std out new file mode 100644 index 00000000..e2af5261 --- /dev/null +++ b/std out @@ -0,0 +1,223 @@ +commit 1fc080684dc2f3926711adaa8d482161a286881e (HEAD -> main, upstream/main, upstream/HEAD, origin/main, origin/HEAD) +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Dec 18 01:18:34 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 8458cf2836320fd4d75a9d1332044763b899d694 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Dec 18 01:16:03 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit e9d9583ad3166caf442036fd51bbd5e9e1b05d9e +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Dec 18 01:15:41 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 4f8a6e28b1047889e0e72a611bdbc48de7c5c7b9 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Dec 18 01:14:31 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 07bc4ad4bf9714212e60368c45870befd81a3743 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Sat Dec 13 16:37:45 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 0589cd0d4d243de3676cca8e378d3469b4c14de5 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Sat Dec 13 16:36:53 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit c5f8f9d6264ceca49faf075b8affbc84eb2a8418 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Mon Dec 1 03:42:45 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 79ac80d08c6e2826fd2f4506bfe873db1eb3cb67 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Fri Nov 28 19:02:14 2025 +0300 + + 120 + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 7d9f06351f04884e4f16bde85c4db8c2e45dd152 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:27:45 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 4e07c9d220c04a03d341551bdb94d687e978d506 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:25:50 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit dc3d33b66fb63a1ca68c43bd25d51344caf0f277 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:22:40 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 1ed30fa45a59e77ee9a96594bc3b1ddbf99fa5b5 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:22:19 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 0d397a8b39e8f3560e76c25d2637a5bbdde542a5 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:21:03 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 11f63e86bb45becb7affabfdde03cb6b5a672b67 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:19:36 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 1e9438a397d34c2f296fca3e19ee6404929f7711 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:14:14 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit fd4e5a1fee92c7ef330f727fcf6fbb4e25ad9fea +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:12:53 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 0d77ab2dfda6a798de21ddff25d98d6c409aabee +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Tue Nov 25 04:09:56 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit db1ec3f5139ff9b5fa941df2fc8b8bf1bb82c832 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Sun Nov 23 22:36:24 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit f729a1cc82bbec2c6666c5bbf7c110c6020a469d +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 16:39:42 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 9ecfbec0409ad19c8b118a46fd2a0242d5d06204 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 16:38:10 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit f71a705e33426c28abd34dcc61a382144935cb9c +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 16:33:56 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 60a6d291d1f2991be09b8e8e0c6d6a0c5c553615 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 16:07:55 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 2750d42c4919f5847a71970d506b84c6d7cd6533 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:55:23 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit b089c54231bc8635cba75a2072428a207790c198 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:45:49 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit c63b0d91bc854f0bff8cf788521099e39a40bd9e +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:39:18 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit fc07c2af1c6f44e8e6739c562f28fa08c87d563e +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:33:02 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 2a17b416637022b87b9a12ba519e7496139d1ac5 +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:24:53 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> + +commit 0ab494ffe89725095c20db976c31bc9c2d301b8f +Author: Ruslan Senatorov <55090151+ruslansenatorov@users.noreply.github.com> +Date: Thu Nov 6 15:19:22 2025 +0300 + + Update README.md + + Signed-off-by: Ruslan Senatorov <55090151+ruslanse \ No newline at end of file From 9f100e3117a44f8904cee7495e91841a72961ef6 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Thu, 8 Jan 2026 04:03:27 +0500 Subject: [PATCH 02/24] [TASK] Quiz #6 (https://github.com/SENATOROVAI/intro-cs/issues/6) Closes https://github.com/SENATOROVAI/intro-cs/issues/6 --- log.ipynb | 71 +++++++++++ log.py | 11 ++ log1.ipynb | 40 ------ log1.py | 9 -- quiz1.ipynb | 208 +++++++++++++++++++++++++++++++ quiz1.py | 158 ++++++++++++++++++++++++ quiz2.ipynb | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++ quiz2.py | 297 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 1095 insertions(+), 49 deletions(-) create mode 100644 log.ipynb create mode 100644 log.py delete mode 100644 log1.ipynb delete mode 100644 log1.py create mode 100644 quiz1.ipynb create mode 100644 quiz1.py create mode 100644 quiz2.ipynb create mode 100644 quiz2.py diff --git a/log.ipynb b/log.ipynb new file mode 100644 index 00000000..3704f784 --- /dev/null +++ b/log.ipynb @@ -0,0 +1,71 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "a5c7f761", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Module for logging experiment results.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Module for logging experiment results.\"\"\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "33ff615f", + "metadata": {}, + "source": [ + "04/01\n", + "1. Закончила выполнение intro, c Cursor разобралась.\n", + "2. Начала проходить курс по Python.\n" + ] + }, + { + "cell_type": "markdown", + "id": "f6cb4978", + "metadata": {}, + "source": [ + "7/01\n", + "1. Выполнила quiz 1 b quiz 2" + ] + }, + { + "cell_type": "markdown", + "id": "3ceda156", + "metadata": {}, + "source": [] + } + ], + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/log.py b/log.py new file mode 100644 index 00000000..b3bfb8fd --- /dev/null +++ b/log.py @@ -0,0 +1,11 @@ +"""Module for logging experiment results.""" + +# 04/01 +# 1. Закончила выполнение intro, c Cursor разобралась. +# 2. Начала проходить курс по Python. +# + +# 7/01 +# 1. Выполнила quiz 1 b quiz 2 + +# diff --git a/log1.ipynb b/log1.ipynb deleted file mode 100644 index c128217b..00000000 --- a/log1.ipynb +++ /dev/null @@ -1,40 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "a5c7f761", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"Module for logging experiment results.\n", - "\n", - "This notebook contains utilities for logging and analysis.\n", - "\"\"\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "33ff615f", - "metadata": {}, - "source": [ - "04/01\n", - "1. Закончила выполнение intro, c Cursor разобралась\n", - "2. Начала проходить курс по Python\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/log1.py b/log1.py deleted file mode 100644 index 982cf884..00000000 --- a/log1.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Module for logging experiment results. - -This notebook contains utilities for logging and analysis. -""" - -# 04/01 -# 1. Закончила выполнение intro, c Cursor разобралась -# 2. Начала проходить курс по Python -# diff --git a/quiz1.ipynb b/quiz1.ipynb new file mode 100644 index 00000000..f1e7afec --- /dev/null +++ b/quiz1.ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "839d001a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Quiz 1.'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Quiz 1.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "7c4ea25e", + "metadata": {}, + "source": [ + "Список вопросов к видео https://youtu.be/hW_7hodGxVU?si=tCEVs00xGt2q61eW (АЛГОРИТМ ПРИНЯТИЯ И ОТДАЧИ ДОМАШКИ):\n", + " \n", + "(По желанию )В ответе подробно всё опишите и обязательно нужно указывать тайм код из видео где я это сказал, по желанию, дополнительно прикладываем скриншот из видео.\n", + "Если вы знаете ответы на вопросы из Вашего опыта, то таймкоды из видео не надо указывать и т.д.\n", + "\n", + "1) Как понять, что домашка пришла?\n", + "В чате homework будет сообщение @а прими пул\n", + "2) Как принять домашку?\n", + "Заходим а Гитхаб десктоп, нажимаем Fetch origin, заходим в history и смотрим самый верхний коммит.\n", + "3) Зачем нужна кнопка history и какие функции появляются при нажатии правой кнопки мыши на коммит?\n", + "Кнопка history показывает коммиты. Если нажать правой кнопкой на коммит, то выйдет контекстное меню. \n", + "\n", + "3.1) Где брать ссылку на коммит? куда её отправлять? \n", + "Ссылку брать с Гитхаба и отправлять в чат homework, пишем \"Коммит отдал\"\n", + "4) Что такое файл лога? \n", + "В файле лога нужно заполнять в конце каждого урока. В этом файле нужно писать дату и что запомнилось в течение урока. \n", + "4.1) Когда нужно его пушить?\n", + "После заполнения и проверки на ошибки.\n", + "5) Что такое интерпритатор? \n", + "Это программа, которая построчно выполняет команды, написанные на языке программирования. \n", + "6) Где можно выбрать интерпритатор?\n", + "В правом верхнем углу. \n", + "7) Что такое модуль? \n", + "Это файл с расширением .py или .ipynb.\n", + "8) Как создать и отправить коммит?\n", + "Создать файл с расширением .ipynb, заполнить, проверить на ошибки, Commit&sync, Commit&push\n", + "9) Как посмотреть что коммит точно отправлен и находится в github?\n", + "Коммит должен быть виден на гитхабе и в Hidtory в кошке. \n", + "10) Какая команда показывает что код не прошёл проверки на ошибки? \n", + "Команда в терминале pre-commit run --all-files\n", + "10.1) Напишите список линтеров которые используются для проверки кода и дайте их краткую характеристику.\n", + "Mypy - проверяет типы\n", + "Pylint - проверяет соответствие стандартам кодирования.\n", + "Pydocstyle - ищет отсутствие docstring\n", + "Flake8 - обнаруживает стилистические ошибки\n", + "\n", + "\n", + "11) Как узнать какой именно линтер не прошёл проверку?\n", + "При проверке через терминал командой pre-commit run --all-files выйдет статус Failed.\n", + "12) Линтер Pylint видит markdown?\n", + "нет\n", + "13) Номер ячейки в терминале и номер ячейки в vs code может отличаться? в каком случае?\n", + "Может. Линтер не видит ячейки markdown.\n", + "14) Где посмотреть номер ячейки в vscode?\n", + "Можно посмотреть внизу справа. \n", + "15) В каком формате ipynb отправляется в гитхаб? причём здесь JSON?\n", + "Файлы ipynb отпраляются на гитхаб в формате JSON.\n", + "16) Где посмотреть в какой ячейке ошибка?\n", + "По коду ошибки или Ctrl+F.\n", + "17) Как запустить терминал?\n", + "Terminal - New Terminal\n", + "18) Что такое линтер?\n", + "Это программа, которая проверяет файл на корректность.\n", + "19) В какой сайт нужно вставлять код ошибки если ошибка связана с pylint?\n", + "На сайт pylint.readthedocs.io\n", + "20) Секция pydocstyle в большинстве случае автоматический закрывается после исправления ошибок в каком линтере?\n", + "В pylint\n", + "21) Что такое описание модуля? Оно должно отражать информацию о том что находится в модуле?\n", + "Это описание того, что находится в модуле. Должно отражвть информацию о том, что находится в модуле. \n", + "21.1) С какой git команды начинается утро программиста?\n", + "С команды Fetch origin. \n", + "22) После внесения изменений в файлах, кнопка open in vs code пропадает в кошке, как по другому открыть vs code из кошки?\n", + "Нажать правой кнопкой на Current repository и выбрать open in VS code.\n", + "23) Что такое stash? \n", + " Общее объяснение концепции.\n", + " stash - буфер обмена, где можно спрятать локальные изменения. \n", + " Мы можем временно сохранить наши изменения, не коммитя их а репозиторий, для дальнейших изменений. \n", + "23.1) Как сохранить стэш?\n", + " git командa(подсказка: https://t.me/c/1937296927/3602/19531): \n", + "git stash save \"Name_stash\" - сохранение в буфер обмена\n", + "git stash apply \"Number_stash\" - извлечение из буфера обмена.\n", + " Кнопка в vs code:\n", + "Stash changes and continue\n", + "23.2) Как восстановить стэш(подсказка: https://t.me/c/1937296927/3602/25747)?:\n", + "\n", + "\n", + " git команда(подсказка: https://t.me/c/1937296927/3602/19531)?:\n", + "git stash apply \"Number_stash\"\n", + "23.3) Различие между стэшем и коммитом. \n", + " Когда лучше сохранить изменения в стэше, а когда коммитить.\n", + " Коммитить - когда мы завершили действия и можем вылоожить в ветку.\n", + " Стэшить - когда мы не завершили работу и хотим вернуться, чтобы доделать. \n", + "23.4) Как просмотреть список сохраненных стэшей? \n", + " git команда (подсказка: https://t.me/c/1937296927/3602/19531):\n", + "git stash list \n", + "23.5) Как удалить стэш? \n", + " Команды для удаления отдельных стэшей или всех сразу.\n", + " git команда (подсказка: https://t.me/c/1937296927/3602/19531):\n", + "git stash drop\n", + "git stash clean\n", + "23.6) Практические примеры использования стэша. \n", + " Краткие сценарии, где стэш помогает.\n", + "Спрятать изменения в моменте, когда нужно поработать над другой задачей\n", + "Спрятать измения, когда возник конфликт.\n", + "24) Где посмотреть что есть конфликт в файлах? \n", + "Рядом с файлом readme будет стоять треугольник с восклицательным знаком. Нажимаем Open in VS Code. Зеленым цветом будет выделено то, что с гитхаба, синим - локальные изменения. \n", + "24.1) Когда он появляется?\n", + "Когда в файле работвют одновременно два человека. \n", + "25) Как решить конфликт в файлах?\n", + "Нажать Reserve in Merge Editor, Complete Merge. \n", + "26) Напишиие правильное утверждение\n", + "-Зелёное то что пришло с гитхаба и синее локальные изменения или синее то что пришло с гитхаба и зелёное это локальные изменения \n", + "Зеленое - с гитхаба\n", + "Синее - локальные изменения.\n", + "27) Если мы работаем в одном файле, можно ли принять pull после того как вы спрячете в стэш свои изменения? \n", + "да, можно.\n", + "27.1) Что может произойти когда stash восстановите после принятия pull?\n", + "Может произойти конфликт. \n", + "28) Сколько способов решения конфликтов было показано в видео? Напишите ЧИСЛО и укажите их способы.\n", + "2 способа\n", + "1 способ - с помощью Accept Incoming Change,Accept Current Change, Accept Both Changes\n", + "2 способ - вручную удалить то что не нужно. \n", + "29) Что делает кнопка complete merge?\n", + "Смерживает конечные изменения из конфликтов в один.\n", + "30) В какой чат нужно писать если остались вопросы?\n", + "в чат HELP ME\n", + "31) Что такое FORK? Зачем его делают? \n", + "Форк - это копия чужого репозитория. Делают, чтобы вносить изменения, не затрагивая оригинала. \n", + "32) Как скачать форкнутый репозиторий на локальный компьютер?\n", + "Нажать на него, выбрать Open in GitHub Desktop, затем Clone\n", + "33) С какой вероятностью ваши ошибки были уже решены? и кто их решил?\n", + "C вероятностью 90%. Их решил Сенаторов Руслан Олегович.\n", + "34) Как создать файл в vs code?\n", + "Нажать на листочек с плюсиком и ввести название и формат файла. \n", + "35) Файл лога нужно заполнять в конце каждого урока?\n", + "Да.\n", + "==================\n", + "\n", + "Дополнительные вопросы:\n", + "1)Какая команда конвертирует файл в py из ipynb? \n", + "подсказка https://t.me/c/1937296927/1/26527 \n", + "jupitex --to py \n", + "2) Что такое пакетный менеджер? Вы пользуетесь пакетным менеджером conda или pip? Какой лучше использовать для дата сайнс?\n", + "Пакетный менеджер - инструмент для установки и управления библиотеками/пакетами\n", + "Для Data Science лучше использовать Conda - он упраляет не только Python-пакетами, но и зависимостями системы, библиотеками (NumPy, SciPy) с нативными расширениями.\n", + "3) Почему расширение py лучше чем ipynb?\n", + "- удобнее для версионирования (Git лучше работает с текстом)\n", + "- Линтеры (Pilint, Pidocstyle) корректно работают только .py\n", + "- проще ревью кода\n", + "- лучше для продакшн-кода и автоматизации\n", + "4) Что такое pep8? \n", + "подсказка:https://peps.python.org/pep-0008/\n", + "pep8 - официальный стиль кода Python.\n", + "4.1) линтеры проверяют на соблюдение pep8?\n", + "Да. Flake8 и Pylint проверяют на соответствие pep8. \n", + "4.2) Какая нотация используется для создания переменных? \n", + "ответ на 85-95 страницы https://t.me/c/1937296927/1/16676\n", + "snake_case (нижнее подчеркивание), например, first_variable\n", + "4.3) Может ли переменная состоять из одной буквы например андерскор \"_\" ?\n", + "Да.\n", + "4.4) Зачем и где мы используем андерскор _ \n", + "в начале два и конце переменных\n", + "4.5) По PEP8 допустима переменная в одну букву?\n", + "ответ на 85-95 страницы https://t.me/c/1937296927/1/16676\n", + "да, но не рекомендовано для обычных переменных. Лучше использовать понятные имена. Исключения - в циклах, в малых областях видимости. \n" + ] + } + ], + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/quiz1.py b/quiz1.py new file mode 100644 index 00000000..3d3cc0e9 --- /dev/null +++ b/quiz1.py @@ -0,0 +1,158 @@ +"""Quiz 1.""" + +# Список вопросов к видео https://youtu.be/hW_7hodGxVU?si=tCEVs00xGt2q61eW (АЛГОРИТМ ПРИНЯТИЯ И ОТДАЧИ ДОМАШКИ): +# +# (По желанию )В ответе подробно всё опишите и обязательно нужно указывать тайм код из видео где я это сказал, по желанию, дополнительно прикладываем скриншот из видео. +# Если вы знаете ответы на вопросы из Вашего опыта, то таймкоды из видео не надо указывать и т.д. +# +# 1) Как понять, что домашка пришла? +# В чате homework будет сообщение @а прими пул +# 2) Как принять домашку? +# Заходим а Гитхаб десктоп, нажимаем Fetch origin, заходим в history и смотрим самый верхний коммит. +# 3) Зачем нужна кнопка history и какие функции появляются при нажатии правой кнопки мыши на коммит? +# Кнопка history показывает коммиты. Если нажать правой кнопкой на коммит, то выйдет контекстное меню. +# +# 3.1) Где брать ссылку на коммит? куда её отправлять? +# Ссылку брать с Гитхаба и отправлять в чат homework, пишем "Коммит отдал" +# 4) Что такое файл лога? +# В файле лога нужно заполнять в конце каждого урока. В этом файле нужно писать дату и что запомнилось в течение урока. +# 4.1) Когда нужно его пушить? +# После заполнения и проверки на ошибки. +# 5) Что такое интерпритатор? +# Это программа, которая построчно выполняет команды, написанные на языке программирования. +# 6) Где можно выбрать интерпритатор? +# В правом верхнем углу. +# 7) Что такое модуль? +# Это файл с расширением .py или .ipynb. +# 8) Как создать и отправить коммит? +# Создать файл с расширением .ipynb, заполнить, проверить на ошибки, Commit&sync, Commit&push +# 9) Как посмотреть что коммит точно отправлен и находится в github? +# Коммит должен быть виден на гитхабе и в Hidtory в кошке. +# 10) Какая команда показывает что код не прошёл проверки на ошибки? +# Команда в терминале pre-commit run --all-files +# 10.1) Напишите список линтеров которые используются для проверки кода и дайте их краткую характеристику. +# Mypy - проверяет типы +# Pylint - проверяет соответствие стандартам кодирования. +# Pydocstyle - ищет отсутствие docstring +# Flake8 - обнаруживает стилистические ошибки +# +# +# 11) Как узнать какой именно линтер не прошёл проверку? +# При проверке через терминал командой pre-commit run --all-files выйдет статус Failed. +# 12) Линтер Pylint видит markdown? +# нет +# 13) Номер ячейки в терминале и номер ячейки в vs code может отличаться? в каком случае? +# Может. Линтер не видит ячейки markdown. +# 14) Где посмотреть номер ячейки в vscode? +# Можно посмотреть внизу справа. +# 15) В каком формате ipynb отправляется в гитхаб? причём здесь JSON? +# Файлы ipynb отпраляются на гитхаб в формате JSON. +# 16) Где посмотреть в какой ячейке ошибка? +# По коду ошибки или Ctrl+F. +# 17) Как запустить терминал? +# Terminal - New Terminal +# 18) Что такое линтер? +# Это программа, которая проверяет файл на корректность. +# 19) В какой сайт нужно вставлять код ошибки если ошибка связана с pylint? +# На сайт pylint.readthedocs.io +# 20) Секция pydocstyle в большинстве случае автоматический закрывается после исправления ошибок в каком линтере? +# В pylint +# 21) Что такое описание модуля? Оно должно отражать информацию о том что находится в модуле? +# Это описание того, что находится в модуле. Должно отражвть информацию о том, что находится в модуле. +# 21.1) С какой git команды начинается утро программиста? +# С команды Fetch origin. +# 22) После внесения изменений в файлах, кнопка open in vs code пропадает в кошке, как по другому открыть vs code из кошки? +# Нажать правой кнопкой на Current repository и выбрать open in VS code. +# 23) Что такое stash? +# Общее объяснение концепции. +# stash - буфер обмена, где можно спрятать локальные изменения. +# Мы можем временно сохранить наши изменения, не коммитя их а репозиторий, для дальнейших изменений. +# 23.1) Как сохранить стэш? +# git командa(подсказка: https://t.me/c/1937296927/3602/19531): +# git stash save "Name_stash" - сохранение в буфер обмена +# git stash apply "Number_stash" - извлечение из буфера обмена. +# Кнопка в vs code: +# Stash changes and continue +# 23.2) Как восстановить стэш(подсказка: https://t.me/c/1937296927/3602/25747)?: +# +# +# git команда(подсказка: https://t.me/c/1937296927/3602/19531)?: +# git stash apply "Number_stash" +# 23.3) Различие между стэшем и коммитом. +# Когда лучше сохранить изменения в стэше, а когда коммитить. +# Коммитить - когда мы завершили действия и можем вылоожить в ветку. +# Стэшить - когда мы не завершили работу и хотим вернуться, чтобы доделать. +# 23.4) Как просмотреть список сохраненных стэшей? +# git команда (подсказка: https://t.me/c/1937296927/3602/19531): +# git stash list +# 23.5) Как удалить стэш? +# Команды для удаления отдельных стэшей или всех сразу. +# git команда (подсказка: https://t.me/c/1937296927/3602/19531): +# git stash drop +# git stash clean +# 23.6) Практические примеры использования стэша. +# Краткие сценарии, где стэш помогает. +# Спрятать изменения в моменте, когда нужно поработать над другой задачей +# Спрятать измения, когда возник конфликт. +# 24) Где посмотреть что есть конфликт в файлах? +# Рядом с файлом readme будет стоять треугольник с восклицательным знаком. Нажимаем Open in VS Code. Зеленым цветом будет выделено то, что с гитхаба, синим - локальные изменения. +# 24.1) Когда он появляется? +# Когда в файле работвют одновременно два человека. +# 25) Как решить конфликт в файлах? +# Нажать Reserve in Merge Editor, Complete Merge. +# 26) Напишиие правильное утверждение +# -Зелёное то что пришло с гитхаба и синее локальные изменения или синее то что пришло с гитхаба и зелёное это локальные изменения +# Зеленое - с гитхаба +# Синее - локальные изменения. +# 27) Если мы работаем в одном файле, можно ли принять pull после того как вы спрячете в стэш свои изменения? +# да, можно. +# 27.1) Что может произойти когда stash восстановите после принятия pull? +# Может произойти конфликт. +# 28) Сколько способов решения конфликтов было показано в видео? Напишите ЧИСЛО и укажите их способы. +# 2 способа +# 1 способ - с помощью Accept Incoming Change,Accept Current Change, Accept Both Changes +# 2 способ - вручную удалить то что не нужно. +# 29) Что делает кнопка complete merge? +# Смерживает конечные изменения из конфликтов в один. +# 30) В какой чат нужно писать если остались вопросы? +# в чат HELP ME +# 31) Что такое FORK? Зачем его делают? +# Форк - это копия чужого репозитория. Делают, чтобы вносить изменения, не затрагивая оригинала. +# 32) Как скачать форкнутый репозиторий на локальный компьютер? +# Нажать на него, выбрать Open in GitHub Desktop, затем Clone +# 33) С какой вероятностью ваши ошибки были уже решены? и кто их решил? +# C вероятностью 90%. Их решил Сенаторов Руслан Олегович. +# 34) Как создать файл в vs code? +# Нажать на листочек с плюсиком и ввести название и формат файла. +# 35) Файл лога нужно заполнять в конце каждого урока? +# Да. +# ================== +# +# Дополнительные вопросы: +# 1)Какая команда конвертирует файл в py из ipynb? +# подсказка https://t.me/c/1937296927/1/26527 +# jupitex --to py +# 2) Что такое пакетный менеджер? Вы пользуетесь пакетным менеджером conda или pip? Какой лучше использовать для дата сайнс? +# Пакетный менеджер - инструмент для установки и управления библиотеками/пакетами +# Для Data Science лучше использовать Conda - он упраляет не только Python-пакетами, но и зависимостями системы, библиотеками (NumPy, SciPy) с нативными расширениями. +# 3) Почему расширение py лучше чем ipynb? +# - удобнее для версионирования (Git лучше работает с текстом) +# - Линтеры (Pilint, Pidocstyle) корректно работают только .py +# - проще ревью кода +# - лучше для продакшн-кода и автоматизации +# 4) Что такое pep8? +# подсказка:https://peps.python.org/pep-0008/ +# pep8 - официальный стиль кода Python. +# 4.1) линтеры проверяют на соблюдение pep8? +# Да. Flake8 и Pylint проверяют на соответствие pep8. +# 4.2) Какая нотация используется для создания переменных? +# ответ на 85-95 страницы https://t.me/c/1937296927/1/16676 +# snake_case (нижнее подчеркивание), например, first_variable +# 4.3) Может ли переменная состоять из одной буквы например андерскор "_" ? +# Да. +# 4.4) Зачем и где мы используем андерскор _ +# в начале два и конце переменных +# 4.5) По PEP8 допустима переменная в одну букву? +# ответ на 85-95 страницы https://t.me/c/1937296927/1/16676 +# да, но не рекомендовано для обычных переменных. Лучше использовать понятные имена. Исключения - в циклах, в малых областях видимости. +# diff --git a/quiz2.ipynb b/quiz2.ipynb new file mode 100644 index 00000000..6cfd0aba --- /dev/null +++ b/quiz2.ipynb @@ -0,0 +1,350 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "f2a093aa", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Quiz 2.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Quiz 2.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "9f4a527e", + "metadata": {}, + "source": [ + "Выполнение заданий по Питону \n", + "\n", + "Список вопросов к видео https://youtu.be/Si9MfV8uJ-0?si=JXHe-tsgOEwSTI5E (НАСТРОЙКА VSCODE, перенос строк, линтеры, работа с ячейками):\n", + "\n", + "\n", + "(По желанию)В ответе подробно всё опишите и обязательно нужно указывать тайм код из видео где я это сказал, по желанию, дополнительно прикладываем скриншот из видео.\n", + "\n", + "Если вы знаете ответы на вопросы из Вашего опыта, то таймкоды из видео не надо указывать и т.д.\n", + "\n", + "\n", + "1. Как включить автосохранение данных в VSCODE?\n", + "\n", + "\n", + "File - Auto Save\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&t=14\n", + "\n", + "\n", + "2. Как настроить перенос строки? \n", + "\n", + "\n", + "Preferences-Settings, в поисковую строку пишем wrap, в поле Editor в контекстном меню выбираем WordWrapColumn, длина строки 79, нажимаем Enter.\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&t=34\n", + "\n", + "\n", + "3. Сколько символов по pep8 разрешено на строке?\n", + "\n", + "\n", + "79\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=1m28s\n", + "\n", + "\n", + "4. Какие способы переноса строк показаны в видео:\n", + "\n", + "\n", + "Вариант 1.\n", + "\n", + "перенос комментариев - с помощью #\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ?=1m55s\n", + "\n", + "перенос кода - взять в скобки ( )\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=2m36s\n", + "\n", + "Вариант 2.\n", + "\n", + "длинную переменную разбить на две переменные, затем “склеить\" их, например, name_sum=name_1+name_2\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=4m\n", + "\n", + "\n", + "4.1 Строки с использованием обратного слэша (\\)\n", + "\n", + "\n", + "string_continued = \"This is a long string that we want to \" \\\n", + "\n", + " \"split across multiple lines.\"\n", + "\n", + "print(string_continued)\n", + "\n", + "\n", + "\n", + "4.2 Тройные кавычки (''' или \"\"\") \n", + "\n", + "\n", + "multi_line_string = \"\"\"This is a string that spans\n", + "\n", + "multiple lines. You can write freely\n", + "\n", + "and it will keep the line breaks.\"\"\"\n", + "\n", + "print(multi_line_string)\n", + "\n", + "\n", + "4.3 Создание списка строк и объединение с помощью join\n", + "\n", + "\n", + "strings = [\n", + "\n", + " \"This is the first line.\",\n", + "\n", + " \"This is the second line.\",\n", + "\n", + " \"This is the third line.\"\n", + "\n", + "]\n", + "\n", + "result = \"\\n\".join(strings) # Используем перенос строк '\\n'\n", + "\n", + "print(result)\n", + "\n", + "\n", + "4.4 Использование круглых скобок для продолжения строки\n", + "\n", + "long_string = (\n", + "\n", + " \"This is a very long string that I would like to \"\n", + "\n", + " \"continue on the next line.\"\n", + "\n", + ")\n", + "\n", + "print(long_string)\n", + "\n", + "\n", + "4.5 Форматированные строки (f-строки) с использованием скобок\n", + "\n", + "letter_a = 5\n", + "\n", + "letter_b = 6\n", + "\n", + "product_ab = letter_a * letter_b\n", + "\n", + "\n", + "message = (\n", + "\n", + " f\"when {letter_a} is multiplied by {letter_b}, \"\n", + "\n", + " f\"the result is {product_ab}\"\n", + "\n", + ")\n", + "\n", + "print(message)\n", + "\n", + "\n", + "4.6 Сложение строк с помощью +\n", + "\n", + "\n", + "string_part1 = \"This is the first part, \"\n", + "\n", + "string_part2 = \"and this is the second part.\"\n", + "\n", + "full_string = string_part1 + string_part2\n", + "\n", + "print(full_string)\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=3m55s\n", + "\n", + "\n", + "5. Проверка на ошибки c помощью кнопки problems, где она находится?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=4m49s\n", + "\n", + "Находится внизу окна редактора, слева. \n", + "\n", + "\n", + "6. Где в vscode находится клиент гита? как в нём отправить коммит? как принять домашку?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=6m24s\n", + "\n", + "Клиент находится в левой части окна(три кружочка)\n", + "\n", + "Чтобы отправить коммит, пишем коммит, затем нажимаем Commit\n", + "\n", + "Домашка принимается с помощью кнопки Pull.\n", + "\n", + "\n", + "7. Что такое GIT? он локальный? В нём можно посмотреть историю изменений файлов и вернуться к любому коммиту?\n", + "\n", + "\n", + "Git - это контроль версий. да, можно посмотреть \n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=7m12s\n", + "\n", + "\n", + "8. Как вставить картинку в маркдаун? \n", + "\n", + "\n", + "С помощью сочетания клавиш Ctrl+V\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m03s\n", + "\n", + "\n", + "9. Где посмотреть длину строки в vs code?\n", + "\n", + "Скопировать строку в файл с расширением .py, внизу справа показывается количество символов. \n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=1m25s\n", + "\n", + "\n", + "\n", + "10. Как поменять тип ячейки с питона на маркдаун?\n", + "\n", + "По умолчанию создается тип ячейки Code. Нажать на тип Python и выбрать в ниспадающем меню Markdown.\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m08s\n", + "\n", + "\n", + "11. Как запустить сразу все ячейки в юпитере?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m36s\n", + "\n", + "\n", + "Нажать Run All - запуск всех ячеек одновременно. \n", + "\n", + "\n", + "12. Как изменить размер картинки в юпитере? Нужно для этого знать HTML?\n", + "\n", + "img are, ссылка на картинку и её размер\n", + "\n", + "Да, нужно знать.\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m21s\n", + "\n", + "\n", + "13. Какой хоткей чтобы запустить ячейку с смещением на следующую?\n", + "\n", + "\n", + "Shift+Enter\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m49s\n", + "\n", + "\n", + "14. Как включить отображение номеров строк в юпитере(Cell line numbers)?\n", + "\n", + "Нажимаем на три точки в правом нижнем углу окна редактора и выбираем Show Cell line Number.\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m17s\n", + "\n", + "\n", + "15. Что такое \"Go To\" чем это полезно? Как перейти сразу на ошибочную ячейку?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m41s\n", + "\n", + "Показывает, в какой ячейке ошибка. Схватываем проблемную ячейку и тащим вниз, нажимаем “Go To”\n", + "\n", + "\n", + "16. Как очистить вывод ячеек которые уже запущены?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=10m51s\n", + "\n", + "Нужно нажать Clear All Outputs.\n", + "\n", + "\n", + "17. Как работать одновременно в нескольких файлах в VSCODE? Что такое SPLIT?\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m03s\n", + "\n", + "Split Editor позволяет работать одновременно в нескольких файлах. \n", + "\n", + "\n", + "18. Каким сочетанием убирается левый сайдбар?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m23s\n", + "\n", + "Ctrl+B, либо просто нажимаем на активное окно.\n", + "\n", + "\n", + "19. Кнопка два листочка это наши локальные файлы?\n", + "\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m36s\n", + "\n", + "Да\n", + "\n", + "\n", + "20. Какая ошибка появилась в трассировке при запуске всех ячеек DICT или LIST?\n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m23s\n", + "\n", + "\n", + "21. Вы ознакомились с https://t.me/c/1937296927/832/19307? и https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet?\n", + "\n", + "\n", + "Ознакомилась\n", + "\n", + "\n", + "22. Что такое валидация?\n", + "\n", + "\n", + "Это проверка соответствия программного кода определённым правилам.\n", + "\n", + "\n", + "23. Что такое трассировка ошибки?\n", + "\n", + "\n", + "Трассировка - это визуализация ошибки \n", + "\n", + "https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=10m05s\n", + "\n", + "\n", + "24. Что значит отвалился интерпретатор?\n", + "\n", + "Это означает, что интерпритатор перестал работать или быть доступным, из-за чего программный код, который от него зависел, не может запуститься, выполнить команды или выдать ошибку. \n", + "\n" + ] + } + ], + "metadata": { + "jupytext": { + "formats": "ipynb,py:light" + }, + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/quiz2.py b/quiz2.py new file mode 100644 index 00000000..85fb8870 --- /dev/null +++ b/quiz2.py @@ -0,0 +1,297 @@ +"""Quiz 2.""" + +# Выполнение заданий по Питону +# +# Список вопросов к видео https://youtu.be/Si9MfV8uJ-0?si=JXHe-tsgOEwSTI5E (НАСТРОЙКА VSCODE, перенос строк, линтеры, работа с ячейками): +# +# +# (По желанию)В ответе подробно всё опишите и обязательно нужно указывать тайм код из видео где я это сказал, по желанию, дополнительно прикладываем скриншот из видео. +# +# Если вы знаете ответы на вопросы из Вашего опыта, то таймкоды из видео не надо указывать и т.д. +# +# +# 1. Как включить автосохранение данных в VSCODE? +# +# +# File - Auto Save +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&t=14 +# +# +# 2. Как настроить перенос строки? +# +# +# Preferences-Settings, в поисковую строку пишем wrap, в поле Editor в контекстном меню выбираем WordWrapColumn, длина строки 79, нажимаем Enter. +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&t=34 +# +# +# 3. Сколько символов по pep8 разрешено на строке? +# +# +# 79 +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=1m28s +# +# +# 4. Какие способы переноса строк показаны в видео: +# +# +# Вариант 1. +# +# перенос комментариев - с помощью # +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ?=1m55s +# +# перенос кода - взять в скобки ( ) +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=2m36s +# +# Вариант 2. +# +# длинную переменную разбить на две переменные, затем “склеить" их, например, name_sum=name_1+name_2 +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=4m +# +# +# 4.1 Строки с использованием обратного слэша (\) +# +# +# string_continued = "This is a long string that we want to " \ +# +# "split across multiple lines." +# +# print(string_continued) +# +# +# +# 4.2 Тройные кавычки (''' или """) +# +# +# multi_line_string = """This is a string that spans +# +# multiple lines. You can write freely +# +# and it will keep the line breaks.""" +# +# print(multi_line_string) +# +# +# 4.3 Создание списка строк и объединение с помощью join +# +# +# strings = [ +# +# "This is the first line.", +# +# "This is the second line.", +# +# "This is the third line." +# +# ] +# +# result = "\n".join(strings) # Используем перенос строк '\n' +# +# print(result) +# +# +# 4.4 Использование круглых скобок для продолжения строки +# +# long_string = ( +# +# "This is a very long string that I would like to " +# +# "continue on the next line." +# +# ) +# +# print(long_string) +# +# +# 4.5 Форматированные строки (f-строки) с использованием скобок +# +# letter_a = 5 +# +# letter_b = 6 +# +# product_ab = letter_a * letter_b +# +# +# message = ( +# +# f"when {letter_a} is multiplied by {letter_b}, " +# +# f"the result is {product_ab}" +# +# ) +# +# print(message) +# +# +# 4.6 Сложение строк с помощью + +# +# +# string_part1 = "This is the first part, " +# +# string_part2 = "and this is the second part." +# +# full_string = string_part1 + string_part2 +# +# print(full_string) +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=3m55s +# +# +# 5. Проверка на ошибки c помощью кнопки problems, где она находится? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=4m49s +# +# Находится внизу окна редактора, слева. +# +# +# 6. Где в vscode находится клиент гита? как в нём отправить коммит? как принять домашку? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=6m24s +# +# Клиент находится в левой части окна(три кружочка) +# +# Чтобы отправить коммит, пишем коммит, затем нажимаем Commit +# +# Домашка принимается с помощью кнопки Pull. +# +# +# 7. Что такое GIT? он локальный? В нём можно посмотреть историю изменений файлов и вернуться к любому коммиту? +# +# +# Git - это контроль версий. да, можно посмотреть +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=7m12s +# +# +# 8. Как вставить картинку в маркдаун? +# +# +# С помощью сочетания клавиш Ctrl+V +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m03s +# +# +# 9. Где посмотреть длину строки в vs code? +# +# Скопировать строку в файл с расширением .py, внизу справа показывается количество символов. +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=1m25s +# +# +# +# 10. Как поменять тип ячейки с питона на маркдаун? +# +# По умолчанию создается тип ячейки Code. Нажать на тип Python и выбрать в ниспадающем меню Markdown. +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m08s +# +# +# 11. Как запустить сразу все ячейки в юпитере? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m36s +# +# +# Нажать Run All - запуск всех ячеек одновременно. +# +# +# 12. Как изменить размер картинки в юпитере? Нужно для этого знать HTML? +# +# img are, ссылка на картинку и её размер +# +# Да, нужно знать. +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m21s +# +# +# 13. Какой хоткей чтобы запустить ячейку с смещением на следующую? +# +# +# Shift+Enter +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=8m49s +# +# +# 14. Как включить отображение номеров строк в юпитере(Cell line numbers)? +# +# Нажимаем на три точки в правом нижнем углу окна редактора и выбираем Show Cell line Number. +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m17s +# +# +# 15. Что такое "Go To" чем это полезно? Как перейти сразу на ошибочную ячейку? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m41s +# +# Показывает, в какой ячейке ошибка. Схватываем проблемную ячейку и тащим вниз, нажимаем “Go To” +# +# +# 16. Как очистить вывод ячеек которые уже запущены? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=10m51s +# +# Нужно нажать Clear All Outputs. +# +# +# 17. Как работать одновременно в нескольких файлах в VSCODE? Что такое SPLIT? +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m03s +# +# Split Editor позволяет работать одновременно в нескольких файлах. +# +# +# 18. Каким сочетанием убирается левый сайдбар? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m23s +# +# Ctrl+B, либо просто нажимаем на активное окно. +# +# +# 19. Кнопка два листочка это наши локальные файлы? +# +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=11m36s +# +# Да +# +# +# 20. Какая ошибка появилась в трассировке при запуске всех ячеек DICT или LIST? +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=9m23s +# +# +# 21. Вы ознакомились с https://t.me/c/1937296927/832/19307? и https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet? +# +# +# Ознакомилась +# +# +# 22. Что такое валидация? +# +# +# Это проверка соответствия программного кода определённым правилам. +# +# +# 23. Что такое трассировка ошибки? +# +# +# Трассировка - это визуализация ошибки +# +# https://youtu.be/Si9MfV8uJ-0?si=U4yGy8-OCkDu1cRZ&=10m05s +# +# +# 24. Что значит отвалился интерпретатор? +# +# Это означает, что интерпритатор перестал работать или быть доступным, из-за чего программный код, который от него зависел, не может запуститься, выполнить команды или выдать ошибку. +# +# From 80bf5e6ebffb44aa8f62b2288966b8ac19966451 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Tue, 20 Jan 2026 01:05:21 +0500 Subject: [PATCH 03/24] [TASK] Quiz #4(https://github.com/SENATOROVAI/intro-cs/issues/4) Closes https://github.com/SENATOROVAI/intro-cs/issues/4 --- python/cpython.ipynb | 179 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 python/cpython.ipynb diff --git a/python/cpython.ipynb b/python/cpython.ipynb new file mode 100644 index 00000000..59e646f1 --- /dev/null +++ b/python/cpython.ipynb @@ -0,0 +1,179 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "c1ccfa97", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Quiz 4.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Quiz 4.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "01f96160", + "metadata": {}, + "source": [ + "1. Что такое CPython и чем он отличается от Python?\n", + "Python - это язык программирования, а CPython - это и язык программирования, и интерпретатор одновременно. \n", + "3. Сколько существует реализаций Python, и какая из них самая популярная?\n", + "Существует 6 реализаций Python, самая популярная из них-CPython\n", + "4. На каком языке написан CPython?\n", + "CPython написан на языке С.\n", + "5. (опционально) Кто создал CPython?\n", + "CPython создал голландский программист Гвидо ван Россум.\n", + "\n", + "6. Почему Python считается быстрым, несмотря на то, что это интерпретируемый язык?\n", + "Потому что ядро CPython написано на языке С, и он вызывает инструкции из С.\n", + "\n", + "7. Напишите путь к Интерпретатору CPython на вашем компьютере\n", + "C:\\Users\\user\\anaconda3\\python.exe\n", + "\n", + "8. Что содержится в папке include в CPython?\n", + "В папке include в CPython находятся заголовочные файлы на языке С.\n", + "\n", + "9. Где можно найти исходный код CPython дайте ссылку на репозиторий гитхаб.\n", + "Ссылка на репозиторий гитхаб: https://github.com/python/cpython\n", + "\n", + "10. (опционально) Как работает интерпретатор CPython при выполнении кода?\n", + "Интерпретатор CPython выполняет код пошагово, преобразуя его в машинные инструкции для компьютера.\n", + "\n", + "11. Какая команда используется для запуска файла с помощью CPython?\n", + "python filename\n", + "\n", + "12. Можно ли запускать текстовые файлы через интерпретатор Python? Почему?\n", + "Можно, так как интерпретатору неважно, какие файлы запускать, главное – валидный пайтон-код.\n", + "\n", + "13. Как указать путь к интерпретатору и файлу для выполнения кода?\n", + "Через абсолютный или относительный путь. \n", + "\n", + "14. Чем PyPy отличается от CPython?\n", + "Этот интерпретатор работает в 10 раз быстрее, чем CPython.\n", + "\n", + "15. Почему PyPy не может использоваться для всех проектов на Python?\n", + "Это достаточно новый интерпретатор, и он ещё не совместим со всеми проектами на Python. \n", + "\n", + "16. Где можно скачать PyPy?\n", + "По ссылке: https://pypy.org/download.html\n", + "\n", + "17. Как установить PyPy после скачивания?\n", + "Извлечь папку и прописать пути в переменных средах.\n", + "\n", + "18. Как запустить файл с помощью PyPy?\n", + "В командной строке Windows ввести абсолютный путь до интерпретатора, пробел, абсолютный путь до файла, нажать Enter.\n", + "\n", + "19. Почему PyPy выполняет код быстрее, чем CPython?\n", + "PyPy использует Just-In-Time компилятор для компиляции Python в машинный код во время выполнения, что ускоряет работу.\n", + "\n", + "Практические задания\n", + "Задание 1: Поиск и установка CPython\n", + "Проверьте, установлен ли CPython на вашем компьютере:\n", + " Используйте поиск в меню \"Пуск\" (Windows) или терминале (Linux/Mac).\n", + " Введите команду python --version или python3 --version в терминале.\n", + "Если CPython не установлен, скачайте его с официального сайта Python https://www.python.org/downloads/ и установите.\n", + "\n", + "C:\\Users\\user>python --version\n", + "Python 3.13.9\n", + "\n", + "\n", + "Задание 2: Исследование структуры CPython\n", + "Найдите папку, где установлен Python (например, через команду where python в терминале или свойства ярлыка).\n", + "Откройте папку include и изучите её содержимое. Какое количество файлов на C там есть?\n", + "Перейдите на [GitHub-репозиторий CPython](https://github.com/python/cpython) и найдите файл README. Прочитайте информацию о проекте.\n", + "\n", + "В папке include количество файлов на C: 77.\n", + "\n", + "C:\\Users\\user>where python\n", + "C:\\Users\\user\\anaconda3\\python.exe\n", + "C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python310\\python.exe\n", + "C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python312\\python.exe\n", + "C:\\Users\\user\\AppData\\Local\\Microsoft\\WindowsApps\\python.exe\n", + "\n", + "C:\\Users\\user>\n", + "\n", + "Задание 3: Запуск файла с помощью CPython\n", + "Создайте текстовый файл example.txt с содержимым:\n", + "print(\"Hello from CPython!\")\n", + "Запустите файл через команду python <путь_до_файла> (замените <путь_до_файла> на фактический путь к вашему файлу).\n", + "Проверьте, что выводится на экран. Попробуйте изменить расширение файла на .py и повторите запуск.\n", + "C:\\Users\\user>C:\\Users\\user\\anaconda3\\Scripts\\ipython3.exe C:\\Users\\user\\Desktop\\Test1\\example.txt\n", + "Hello from CPython!\n", + "\n", + "C:\\Users\\user>C:\\Users\\user\\anaconda3\\Scripts\\ipython3.exe\n", + "C:\\Users\\user\\Desktop\\Test1\\example.py\n", + "Hello from CPython!\n", + "\n", + "\n", + "Задание 4: Установка и использование PyPy\n", + "Перейдите на [официальный сайт PyPy](https://www.pypy.org/) и скачайте подходящую версию для вашей операционной системы.\n", + "Распакуйте скачанный архив в удобное место.\n", + "Создайте файл example_pypy.py с кодом:\n", + "print(\"Hello from pypy!\")\n", + "Запустите файл через PyPy\n", + "pypy <путь_до_файла> (замените <путь_до_файла> на фактический путь к вашему файлу).\n", + "Проверьте, что выводится на экран. Попробуйте изменить расширение файла на .py и повторите запуск.\n", + "Вывод:\n", + "C:\\Users\\user>C:\\Users\\user\\Downloads\\pypy3.11-v7.3.20-win64\\pypy.exe C:\\Users\\user\\Desktop\\Test1\\example_pypy.py\n", + "Hello from PyPy\n", + "C:\\Users\\user>\n", + "Задание 5: Сравнение производительности CPython и PyPy\n", + "Создайте файл performance_test.py с кодом:\n", + " import time\n", + " start_time = time.time()\n", + " total = 0\n", + " for i in range(1, 10000000):\n", + " total += i\n", + " end_time = time.time()\n", + " \n", + " print(\"Result:\", total)\n", + " print(\"Execution time:\", end_time - start_time, \"seconds\")\n", + "Запустите этот файл сначала через CPython, а затем через PyPy. Запишите результаты времени выполнения для обоих интерпретаторов.\n", + "Сделайте вывод о разнице в производительности.\n", + "\n", + "Результат запуска через PyPy:\n", + "C:\\Users\\user>C:\\Users\\user\\Downloads\\pypy3.11-v7.3.20-win64\\pypy.exe C:\\Users\\user\\Desktop\\Test1\\performance_test.py\n", + "Result: 49999995000000\n", + "Execution time: 0.015625715255737305 seconds\n", + "\n", + "Результат запуска через iPython:\n", + "C:\\Users\\user>C:\\Users\\user\\anaconda3\\Scripts\\ipython.exe C:\\Users\\user\\Desktop\\Test1\\ performance_test.py\n", + "Result: 49999995000000\n", + "Execution time: 2.2144627571105957 seconds\n", + "Вывод: Время выполнения через интерпретатор iPython в 142 раза больше.\n" + ] + } + ], + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 157a2ecec21a8bc9b5a9ba9c8388db1c6fe2d051 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 26 Jan 2026 15:02:18 +0500 Subject: [PATCH 04/24] [TASK] Quiz#7 (https://github.com/SENATOROVAI/intro-cs/issues/7) Closes https://github.com/SENATOROVAI/intro-cs/issues/7 --- python/venv.ipynb | 100 ++++++++++++++++++++++++++++++++++++++++++++++ python/venv.py | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 python/venv.ipynb create mode 100644 python/venv.py diff --git a/python/venv.ipynb b/python/venv.ipynb new file mode 100644 index 00000000..94e8c6d1 --- /dev/null +++ b/python/venv.ipynb @@ -0,0 +1,100 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a6e9c430", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Quiz 7.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "c01338ff", + "metadata": {}, + "source": [ + "1.\tЧто делает команда python -m venv venv? \n", + "\n", + "Ответ: создаёт виртуальное окружение, название окружения venv\n", + "\n", + "1.1 Что делает каждая команда в списке ниже?\n", + "\n", + "pip list - отображает пакеты, находящиеся в pip\n", + "pip freeze > requirements.txt - выгружает все пакеты в один файл, который называется requirements.txt.\n", + "pip install -r requirements.txt - устанавливает все пакеты из файла requirements.txt одним махом.\n", + "\n", + "2.\tЧто делает каждая команда в списке ниже?\n", + "\n", + "conda env list - используется для отображения списка всех существующих окружений conda вместе с путями к ним в файловой системе. \n", + "conda create -n env_name python=3.5 - создаёт виртуальное окружение conda с именем env_name, здесь python=3.5 - версия питона.\n", + "conda env update -n env_name -f file.yml - обновляет окружение env_name зависимостями из yaml-файла.\n", + "source activate env_name - активирует виртуальное окружение с именем env_name. \n", + "source deactivate - деактивирует виртуальное окружение \n", + "conda clean -all - удаляет кэш и неиспользуемые пакеты. \n", + "\n", + "3.\tВставьте скрин вашего терминала, где вы активировали сначала venv, потом conda, назовите окружение “Senatorov”.\n", + "\n", + "Ответ: image.png\n", + "4.\tКак установить необходимые пакеты внутрь виртуального окружения для conda/venv?\n", + "\n", + "Ответ: 1) для venv: \n", + "-активация нужного окружения и установка нужных зависимостей с помощью команды pip install “имя зависимости”.\n", + "-создать файл requirements.txt, записать туда все необходимые зависимости и с помощью команды pip install -r requirements.txt установить их.\n", + "2) для conda: \n", + "-активация нужного окружения и установка нужных зависимостей с помощью команды conda install “имя зависимости”.\n", + "-создать файл environment.yml, записать туда все необходимые зависимости и с помощью команды conda env update -f environment.yml установить их или обновить. \n", + "\n", + "5.\tЧто делают эти команды?\n", + "\n", + "pip freeze > requirements.txt -выгружает все пакеты venv в один файл, который называется requirements.txt.\n", + "conda env export > environment.yml - выгружает файлы зависимостей conda в файл environment.yml \n", + "\n", + "5.1 вставьте скрин, где будет видна папка VENV в вашем репозитории а также файлы зависимостей requirements.txt и environment.yml, файлы должны содержать зависимости\n", + "Ответ: image.png \n", + " image.png\n", + "6.\tЧто делают эти команды?\n", + "\n", + "pip install -r requirements.txt - устанавливает файлы зависимостей, находящиеся в requirements.txt, через пакетный менеджер pip.\n", + "conda env create -f environment.yml - устанавливает файлы зависимостей, находящиеся в environment.yml через пакетный менеджер conda.\n", + "\n", + "7.\tЧто делают эти команды?\n", + "\n", + "pip list - отображает список зависимостей выбранного окружения в venv.\n", + "pip show - выводит подробную информацию об установленном пакете: его версии, авторе, лицензии, месте установки, описании и зависимостях.\n", + "conda list - отображает список зависимостей выбранного окружения в conda. \n", + "\n", + "8.\tГде по умолчанию больше пакетов venv/pip или conda? и почему дата сайентисты используют conda? \n", + "\n", + "Ответ: больше пакетов в conda. В pip нет пакетов для Data science,поэтому дата сайентисты используют conda.\n", + "\n", + "9.\tвставьте скрин где будет видно, Выбор интерпретатора Python (conda) в VS Code/cursor\n", + "Ответ: image.png\n", + "\n", + "10.\tдобавьте в .gitignore папку SENATOROV\n", + "\n", + "11.\tЗачем нужно виртуальное окружение? \n", + "Ответ: виртуальное окружение - это изолированное пространство, в котором можно установить необходимую версию Python и пакеты, отличные от тех, которые установлены в системе. Это позволяет предотвратить конфликты между различными версиями Python и пакетов. Позволяет создавать “чистый” проект без лишних зависимостей. \n", + "\n", + "12.\tС этого момента надо работать в виртуальном окружении conda, ты научился(-ась) выгружать зависимости и работать с окружением?\n", + "Ответ: да\n", + "13.\tУдалите папку VENV, она больше не нужна, мы же не разрабы, нам нужна только conda\n", + "Ответ: удалила\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/venv.py b/python/venv.py new file mode 100644 index 00000000..b7ed7741 --- /dev/null +++ b/python/venv.py @@ -0,0 +1,69 @@ +"""Quiz 7.""" + +# 1. Что делает команда python -m venv venv? +# +# Ответ: создаёт виртуальное окружение, название окружения venv +# +# 1.1 Что делает каждая команда в списке ниже? +# +# pip list - отображает пакеты, находящиеся в pip +# pip freeze > requirements.txt - выгружает все пакеты в один файл, который называется requirements.txt. +# pip install -r requirements.txt - устанавливает все пакеты из файла requirements.txt одним махом. +# +# 2. Что делает каждая команда в списке ниже? +# +# conda env list - используется для отображения списка всех существующих окружений conda вместе с путями к ним в файловой системе. +# conda create -n env_name python=3.5 - создаёт виртуальное окружение conda с именем env_name, здесь python=3.5 - версия питона. +# conda env update -n env_name -f file.yml - обновляет окружение env_name зависимостями из yaml-файла. +# source activate env_name - активирует виртуальное окружение с именем env_name. +# source deactivate - деактивирует виртуальное окружение +# conda clean -all - удаляет кэш и неиспользуемые пакеты. +# +# 3. Вставьте скрин вашего терминала, где вы активировали сначала venv, потом conda, назовите окружение “Senatorov”. +# +# Ответ: image.png +# 4. Как установить необходимые пакеты внутрь виртуального окружения для conda/venv? +# +# Ответ: 1) для venv: +# -активация нужного окружения и установка нужных зависимостей с помощью команды pip install “имя зависимости”. +# -создать файл requirements.txt, записать туда все необходимые зависимости и с помощью команды pip install -r requirements.txt установить их. +# 2) для conda: +# -активация нужного окружения и установка нужных зависимостей с помощью команды conda install “имя зависимости”. +# -создать файл environment.yml, записать туда все необходимые зависимости и с помощью команды conda env update -f environment.yml установить их или обновить. +# +# 5. Что делают эти команды? +# +# pip freeze > requirements.txt -выгружает все пакеты venv в один файл, который называется requirements.txt. +# conda env export > environment.yml - выгружает файлы зависимостей conda в файл environment.yml +# +# 5.1 вставьте скрин, где будет видна папка VENV в вашем репозитории а также файлы зависимостей requirements.txt и environment.yml, файлы должны содержать зависимости +# Ответ: image.png +# image.png +# 6. Что делают эти команды? +# +# pip install -r requirements.txt - устанавливает файлы зависимостей, находящиеся в requirements.txt, через пакетный менеджер pip. +# conda env create -f environment.yml - устанавливает файлы зависимостей, находящиеся в environment.yml через пакетный менеджер conda. +# +# 7. Что делают эти команды? +# +# pip list - отображает список зависимостей выбранного окружения в venv. +# pip show - выводит подробную информацию об установленном пакете: его версии, авторе, лицензии, месте установки, описании и зависимостях. +# conda list - отображает список зависимостей выбранного окружения в conda. +# +# 8. Где по умолчанию больше пакетов venv/pip или conda? и почему дата сайентисты используют conda? +# +# Ответ: больше пакетов в conda. В pip нет пакетов для Data science,поэтому дата сайентисты используют conda. +# +# 9. вставьте скрин где будет видно, Выбор интерпретатора Python (conda) в VS Code/cursor +# Ответ: image.png +# +# 10. добавьте в .gitignore папку SENATOROV +# +# 11. Зачем нужно виртуальное окружение? +# Ответ: виртуальное окружение - это изолированное пространство, в котором можно установить необходимую версию Python и пакеты, отличные от тех, которые установлены в системе. Это позволяет предотвратить конфликты между различными версиями Python и пакетов. Позволяет создавать “чистый” проект без лишних зависимостей. +# +# 12. С этого момента надо работать в виртуальном окружении conda, ты научился(-ась) выгружать зависимости и работать с окружением? +# Ответ: да +# 13. Удалите папку VENV, она больше не нужна, мы же не разрабы, нам нужна только conda +# Ответ: удалила +# From c5877e1ac6867c3476e7f62a73e6670891495a90 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Fri, 30 Jan 2026 23:33:06 +0500 Subject: [PATCH 05/24] [TASK] Commits #5 (https://github.com/SENATOROVAI/intro-cs/issues/5) Closes https://github.com/SENATOROVAI/intro-cs/issues/5 --- python/commits.ipynb | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 python/commits.ipynb diff --git a/python/commits.ipynb b/python/commits.ipynb new file mode 100644 index 00000000..711712e8 --- /dev/null +++ b/python/commits.ipynb @@ -0,0 +1,95 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "84aa8d56", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Commits 5.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Commits 5.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "a5fe8ea0", + "metadata": {}, + "source": [ + "1.\tОпишите своими словами назначение каждого из этих типов коммитов:\n", + "feat, fix, docs, style, refactor, test, build, ci, perf, chore. \n", + "feat - добавление новой функциональности, то есть добавление новых модулей, изменение существующего кода, добавление UI-элементов.\n", + " Пример: \n", + "feat(web): add new icon\n", + "fix - используются для обозначения исправления ошибок(багов) в коде.\n", + "Пример: \n", + "fix(auth): fix token validation issue\n", + "docs - изменения в документации \n", + "Пример:\n", + "docs(readme): добавлена инструкция по установке \n", + "style - внесение правок по стилю(форматирование, пробелы, запятые и т.д.)\n", + "Пример: \n", + "style: форматирование отступов в модуле авторизации \n", + "refactor - изменения(наведение порядка) в коде без изменения его исходной функциональности.\n", + "test - добавление или изменение тестов\n", + "build - изменения, касающиеся сборки проекта - обновление версий библиотек, изменение скриптов сборки, настройки webpack/npm/gulp, обновление конфигурации Docker (связанной со сборкой).\n", + "Пример:\n", + "build: add dependencies for UI components\n", + "ci - настройка или изменение CI/CD (Continuous Integration/Continuous Delivery)\n", + "perl - оптимизация производительности - структурные, синтаксические или функциональные правки в Perl-коде, часто применяемые в рамках обслуживания систем (chore) или исправления ошибок (fix). \n", + "Пример: \n", + "●\tperl: Fix dependency check in script.pl\n", + "chore - прочие задачи (например, изменения в .gitignore),не меняющие код приложения, не исправляющие ошибки и не меняющие функциональности продукта.\n", + "2.\tПредставьте, что вы исправили баг в функции, которая некорректно округляет числа. Сделайте фиктивный коммит и напишите для него сообщение в соответствии с Conventional Commits (используя тип fix).\n", + "Ответ: \n", + "git commit -m “fix: financial rounding“\n", + "3.\tДобавление новой функциональности:\n", + "Допустим, вы реализовали новую функцию generateReport в проекте. Сделайте фиктивный коммит с типом feat, отражающий добавление этой функциональности\n", + "Ответ: \n", + "git commit -m “feat: add function generateReport“\n", + "4.\tМодификация формата кода или стилей:\n", + "Представьте, что вы поправили отступы и форматирование во всём проекте, не меняя логики кода. Сделайте фиктивный коммит с типом style. \n", + "Ответ: \n", + "git commit -m “style: replace style errors “\n", + "5.\tДокументация и тестирование:\n", + "Сделайте фиктивный коммит с типом docs, добавляющий или улучшающий документацию для вашей новой функции.\n", + "Ответ: \n", + "git commit -m “docs: update README with new contribution guidelines”\n", + "Сделайте фиктивный коммит с типом test, добавляющий тесты для этой же функции.\n", + "Ответ: \n", + "git commit -m “add mock tests”\n" + ] + } + ], + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From f718a0eb5ae7da6696e30ba1735dd6a340c2c668 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Fri, 30 Jan 2026 23:33:06 +0500 Subject: [PATCH 06/24] [TASK] Commits #5 (https://github.com/SENATOROVAI/intro-cs/issues/5) Closes https://github.com/SENATOROVAI/intro-cs/issues/5 --- python/commits.ipynb | 95 ++++++++++++++++++++++++++++++++++++++++++++ python/commits.py | 45 +++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 python/commits.ipynb create mode 100644 python/commits.py diff --git a/python/commits.ipynb b/python/commits.ipynb new file mode 100644 index 00000000..711712e8 --- /dev/null +++ b/python/commits.ipynb @@ -0,0 +1,95 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "84aa8d56", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Commits 5.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Commits 5.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "a5fe8ea0", + "metadata": {}, + "source": [ + "1.\tОпишите своими словами назначение каждого из этих типов коммитов:\n", + "feat, fix, docs, style, refactor, test, build, ci, perf, chore. \n", + "feat - добавление новой функциональности, то есть добавление новых модулей, изменение существующего кода, добавление UI-элементов.\n", + " Пример: \n", + "feat(web): add new icon\n", + "fix - используются для обозначения исправления ошибок(багов) в коде.\n", + "Пример: \n", + "fix(auth): fix token validation issue\n", + "docs - изменения в документации \n", + "Пример:\n", + "docs(readme): добавлена инструкция по установке \n", + "style - внесение правок по стилю(форматирование, пробелы, запятые и т.д.)\n", + "Пример: \n", + "style: форматирование отступов в модуле авторизации \n", + "refactor - изменения(наведение порядка) в коде без изменения его исходной функциональности.\n", + "test - добавление или изменение тестов\n", + "build - изменения, касающиеся сборки проекта - обновление версий библиотек, изменение скриптов сборки, настройки webpack/npm/gulp, обновление конфигурации Docker (связанной со сборкой).\n", + "Пример:\n", + "build: add dependencies for UI components\n", + "ci - настройка или изменение CI/CD (Continuous Integration/Continuous Delivery)\n", + "perl - оптимизация производительности - структурные, синтаксические или функциональные правки в Perl-коде, часто применяемые в рамках обслуживания систем (chore) или исправления ошибок (fix). \n", + "Пример: \n", + "●\tperl: Fix dependency check in script.pl\n", + "chore - прочие задачи (например, изменения в .gitignore),не меняющие код приложения, не исправляющие ошибки и не меняющие функциональности продукта.\n", + "2.\tПредставьте, что вы исправили баг в функции, которая некорректно округляет числа. Сделайте фиктивный коммит и напишите для него сообщение в соответствии с Conventional Commits (используя тип fix).\n", + "Ответ: \n", + "git commit -m “fix: financial rounding“\n", + "3.\tДобавление новой функциональности:\n", + "Допустим, вы реализовали новую функцию generateReport в проекте. Сделайте фиктивный коммит с типом feat, отражающий добавление этой функциональности\n", + "Ответ: \n", + "git commit -m “feat: add function generateReport“\n", + "4.\tМодификация формата кода или стилей:\n", + "Представьте, что вы поправили отступы и форматирование во всём проекте, не меняя логики кода. Сделайте фиктивный коммит с типом style. \n", + "Ответ: \n", + "git commit -m “style: replace style errors “\n", + "5.\tДокументация и тестирование:\n", + "Сделайте фиктивный коммит с типом docs, добавляющий или улучшающий документацию для вашей новой функции.\n", + "Ответ: \n", + "git commit -m “docs: update README with new contribution guidelines”\n", + "Сделайте фиктивный коммит с типом test, добавляющий тесты для этой же функции.\n", + "Ответ: \n", + "git commit -m “add mock tests”\n" + ] + } + ], + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/commits.py b/python/commits.py new file mode 100644 index 00000000..ad27d6fe --- /dev/null +++ b/python/commits.py @@ -0,0 +1,45 @@ +"""Commits 5.""" + +# 1. Опишите своими словами назначение каждого из этих типов коммитов: +# feat, fix, docs, style, refactor, test, build, ci, perf, chore. +# feat - добавление новой функциональности, то есть добавление новых модулей, изменение существующего кода, добавление UI-элементов. +# Пример: +# feat(web): add new icon +# fix - используются для обозначения исправления ошибок(багов) в коде. +# Пример: +# fix(auth): fix token validation issue +# docs - изменения в документации +# Пример: +# docs(readme): добавлена инструкция по установке +# style - внесение правок по стилю(форматирование, пробелы, запятые и т.д.) +# Пример: +# style: форматирование отступов в модуле авторизации +# refactor - изменения(наведение порядка) в коде без изменения его исходной функциональности. +# test - добавление или изменение тестов +# build - изменения, касающиеся сборки проекта - обновление версий библиотек, изменение скриптов сборки, настройки webpack/npm/gulp, обновление конфигурации Docker (связанной со сборкой). +# Пример: +# build: add dependencies for UI components +# ci - настройка или изменение CI/CD (Continuous Integration/Continuous Delivery) +# perl - оптимизация производительности - структурные, синтаксические или функциональные правки в Perl-коде, часто применяемые в рамках обслуживания систем (chore) или исправления ошибок (fix). +# Пример: +# ● perl: Fix dependency check in script.pl +# chore - прочие задачи (например, изменения в .gitignore),не меняющие код приложения, не исправляющие ошибки и не меняющие функциональности продукта. +# 2. Представьте, что вы исправили баг в функции, которая некорректно округляет числа. Сделайте фиктивный коммит и напишите для него сообщение в соответствии с Conventional Commits (используя тип fix). +# Ответ: +# git commit -m “fix: financial rounding“ +# 3. Добавление новой функциональности: +# Допустим, вы реализовали новую функцию generateReport в проекте. Сделайте фиктивный коммит с типом feat, отражающий добавление этой функциональности +# Ответ: +# git commit -m “feat: add function generateReport“ +# 4. Модификация формата кода или стилей: +# Представьте, что вы поправили отступы и форматирование во всём проекте, не меняя логики кода. Сделайте фиктивный коммит с типом style. +# Ответ: +# git commit -m “style: replace style errors “ +# 5. Документация и тестирование: +# Сделайте фиктивный коммит с типом docs, добавляющий или улучшающий документацию для вашей новой функции. +# Ответ: +# git commit -m “docs: update README with new contribution guidelines” +# Сделайте фиктивный коммит с типом test, добавляющий тесты для этой же функции. +# Ответ: +# git commit -m “add mock tests” +# From 760439c9fb7b994550127b6fb76f0d3c09f90eef Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 2 Feb 2026 23:22:17 +0500 Subject: [PATCH 07/24] [TASK] Issues # 2 (https://github.com/SENATOROVAI/intro-cs/issues/2) Closes https://github.com/SENATOROVAI/intro-cs/issues/2 --- python/issues.ipynb | 190 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 python/issues.ipynb diff --git a/python/issues.ipynb b/python/issues.ipynb new file mode 100644 index 00000000..3c86586c --- /dev/null +++ b/python/issues.ipynb @@ -0,0 +1,190 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "719c7baf", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Issues Task 2.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "7af62bfb", + "metadata": {}, + "source": [ + "[TASK] issues #2\n", + "Общие вопросы\n", + "1. Что такое Issues на GitHub и для чего они используются?\n", + "Ответ: Issues — это встроенная на GitHub система учёта задач, багов и предложений,\n", + "позволяющая как разработчикам, так и пользователям сообщать о проблемах,\n", + "предлагать улучшения и обсуждать различные аспекты проекта.\n", + "2. Чем Issues отличаются от других инструментов управления задачами?\n", + "Ответ: Issues связаны непосредственно с репозиторием, автоматически связываются с\n", + "коммитами и пулл-реквестами, имеют встроенную систему меток и milestone’ов, и\n", + "доступны всем участникам репозитория.\n", + "3. Какие основные компоненты (поля) есть у каждого Issue?\n", + "Ответ: Title (заголовок) и Description(описание), теги(Labels), исполнителя (Assignees),\n", + "Milestone, связанные Pull Requests, комментарии, статус, дата создания и последнего\n", + "обновления.\n", + "Создание Issues\n", + "4. Как создать новое Issue в репозитории?\n", + "Ответ: чтобы создать новый Issue, нужно зайти в репозиторий. Допустим, мы нашли\n", + "файл с проблемным кодом. Выделяем строки проблемной кода в файле, копируем\n", + "permalink. Затем нужно открыть вкладку “Issues” нажать зеленую кнопку “New Issue”.\n", + "Далее заполняем заголовок(Title) и описание (Description), при необходимости можно\n", + "использовать шаблоны, затем нажимаем на кнопку «Submit new issue».\n", + "5. Какие данные рекомендуется указывать в описании Issue для лучшего\n", + "понимания задачи?\n", + "Ответ: содержание задачи. Например, файл и строки кода, которые нужно\n", + "прокомментировать.\n", + "6. Какие теги (labels) можно добавить к Issue? Какие из них стандартные?\n", + "Ответ: по умолчанию, GitHub предлагает следующие метки:\n", + "bug - что-то не работает\n", + "documentation - улучшение или добавление документации\n", + "duplicate - указывает на то, что такой Issue уже существует.\n", + "enhancement - указывает на новые запросы функций\n", + "good first Issue - для тех, кто создаёт Issue впервые\n", + "help wanted - указывает на то, что нужна помощь по какому-либо вопросу или запросу\n", + "на слияние\n", + "invalid - указывает на неактуальность\n", + "question - указывает на необходимость получения информации\n", + "wontfix - указывает на то, что работа над проблемой продолжаться не будет.\n", + "Эти метки могут быть отредактированы или удалены, а также можно создать\n", + "собственные метки.\n", + "7. Как прикрепить Assignees (ответственных) к Issue?\n", + "Ответ: справа на панели в разделе “Assignees” выберите “Редактировать”. Из\n", + "выпадающего списка нужно выбрать пользователя, которого хотите назначить в\n", + "качестве ответственного.\n", + "Работа с Issues\n", + "8. Как использовать Labels для классификации задач?\n", + "В каждом новом репозитории есть набор стандартных labels, их можно редактировать\n", + "или удалять, также можно создать новые labels. Теги должны соответствовать целям\n", + "Issue.\n", + "9. Для чего нужен Milestone, и как связать его с Issue?\n", + "Ответ: Milestones - это контрольные точки, способ группировки связанных задач,\n", + "направленных на достижение конкретного результата. Например, можно сгруппировать\n", + "Issues по дате.\n", + "Чтобы связать Milestone c Issue, нужно:\n", + "- перейти на страницу репозитория\n", + "- нажать на вкладку Issues и выбрать Issue, которое вы хотите связать\n", + "- выбрать наверху в меню Milestones\n", + "- в поле “Filter Milestones” начните вводить название существующего Milestone,\n", + "затем щёлкните по названию, чтобы связать его с элементом.\n", + "10. Как привязать Issue к пул-реквесту (Pull Request)?\n", + "Ответ: в описании или комментарии к Pull Request написать “Closes #11 или Fixed #11\n", + "(здесь 11 - номер Issue). Issue автоматически закроется при слиянии PR.\n", + "11. Как добавить комментарий к существующему Issue?\n", + "Ответ: внизу есть поле для комментариев.\n", + "Закрытие и завершение Issues\n", + "12. Как закрыть Issue вручную?\n", + "Ответ: открыть нужный Issue, прокрутить вниз и нажать кнопку “Close issue”.\n", + "13. Можно ли автоматически закрыть Issue с помощью сообщения в коммите или\n", + "пул-реквесте? Как это сделать?\n", + "Ответ: зайти в файл, сделать исправления, на верхней панели в правом углу выбрать\n", + "“Commit changes“. Заполнить заголовок и описание коммита и нажать на “Sign off and\n", + "commit changes“.\n", + "14. Как повторно открыть закрытое Issue, если работа ещё не завершена?\n", + "Ответ: перейти на страницу репозитория, нажать на вкладку Issues и в списке Closed\n", + "выбрать Issue, которое вы хотите открыть заново. Нажатием на заголовок перейдите в\n", + "Issue и внизу кликните по кнопке “Reopen issue”.\n", + "Фильтрация и поиск\n", + "15. Как найти все открытые или закрытые Issues в репозитории?\n", + "Ответ: перейти на страницу репозитория, нажать на вкладку Issues. Появится список с\n", + "двумя вкладками: Open и Closed.\n", + "16. Как использовать фильтры для поиска Issues по меткам, исполнителям или\n", + "другим критериям?\n", + "Ответ: рядом с вкладками Open и Closed есть вкладки “Author”, “Labels”, “Projects”,\n", + "“Milestones”.\n", + "17. Как сортировать Issues по приоритету, дате создания или другим параметрам?\n", + "Ответ: на верхней панели в правом верхнем углу нажать на три точки, появится\n", + "ниспадающее меню, выбрать Sort by …(Created on, last updated, Total comments, Best\n", + "match, Reactions)\n", + "Интеграции и автоматизация\n", + "18. Как настроить автоматические уведомления о новых или изменённых Issues?\n", + "Ответ: в профиле пользователя можно на вкладке Notifications настроить уведомления.\n", + "19. Что такое Projects в контексте GitHub, и как связать их с Issues?\n", + "Ответ: GitHub Projects - инструменты для создания Канбан-досок и таблиц,\n", + "позволяющие визуализировать рабочие процессы и отслеживать прогресс выполнения\n", + "задач.\n", + "Чтобы связать project c issue, нужно перейти в проект, в нижней строке любого столбца\n", + "или списка (рядом со знаком «+») нажмите знак плюса или просто поместить туда\n", + "курсор. Затем можно:\n", + "- вставить URL существующей Issue и нажать Enter.\n", + "- Найти существующую issue, набрав #, а затем номер или заголовок задачи, и\n", + "выбрать ее из результатов.\n", + "- создать новую issue, ввести заголовок и нажать Enter. Вы можете щелкнуть по\n", + "новому элементу, чтобы добавить дополнительные сведения (описание,\n", + "ответственные, метки).\n", + "20. Какие сторонние инструменты можно использовать для автоматизации работы с\n", + "Issues (например, боты, Webhooks)?\n", + "Ответ:\n", + "Zapier - сервис автоматизации рабочих действий, включает отслеживание новых\n", + "Issue/комментариев, автоматическое назначение задач, обновление статусов и\n", + "уведомления в мессенджерах (Slack, Discord) при пушах или релизах\n", + "Probot - платформа для создания GitHub ботов, которые могут автоматически\n", + "реагировать на действия в репозитории, например на создание Issues.\n", + "IFTTT (If This Then That) — это облачная платформа и приложение для\n", + "автоматизации взаимодействия между различными веб-сервисами и\n", + "приложениями, включая GitHub.\n", + "Webhooks - встроенная функция GitHub, которая позволяет отправлять HTTP\n", + "POST запросы на указанный URL при определённых событиях (например,\n", + "создание или изменение Issues).\n", + "21.\n", + "Коллаборация\n", + "21. Как упомянуть другого пользователя в комментарии к Issue?\n", + "Ответ: нужно использовать символ @, после которого вводится имя пользователя,\n", + "например @svetlana-s88. Упомянутый пользователь получит уведомление о том, что\n", + "его упомянули в комментарии.\n", + "22. Как запросить дополнительные данные или уточнения у автора Issue?\n", + "Ответ: все вопросы можно задать в комментарии к Issue.\n", + "23. Что делать, если Issue неактуально или его нужно объединить с другим?\n", + "Ответ: если Issue неактуально, его можно закрыть с помощью кнопки Close issue,\n", + "написав при этом комментарий об неактуальности.\n", + "Для объединения Issue с другим можно использовать метку “duplicate”. В комментарии\n", + "к этому Issue нужно вставить ссылку на основной Issue, затем этот Issue закрыть.\n", + "Практические аспекты\n", + "24. Как использовать шаблоны для создания Issues?\n", + "Ответ: В репозитории нужно создать папку .github/ISSUE_TEMPLATE. В этой папке\n", + "нужно создать файлы формата .mb для каждого шаблона, например, bug_report.mb,\n", + "feature_request.mb. В каждом файле описать структуру шаблона, включая заголовки и\n", + "инструкцию по заполнению.\n", + "25. Что такое Linked Issues, и как создать связь между задачами?\n", + "Ответ: Чтобы создать связь между задачами, нужно: \n", + "- Открыть Issue или пул-реквест,\n", + "который хотим связать с другим.\n", + "- На правой боковой панели найти раздел \"Linked\n", + "issues\". \n", + "- Нажать \"Link an issue\" и выбрать Issue из списка или ввести его номер. \n", + "- Выбрать тип связи, например, \"blocks\" (блокирует), \"is blocked by\" (заблокирован) или\n", + "\"relates to\" (связан с).\n", + "- Нажать \"Link\" для создания связи.\n", + "26. Какие метрики (например, время выполнения) можно отслеживать с помощью\n", + "Issues?\n", + "Ответ:\n", + "- Time to Close: Время, прошедшее с момента создания Issue до его закрытия.\n", + "- Количество комментариев\n", + "- Количество открытых и закрытых Issues\n", + "- Среднее время ответа: Время, которое проходит между созданием Issue и первым\n", + "комментарием или ответом от команды.\n", + "- Количество переоткрытий: Сколько раз Issue было закрыто и затем повторно открыто,\n", + "что может указывать на сложность задачи или недостаток информации.\n", + "- Распределение по меткам: Анализ количества Issues по разным меткам (например,\n", + "баги, улучшения) для понимания основных проблем в проекте.\n", + "27. Какие best practices рекомендуются при работе с Issues в команде?\n", + "Ответ:\n", + "- закрывать устаревшие Issue и дубликаты;\n", + "- ссылаться на связанные Pull Requests или коммиты." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From ed19d6b44b1285728246b6a001ded9f3a49251ca Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 2 Feb 2026 23:22:17 +0500 Subject: [PATCH 08/24] [TASK] Issues # 2 (https://github.com/SENATOROVAI/intro-cs/issues/2) Closes https://github.com/SENATOROVAI/intro-cs/issues/2 --- python/issues.ipynb | 190 ++++++++++++++++++++++++++++++++++++++++++++ python/issues.py | 164 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 python/issues.ipynb create mode 100644 python/issues.py diff --git a/python/issues.ipynb b/python/issues.ipynb new file mode 100644 index 00000000..3c86586c --- /dev/null +++ b/python/issues.ipynb @@ -0,0 +1,190 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "719c7baf", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Issues Task 2.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "7af62bfb", + "metadata": {}, + "source": [ + "[TASK] issues #2\n", + "Общие вопросы\n", + "1. Что такое Issues на GitHub и для чего они используются?\n", + "Ответ: Issues — это встроенная на GitHub система учёта задач, багов и предложений,\n", + "позволяющая как разработчикам, так и пользователям сообщать о проблемах,\n", + "предлагать улучшения и обсуждать различные аспекты проекта.\n", + "2. Чем Issues отличаются от других инструментов управления задачами?\n", + "Ответ: Issues связаны непосредственно с репозиторием, автоматически связываются с\n", + "коммитами и пулл-реквестами, имеют встроенную систему меток и milestone’ов, и\n", + "доступны всем участникам репозитория.\n", + "3. Какие основные компоненты (поля) есть у каждого Issue?\n", + "Ответ: Title (заголовок) и Description(описание), теги(Labels), исполнителя (Assignees),\n", + "Milestone, связанные Pull Requests, комментарии, статус, дата создания и последнего\n", + "обновления.\n", + "Создание Issues\n", + "4. Как создать новое Issue в репозитории?\n", + "Ответ: чтобы создать новый Issue, нужно зайти в репозиторий. Допустим, мы нашли\n", + "файл с проблемным кодом. Выделяем строки проблемной кода в файле, копируем\n", + "permalink. Затем нужно открыть вкладку “Issues” нажать зеленую кнопку “New Issue”.\n", + "Далее заполняем заголовок(Title) и описание (Description), при необходимости можно\n", + "использовать шаблоны, затем нажимаем на кнопку «Submit new issue».\n", + "5. Какие данные рекомендуется указывать в описании Issue для лучшего\n", + "понимания задачи?\n", + "Ответ: содержание задачи. Например, файл и строки кода, которые нужно\n", + "прокомментировать.\n", + "6. Какие теги (labels) можно добавить к Issue? Какие из них стандартные?\n", + "Ответ: по умолчанию, GitHub предлагает следующие метки:\n", + "bug - что-то не работает\n", + "documentation - улучшение или добавление документации\n", + "duplicate - указывает на то, что такой Issue уже существует.\n", + "enhancement - указывает на новые запросы функций\n", + "good first Issue - для тех, кто создаёт Issue впервые\n", + "help wanted - указывает на то, что нужна помощь по какому-либо вопросу или запросу\n", + "на слияние\n", + "invalid - указывает на неактуальность\n", + "question - указывает на необходимость получения информации\n", + "wontfix - указывает на то, что работа над проблемой продолжаться не будет.\n", + "Эти метки могут быть отредактированы или удалены, а также можно создать\n", + "собственные метки.\n", + "7. Как прикрепить Assignees (ответственных) к Issue?\n", + "Ответ: справа на панели в разделе “Assignees” выберите “Редактировать”. Из\n", + "выпадающего списка нужно выбрать пользователя, которого хотите назначить в\n", + "качестве ответственного.\n", + "Работа с Issues\n", + "8. Как использовать Labels для классификации задач?\n", + "В каждом новом репозитории есть набор стандартных labels, их можно редактировать\n", + "или удалять, также можно создать новые labels. Теги должны соответствовать целям\n", + "Issue.\n", + "9. Для чего нужен Milestone, и как связать его с Issue?\n", + "Ответ: Milestones - это контрольные точки, способ группировки связанных задач,\n", + "направленных на достижение конкретного результата. Например, можно сгруппировать\n", + "Issues по дате.\n", + "Чтобы связать Milestone c Issue, нужно:\n", + "- перейти на страницу репозитория\n", + "- нажать на вкладку Issues и выбрать Issue, которое вы хотите связать\n", + "- выбрать наверху в меню Milestones\n", + "- в поле “Filter Milestones” начните вводить название существующего Milestone,\n", + "затем щёлкните по названию, чтобы связать его с элементом.\n", + "10. Как привязать Issue к пул-реквесту (Pull Request)?\n", + "Ответ: в описании или комментарии к Pull Request написать “Closes #11 или Fixed #11\n", + "(здесь 11 - номер Issue). Issue автоматически закроется при слиянии PR.\n", + "11. Как добавить комментарий к существующему Issue?\n", + "Ответ: внизу есть поле для комментариев.\n", + "Закрытие и завершение Issues\n", + "12. Как закрыть Issue вручную?\n", + "Ответ: открыть нужный Issue, прокрутить вниз и нажать кнопку “Close issue”.\n", + "13. Можно ли автоматически закрыть Issue с помощью сообщения в коммите или\n", + "пул-реквесте? Как это сделать?\n", + "Ответ: зайти в файл, сделать исправления, на верхней панели в правом углу выбрать\n", + "“Commit changes“. Заполнить заголовок и описание коммита и нажать на “Sign off and\n", + "commit changes“.\n", + "14. Как повторно открыть закрытое Issue, если работа ещё не завершена?\n", + "Ответ: перейти на страницу репозитория, нажать на вкладку Issues и в списке Closed\n", + "выбрать Issue, которое вы хотите открыть заново. Нажатием на заголовок перейдите в\n", + "Issue и внизу кликните по кнопке “Reopen issue”.\n", + "Фильтрация и поиск\n", + "15. Как найти все открытые или закрытые Issues в репозитории?\n", + "Ответ: перейти на страницу репозитория, нажать на вкладку Issues. Появится список с\n", + "двумя вкладками: Open и Closed.\n", + "16. Как использовать фильтры для поиска Issues по меткам, исполнителям или\n", + "другим критериям?\n", + "Ответ: рядом с вкладками Open и Closed есть вкладки “Author”, “Labels”, “Projects”,\n", + "“Milestones”.\n", + "17. Как сортировать Issues по приоритету, дате создания или другим параметрам?\n", + "Ответ: на верхней панели в правом верхнем углу нажать на три точки, появится\n", + "ниспадающее меню, выбрать Sort by …(Created on, last updated, Total comments, Best\n", + "match, Reactions)\n", + "Интеграции и автоматизация\n", + "18. Как настроить автоматические уведомления о новых или изменённых Issues?\n", + "Ответ: в профиле пользователя можно на вкладке Notifications настроить уведомления.\n", + "19. Что такое Projects в контексте GitHub, и как связать их с Issues?\n", + "Ответ: GitHub Projects - инструменты для создания Канбан-досок и таблиц,\n", + "позволяющие визуализировать рабочие процессы и отслеживать прогресс выполнения\n", + "задач.\n", + "Чтобы связать project c issue, нужно перейти в проект, в нижней строке любого столбца\n", + "или списка (рядом со знаком «+») нажмите знак плюса или просто поместить туда\n", + "курсор. Затем можно:\n", + "- вставить URL существующей Issue и нажать Enter.\n", + "- Найти существующую issue, набрав #, а затем номер или заголовок задачи, и\n", + "выбрать ее из результатов.\n", + "- создать новую issue, ввести заголовок и нажать Enter. Вы можете щелкнуть по\n", + "новому элементу, чтобы добавить дополнительные сведения (описание,\n", + "ответственные, метки).\n", + "20. Какие сторонние инструменты можно использовать для автоматизации работы с\n", + "Issues (например, боты, Webhooks)?\n", + "Ответ:\n", + "Zapier - сервис автоматизации рабочих действий, включает отслеживание новых\n", + "Issue/комментариев, автоматическое назначение задач, обновление статусов и\n", + "уведомления в мессенджерах (Slack, Discord) при пушах или релизах\n", + "Probot - платформа для создания GitHub ботов, которые могут автоматически\n", + "реагировать на действия в репозитории, например на создание Issues.\n", + "IFTTT (If This Then That) — это облачная платформа и приложение для\n", + "автоматизации взаимодействия между различными веб-сервисами и\n", + "приложениями, включая GitHub.\n", + "Webhooks - встроенная функция GitHub, которая позволяет отправлять HTTP\n", + "POST запросы на указанный URL при определённых событиях (например,\n", + "создание или изменение Issues).\n", + "21.\n", + "Коллаборация\n", + "21. Как упомянуть другого пользователя в комментарии к Issue?\n", + "Ответ: нужно использовать символ @, после которого вводится имя пользователя,\n", + "например @svetlana-s88. Упомянутый пользователь получит уведомление о том, что\n", + "его упомянули в комментарии.\n", + "22. Как запросить дополнительные данные или уточнения у автора Issue?\n", + "Ответ: все вопросы можно задать в комментарии к Issue.\n", + "23. Что делать, если Issue неактуально или его нужно объединить с другим?\n", + "Ответ: если Issue неактуально, его можно закрыть с помощью кнопки Close issue,\n", + "написав при этом комментарий об неактуальности.\n", + "Для объединения Issue с другим можно использовать метку “duplicate”. В комментарии\n", + "к этому Issue нужно вставить ссылку на основной Issue, затем этот Issue закрыть.\n", + "Практические аспекты\n", + "24. Как использовать шаблоны для создания Issues?\n", + "Ответ: В репозитории нужно создать папку .github/ISSUE_TEMPLATE. В этой папке\n", + "нужно создать файлы формата .mb для каждого шаблона, например, bug_report.mb,\n", + "feature_request.mb. В каждом файле описать структуру шаблона, включая заголовки и\n", + "инструкцию по заполнению.\n", + "25. Что такое Linked Issues, и как создать связь между задачами?\n", + "Ответ: Чтобы создать связь между задачами, нужно: \n", + "- Открыть Issue или пул-реквест,\n", + "который хотим связать с другим.\n", + "- На правой боковой панели найти раздел \"Linked\n", + "issues\". \n", + "- Нажать \"Link an issue\" и выбрать Issue из списка или ввести его номер. \n", + "- Выбрать тип связи, например, \"blocks\" (блокирует), \"is blocked by\" (заблокирован) или\n", + "\"relates to\" (связан с).\n", + "- Нажать \"Link\" для создания связи.\n", + "26. Какие метрики (например, время выполнения) можно отслеживать с помощью\n", + "Issues?\n", + "Ответ:\n", + "- Time to Close: Время, прошедшее с момента создания Issue до его закрытия.\n", + "- Количество комментариев\n", + "- Количество открытых и закрытых Issues\n", + "- Среднее время ответа: Время, которое проходит между созданием Issue и первым\n", + "комментарием или ответом от команды.\n", + "- Количество переоткрытий: Сколько раз Issue было закрыто и затем повторно открыто,\n", + "что может указывать на сложность задачи или недостаток информации.\n", + "- Распределение по меткам: Анализ количества Issues по разным меткам (например,\n", + "баги, улучшения) для понимания основных проблем в проекте.\n", + "27. Какие best practices рекомендуются при работе с Issues в команде?\n", + "Ответ:\n", + "- закрывать устаревшие Issue и дубликаты;\n", + "- ссылаться на связанные Pull Requests или коммиты." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/issues.py b/python/issues.py new file mode 100644 index 00000000..bc8dba50 --- /dev/null +++ b/python/issues.py @@ -0,0 +1,164 @@ +"""Issues Task 2.""" + +# [TASK] issues #2 +# Общие вопросы +# 1. Что такое Issues на GitHub и для чего они используются? +# Ответ: Issues — это встроенная на GitHub система учёта задач, багов и предложений, +# позволяющая как разработчикам, так и пользователям сообщать о проблемах, +# предлагать улучшения и обсуждать различные аспекты проекта. +# 2. Чем Issues отличаются от других инструментов управления задачами? +# Ответ: Issues связаны непосредственно с репозиторием, автоматически связываются с +# коммитами и пулл-реквестами, имеют встроенную систему меток и milestone’ов, и +# доступны всем участникам репозитория. +# 3. Какие основные компоненты (поля) есть у каждого Issue? +# Ответ: Title (заголовок) и Description(описание), теги(Labels), исполнителя (Assignees), +# Milestone, связанные Pull Requests, комментарии, статус, дата создания и последнего +# обновления. +# Создание Issues +# 4. Как создать новое Issue в репозитории? +# Ответ: чтобы создать новый Issue, нужно зайти в репозиторий. Допустим, мы нашли +# файл с проблемным кодом. Выделяем строки проблемной кода в файле, копируем +# permalink. Затем нужно открыть вкладку “Issues” нажать зеленую кнопку “New Issue”. +# Далее заполняем заголовок(Title) и описание (Description), при необходимости можно +# использовать шаблоны, затем нажимаем на кнопку «Submit new issue». +# 5. Какие данные рекомендуется указывать в описании Issue для лучшего +# понимания задачи? +# Ответ: содержание задачи. Например, файл и строки кода, которые нужно +# прокомментировать. +# 6. Какие теги (labels) можно добавить к Issue? Какие из них стандартные? +# Ответ: по умолчанию, GitHub предлагает следующие метки: +# bug - что-то не работает +# documentation - улучшение или добавление документации +# duplicate - указывает на то, что такой Issue уже существует. +# enhancement - указывает на новые запросы функций +# good first Issue - для тех, кто создаёт Issue впервые +# help wanted - указывает на то, что нужна помощь по какому-либо вопросу или запросу +# на слияние +# invalid - указывает на неактуальность +# question - указывает на необходимость получения информации +# wontfix - указывает на то, что работа над проблемой продолжаться не будет. +# Эти метки могут быть отредактированы или удалены, а также можно создать +# собственные метки. +# 7. Как прикрепить Assignees (ответственных) к Issue? +# Ответ: справа на панели в разделе “Assignees” выберите “Редактировать”. Из +# выпадающего списка нужно выбрать пользователя, которого хотите назначить в +# качестве ответственного. +# Работа с Issues +# 8. Как использовать Labels для классификации задач? +# В каждом новом репозитории есть набор стандартных labels, их можно редактировать +# или удалять, также можно создать новые labels. Теги должны соответствовать целям +# Issue. +# 9. Для чего нужен Milestone, и как связать его с Issue? +# Ответ: Milestones - это контрольные точки, способ группировки связанных задач, +# направленных на достижение конкретного результата. Например, можно сгруппировать +# Issues по дате. +# Чтобы связать Milestone c Issue, нужно: +# - перейти на страницу репозитория +# - нажать на вкладку Issues и выбрать Issue, которое вы хотите связать +# - выбрать наверху в меню Milestones +# - в поле “Filter Milestones” начните вводить название существующего Milestone, +# затем щёлкните по названию, чтобы связать его с элементом. +# 10. Как привязать Issue к пул-реквесту (Pull Request)? +# Ответ: в описании или комментарии к Pull Request написать “Closes #11 или Fixed #11 +# (здесь 11 - номер Issue). Issue автоматически закроется при слиянии PR. +# 11. Как добавить комментарий к существующему Issue? +# Ответ: внизу есть поле для комментариев. +# Закрытие и завершение Issues +# 12. Как закрыть Issue вручную? +# Ответ: открыть нужный Issue, прокрутить вниз и нажать кнопку “Close issue”. +# 13. Можно ли автоматически закрыть Issue с помощью сообщения в коммите или +# пул-реквесте? Как это сделать? +# Ответ: зайти в файл, сделать исправления, на верхней панели в правом углу выбрать +# “Commit changes“. Заполнить заголовок и описание коммита и нажать на “Sign off and +# commit changes“. +# 14. Как повторно открыть закрытое Issue, если работа ещё не завершена? +# Ответ: перейти на страницу репозитория, нажать на вкладку Issues и в списке Closed +# выбрать Issue, которое вы хотите открыть заново. Нажатием на заголовок перейдите в +# Issue и внизу кликните по кнопке “Reopen issue”. +# Фильтрация и поиск +# 15. Как найти все открытые или закрытые Issues в репозитории? +# Ответ: перейти на страницу репозитория, нажать на вкладку Issues. Появится список с +# двумя вкладками: Open и Closed. +# 16. Как использовать фильтры для поиска Issues по меткам, исполнителям или +# другим критериям? +# Ответ: рядом с вкладками Open и Closed есть вкладки “Author”, “Labels”, “Projects”, +# “Milestones”. +# 17. Как сортировать Issues по приоритету, дате создания или другим параметрам? +# Ответ: на верхней панели в правом верхнем углу нажать на три точки, появится +# ниспадающее меню, выбрать Sort by …(Created on, last updated, Total comments, Best +# match, Reactions) +# Интеграции и автоматизация +# 18. Как настроить автоматические уведомления о новых или изменённых Issues? +# Ответ: в профиле пользователя можно на вкладке Notifications настроить уведомления. +# 19. Что такое Projects в контексте GitHub, и как связать их с Issues? +# Ответ: GitHub Projects - инструменты для создания Канбан-досок и таблиц, +# позволяющие визуализировать рабочие процессы и отслеживать прогресс выполнения +# задач. +# Чтобы связать project c issue, нужно перейти в проект, в нижней строке любого столбца +# или списка (рядом со знаком «+») нажмите знак плюса или просто поместить туда +# курсор. Затем можно: +# - вставить URL существующей Issue и нажать Enter. +# - Найти существующую issue, набрав #, а затем номер или заголовок задачи, и +# выбрать ее из результатов. +# - создать новую issue, ввести заголовок и нажать Enter. Вы можете щелкнуть по +# новому элементу, чтобы добавить дополнительные сведения (описание, +# ответственные, метки). +# 20. Какие сторонние инструменты можно использовать для автоматизации работы с +# Issues (например, боты, Webhooks)? +# Ответ: +# Zapier - сервис автоматизации рабочих действий, включает отслеживание новых +# Issue/комментариев, автоматическое назначение задач, обновление статусов и +# уведомления в мессенджерах (Slack, Discord) при пушах или релизах +# Probot - платформа для создания GitHub ботов, которые могут автоматически +# реагировать на действия в репозитории, например на создание Issues. +# IFTTT (If This Then That) — это облачная платформа и приложение для +# автоматизации взаимодействия между различными веб-сервисами и +# приложениями, включая GitHub. +# Webhooks - встроенная функция GitHub, которая позволяет отправлять HTTP +# POST запросы на указанный URL при определённых событиях (например, +# создание или изменение Issues). +# 21. +# Коллаборация +# 21. Как упомянуть другого пользователя в комментарии к Issue? +# Ответ: нужно использовать символ @, после которого вводится имя пользователя, +# например @svetlana-s88. Упомянутый пользователь получит уведомление о том, что +# его упомянули в комментарии. +# 22. Как запросить дополнительные данные или уточнения у автора Issue? +# Ответ: все вопросы можно задать в комментарии к Issue. +# 23. Что делать, если Issue неактуально или его нужно объединить с другим? +# Ответ: если Issue неактуально, его можно закрыть с помощью кнопки Close issue, +# написав при этом комментарий об неактуальности. +# Для объединения Issue с другим можно использовать метку “duplicate”. В комментарии +# к этому Issue нужно вставить ссылку на основной Issue, затем этот Issue закрыть. +# Практические аспекты +# 24. Как использовать шаблоны для создания Issues? +# Ответ: В репозитории нужно создать папку .github/ISSUE_TEMPLATE. В этой папке +# нужно создать файлы формата .mb для каждого шаблона, например, bug_report.mb, +# feature_request.mb. В каждом файле описать структуру шаблона, включая заголовки и +# инструкцию по заполнению. +# 25. Что такое Linked Issues, и как создать связь между задачами? +# Ответ: Чтобы создать связь между задачами, нужно: +# - Открыть Issue или пул-реквест, +# который хотим связать с другим. +# - На правой боковой панели найти раздел "Linked +# issues". +# - Нажать "Link an issue" и выбрать Issue из списка или ввести его номер. +# - Выбрать тип связи, например, "blocks" (блокирует), "is blocked by" (заблокирован) или +# "relates to" (связан с). +# - Нажать "Link" для создания связи. +# 26. Какие метрики (например, время выполнения) можно отслеживать с помощью +# Issues? +# Ответ: +# - Time to Close: Время, прошедшее с момента создания Issue до его закрытия. +# - Количество комментариев +# - Количество открытых и закрытых Issues +# - Среднее время ответа: Время, которое проходит между созданием Issue и первым +# комментарием или ответом от команды. +# - Количество переоткрытий: Сколько раз Issue было закрыто и затем повторно открыто, +# что может указывать на сложность задачи или недостаток информации. +# - Распределение по меткам: Анализ количества Issues по разным меткам (например, +# баги, улучшения) для понимания основных проблем в проекте. +# 27. Какие best practices рекомендуются при работе с Issues в команде? +# Ответ: +# - закрывать устаревшие Issue и дубликаты; +# - ссылаться на связанные Pull Requests или коммиты. From 872f53f7f5a3293638fb6412411da4413f00718b Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 2 Mar 2026 19:54:54 +0500 Subject: [PATCH 09/24] #576 Closes #576 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 61a9e44d..b4415a30 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,4 @@ - Улучшение курса [множественной регрессии](https://stepik.org/lesson/1792810/step/2?auth=login&unit=1818500), внедрение логической связи вывода матричной формы SSE, спасибо [rizespbya](https://github.com/rizespbya) - Улучшение курса, [множественной регрессии](https://stepik.org/lesson/1792848/step/2?unit=1818537), внедрён аудиопересказ, спасибо [Ekubbo](https://github.com/Ekubbo) +https://t.me/RuslanSenatorov From 57e571f805ba8bc33fbe4c2151e5707a8b525e0a Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Sat, 7 Mar 2026 12:28:14 +0500 Subject: [PATCH 10/24] =?UTF-8?q?[TASK]=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80?= =?UTF-8?q?=D0=B8=D0=B1=D1=8C=D1=8E=D1=82=D0=B8=D0=BD=D0=B3=20=D0=B2=20Ope?= =?UTF-8?q?n=20Source=20(https://github.com/SENATOROVAI/intro-cs/issues/8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/SENATOROVAI/intro-cs/issues/8 --- github/opensource.ipynb | 92 +++++++++++++++++++++ github/opensource.py | 43 ++++++++++ github/quiz.ipynb | 175 ++++++++++++++++++++++++++++++++++++++++ github/quiz.py | 151 ++++++++++++++++++++++++++++++++++ 4 files changed, 461 insertions(+) create mode 100644 github/opensource.ipynb create mode 100644 github/opensource.py create mode 100644 github/quiz.ipynb create mode 100644 github/quiz.py diff --git a/github/opensource.ipynb b/github/opensource.ipynb new file mode 100644 index 00000000..6eca5e7e --- /dev/null +++ b/github/opensource.ipynb @@ -0,0 +1,92 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "db5dd10c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Ответы на вопросы.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Ответы на вопросы.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "839c522b", + "metadata": {}, + "source": [ + "Проект в который вы отправили пул реквест, попадает под определение опенсорса:\n", + "Есть ли у него лицензия? Обычно в корне репозитория находится файл LICENSE.\n", + "Ответ: да, Apache License.\n", + "Напишите название понравившейся компании и ссылку на репозиторий\n", + "Ответ: Yandex CatBoost, ссылка на репозиторий: https://github.com/catboost/catboost\n", + "Проект активно принимает стороннюю помощь?\n", + "Ответ: да\n", + "Напишите второе улучшение которое вы сделали. \n", + "Ответ: исправила описание в файле README.\n", + "Посмотрите на коммиты в основной ветке, напишите общее количество\n", + "Ответ: 50 274 коммита по состоянию на 7.03.2026г.\n", + "Когда был последний коммит? \n", + "Ответ: последний коммит был 5 марта 2026 года\n", + "\n", + "Сколько контрибьюторов у проекта?\n", + "Ответ: 401\n", + "Как часто люди коммитят в репозиторий? (На GitHub выяснить это можно, кликнув по ссылке «Commits» в верхней панели.) \n", + "Ответ: часто, каждую неделю \n", + "\n", + "Сколько сейчас открытых ишью?\n", + "Ответ: 654\n", + "Быстро ли мейнтейнеры реагируют на ишью после того, когда они открываются?\n", + "Ответ: да\n", + "Ведётся ли активное обсуждение ишью?\n", + "Ответ: обсуждение есть, 1-3 человека комментируют.\n", + "Есть ли недавно созданные ишью?\n", + "Ответ: последнее issue было создано на прошлой неделе. \n", + "Есть ли закрытые ишью? (На странице Issues GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые ишью.)\n", + "Ответ: сейчас 1871 закрытых ишью.\n", + "Сколько сейчас открытых пул-реквестов?\n", + "Ответ: 28\n", + "Быстро ли мейнтейнеры реагируют на пул-реквесты после их открытия?\n", + "Ответ: да, в тот же день\n", + "Ведётся ли активное обсуждение пул-реквестов? \n", + "Ответ: \n", + "Есть ли недавно отправленные пул-реквесты?\n", + "Ответ: да\n", + "Как давно были объединены пул-реквесты? (На странице Pull Request GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые пул-реквесты.)\n", + "Ответ: 4 марта 2026\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/github/opensource.py b/github/opensource.py new file mode 100644 index 00000000..d6b38b13 --- /dev/null +++ b/github/opensource.py @@ -0,0 +1,43 @@ +# %% +"""Ответы на вопросы.""" + +# Проект в который вы отправили пул реквест, попадает под определение опенсорса: +# Есть ли у него лицензия? Обычно в корне репозитория находится файл LICENSE. +# Ответ: да, Apache License. +# Напишите название понравившейся компании и ссылку на репозиторий +# Ответ: Yandex CatBoost, ссылка на репозиторий: https://github.com/catboost/catboost +# Проект активно принимает стороннюю помощь? +# Ответ: да +# Напишите второе улучшение которое вы сделали. +# Ответ: исправила описание в файле README. +# Посмотрите на коммиты в основной ветке, напишите общее количество +# Ответ: 50 274 коммита по состоянию на 7.03.2026г. +# Когда был последний коммит? +# Ответ: последний коммит был 5 марта 2026 года +# +# Сколько контрибьюторов у проекта? +# Ответ: 401 +# Как часто люди коммитят в репозиторий? (На GitHub выяснить это можно, кликнув по ссылке «Commits» в верхней панели.) +# Ответ: часто, каждую неделю +# +# Сколько сейчас открытых ишью? +# Ответ: 654 +# Быстро ли мейнтейнеры реагируют на ишью после того, когда они открываются? +# Ответ: да +# Ведётся ли активное обсуждение ишью? +# Ответ: обсуждение есть, 1-3 человека комментируют. +# Есть ли недавно созданные ишью? +# Ответ: последнее issue было создано на прошлой неделе. +# Есть ли закрытые ишью? (На странице Issues GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые ишью.) +# Ответ: сейчас 1871 закрытых ишью. +# Сколько сейчас открытых пул-реквестов? +# Ответ: 28 +# Быстро ли мейнтейнеры реагируют на пул-реквесты после их открытия? +# Ответ: да, в тот же день +# Ведётся ли активное обсуждение пул-реквестов? +# Ответ: +# Есть ли недавно отправленные пул-реквесты? +# Ответ: да +# Как давно были объединены пул-реквесты? (На странице Pull Request GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые пул-реквесты.) +# Ответ: 4 марта 2026 +# diff --git a/github/quiz.ipynb b/github/quiz.ipynb new file mode 100644 index 00000000..2025bdd1 --- /dev/null +++ b/github/quiz.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "bbd208ad", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Quiz Issue 8.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "6c7348c5", + "metadata": {}, + "source": [ + "1.1. Что такое GitHub?\n", + "\n", + "Ответ: GitHub - это крупнейшее хранилище Git-репозиториев, а также центр сотрудничества для миллионов разработчиков и проектов, позволяющий разработчикам со всего мира работать над одним кодом одновременно, не мешая друг другу. \n", + "\n", + "1.2. Как GitHub связан с Git?\n", + "Ответ: Git - это инструмент, локальная система контроля версий, установленная на компьютере пользователя, а GitHub - его облачное хранилище, онлайн-сервис. Git отслеживает изменения локально, а GitHub синхронизирует эти изменения через удаленные репозитории.\n", + "\n", + "1.3. Чем отличается fork репозитория от его клонирования (clone)?\n", + "Ответ: Fork - это создание копии репозитория на GitHub под своим аккаунтом для независимой разработки и внесения изменений (Pull Request). Clone - это загрузка копии репозитория (форкнутого или оригинального) с сервера на локальный компьютер для работы. Форк нужен для внесения вклада в чужие проекты или создание отдельного проекта. Clone - для работы с кодом, локального тестирования и коммитов. \n", + "\n", + "1.4. Зачем нужны и как работают pull requests?\n", + "Ответ: Pull Request (PR) — это механизм в системе контроля версий на GitHub, позволяющий разработчику уведомить коллег о завершении работы над веткой и предложить слияние изменений в основной код. PR нужны для рецензирования кода (code review), обсуждения, тестирования и контроля качества, обеспечивая защиту от ошибок. \n", + "Pull Request работают следующим образом: разработчик создаёт новую ветку для новой фичи или багфикса, вносит изменения и коммитит их в свою ветку, затем создаёт PR, указывая, что хочет слить изменения из своей ветки в целевую. Коллеги просматривают код, оставляют комментарии, автор вносит правки. После одобрения (approval) ответственным лицом изменения вливаются в целевую ветку. \n", + "\n", + "1.5. GitHub использует ваш почтовый адрес для привязки ваших Git коммитов к вашей учётной записи?\n", + "Ответ: Да, GitHub использует ваш почтовый адрес для привязки ваших Git коммитов к вашей учётной записи. Если вы используете несколько почтовых адресов в своих коммитах и хотите, чтобы GitHub работал с ними корректно, то вам нужно будет добавить все используемые почтовые адреса в секцию под названием «Почтовые адреса» («Emails»), расположенную на вкладке «Администрирование» («Admin»).\n", + "\n", + "1.6 Какая команда генерирует SSH ключ для Доступа по SSH к репозиторию (Рисунок 83)\n", + "Ответ: Для генерации SSH-ключа (публичного и приватного) используется команда ssh-keygen. Рекомендуется использовать современный алгоритм Ed25519 для большей безопасности, выполнив в терминале (Linux/MacOS/Git Bash) команду:\n", + "ssh-keygen -t ed25519 -C \"your_email@example.com\"\n", + "\n", + "Создайте ишьюс и запомните его номер, в https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-SENATOROV/issues, назовите его \"UPDATE README\", в дескрипшене добавьте список задач (Рисунок 102)\n", + "2.1. Если вы хотите вносить свой вклад в уже существующие проекты, в которых у нас нет прав на внесения изменений путём отправки (push) изменений, вы можете создать своё собственное ответвление, что нужно сделать чтобы создать собственное ответвление? (Рисунок 88), сделайте ответвление https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-SENATOROV, и вставьте сюда ссылку на ваше ответвление. \n", + "Ответ: нужно создать форк репозитория.\n", + "https://github.com/svetlana-s88/Data-Science-For-Beginners-from-scratch-SENATOROV\n", + "\n", + "2.2 создайте ветку dev в ФОРКЕ Data-Science-For-Beginners, вставьте сюда ссылку на вашу ветку dev\n", + "Ответ:\n", + "https://github.com/svetlana-s88/Data-Science-For-Beginners-from-scratch-SENATOROV/tree/dev\n", + "2.3 В README файле вашего ФОРКА, добавьте ссылку на мой телеграм канал https://t.me/RuslanSenatorov, сохраните коммит, название коммита - в тайтле название ишьюса (#номер_ишьюс), в дескрипшене - Closes #NUMBER-ISSUES номер возьмите из пункта 2\n", + "2.4 Отправьте пул реквест из ФОРКА в основу В ВАШУ ВЕТКУ, тайтл пул реквеста скопируйте из ISSUES-TITLE, в дескрипшине пул реквеста напишите Closes #NUMBER-ISSUES вставьте номер из пункта 2\n", + "2.5 Прокомментириуйте ваш пул реквест перед слиянием, перейдите во вкладку(Рисунок 92) и напишите \"ок\", потом нажимайте сабмит ревью затем не выходя из этой вкладки, в файле README , добавьте туда ссылку на https://t.me/SENATOROVAI,\n", + "=> инструкция\n", + "2.6 Выполните Merge pull request (Рисунок 116), вставьте сюда ссылку на ваш пул реквест\n", + "Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/pull/586\n", + "\n", + "2.7 Вставьте сюда ссылку на закрытые пул реквесты в репозитории, найти можно тут\n", + "Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/pulls?q=is%3Apr+is%3Aclosed\n", + "\n", + "2.8 Как посмотреть какие файлы были в репозитории на момент определенного коммита? вставьте сюда ссылку на любой коммит, где взять ссылку? подсказка:\n", + "Выбираем любой коммит в ВАШЕЙ ВЕТКЕ\n", + "Нажимаем на Browse\n", + "Убедитесь что слева у вас написан номер коммита, потом смотрим какие файлы были в репозитории, на момент этого коммита, это очень полезно если вы накосячили, и хотите откатиться к этому коммиту.\n", + "Поэтому крайне важно называть коммиты ПРАВИЛЬНО, и в коммите должны быть только те файлы которые соответствуют названию коммита, лишних файлов НЕ ДОЛЖНО БЫТЬ, в одном коммите отправлять НЕСКОЛЬКО файлов не надо!\n", + "Как должна выглядеть ссылка\n", + "Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/commit/157a2ecec21a8bc9b5a9ba9c8388db1c6fe2d051\n", + "\n", + "2.9 как открыть запрос слияния, указывающий на другой запрос слияния и зачем это нужно? (Рисунок 117)\n", + "\n", + "Ответ: При открытии запроса на слияние вверху страницы вы увидите меню для выбора целевой и исходной веток. Если нажать кнопку Edit справа, то станет доступным выбор не только исходной ветки, а ещё и форка. \n", + "Это нужно в том случае, если вы видите толковый запрос слияния и у вас есть идея как его улучшить или вы не уверены, что это хорошая идея, или у вас просто нет прав записи в целевую ветку. В таком случае вы можете открыть запрос слияния, указывающий на данный запрос.\n", + " \n", + "Рабочий процесс с использованием GitHub\n", + "3 Напишите 8 пунктов, которые нужно сделать, чтобы внести вклад в чужой проект.\n", + "Ответ: \n", + "Создайте форк проекта \n", + "Создайте тематическую ветку на основании ветки master.\n", + "Создайте один или несколько коммитов с изменениями, улучшающими проект\n", + "Отправьте эту ветку в ваш проект на GitHub\n", + "Откройте запрос на слияние на GitHub\n", + "Обсуждайте его, вносите изменения, если нужно. \n", + "Владелец проекта принимает решение о принятии изменений проекта, либо об их отклонении. \n", + "Получите обновлённую ветку master и отправьте её в свой форк.\n", + "\n", + "3.1.1\n", + "Какие практики принято соблюдать при создании Pull Request чтобы закрыть автоматический issues?\n", + "Ответ: В описании PR указать ключевые слова: \"Closes #номер, Fixes #номер, Resolves #номер для автоматического закрытия Issues. \n", + "\n", + "3.1.2 Какие практики принято соблюдать при создании commit чтобы закрыть автоматический issues?\n", + "Ответ: В заголовке и сообщении коммита указать ключевые слова \"Closes #номер, Fixes #номер, Resolves #номер.\n", + "\n", + "3.2 Как отклонить/закрыть пул реквест? (предоставьте скриншот где это в гитхабе)\n", + "Ответ: чтобы отклонить Pull Request, нужно нажать на него в списке, открыть его, в нижней части нажать на кнопку Revert, затем выполнить слияние PR. \n", + "Чтобы закрыть Pull Request, нужно нажать кнопку Close Pull Request. \n", + "\n", + "3.3 Перед отправкой пул реквеста нужно ли создавать ишьюс?\n", + "Ответ: Не обязательно, но рекомендуется для обсуждения изменений и получения обратной связи перед реализацией. \n", + "\n", + "3.4 В какой вкладке можно посмотреть список изменений который был в пул реквесте? (Рисунок 92)\n", + "Ответ: во вкладке Files Changed.\n", + "3.5 В какой вкладке находится страница обсуждений пул реквеста? (Рисунок 94)\n", + "Ответ: во вкладке Conversation.\n", + "\n", + "Создание запроса на слияние\n", + "4 Можно ли открыть пул реквест, если вы ничего не вносили в FORK?\n", + "Ответ: технически открыть PR можно, но он будет пустым. Если вы хотите обсудить что-то, то лучше использовать Issues, а не PR. \n", + "\n", + "4.1 Что нужно сделать чтобы открыть пул реквест? (Рисунок 90)\n", + "Ответ: после того, как мы создали тематическую ветку, внесли изменения, зафиксировали изменения в тематическую ветку, и отправили ветку на GitHub, мы увидим, что GitHub предлагает нам открыть PR с помощью зеленой кнопки Compare & Pull request. \n", + "\n", + "4.2 Что нужно сделать Если ваш Форк устарел?\n", + "Ответ: Синхронизировать форк с оригинальным репозиторием через кнопку \"Sync fork\" или вручную через git: добавить upstream, выполнить fetch и merge. \n", + "\n", + "4.3 Что нужно сделать если в пул реквесте имеются конфликты слияния (Рисунок 96)\n", + "Ответ: Разрешить конфликты вручную: нажать Resolve conflicts, отредактировать файлы с конфликтами, пометить конфликты как разрешенные, закоммитить изменения. \n", + "Отрывки кода\n", + "5 Что нужно сделать Для добавления отрывка кода в комментарии к ишьюсу? (Рисунок 104)\n", + "Ответ: Для добавления отрывка кода в комментарии к ишьюсу код следует обрамить обратными кавычками. Если указать название языка, то GitHub попробует применить к нему подсветку синтаксиса. \n", + "\n", + "5.1 На какую клавишу нажать клавишу чтобы выделенный текст был включён как цитата в ваш комментарий?(Рисунок 105)\n", + "Ответ: если в комментарии выделить текст, на который вы собираетесь ответить, и нажать клавишу r, то выделенный текст будет включён как цитата в ваш комментарий. \n", + "\n", + "5.2 Как вставить картинку в ишьюс? (Рисунок 108)\n", + "Ответ: перетищить изображение в поле комментария или исподьзовать ссылку в формате Markdown: ![описание](ссылка_на_изображение).\n", + "\n", + "Поддержание GitHub репозитория в актуальном состоянии\n", + "6 Как понять что ваш форк устарел?\n", + "Ответ:Форк устарел, если в оригинальном репозитории (upstream) появились новые коммиты, ветки или релизы, которых нет в вашей копии. В GitHub это видно по сообщению «This branch is X commits behind...», а в консоли — по разнице при git fetch upstream. \n", + "\n", + "6.1 Как обновить форк?\n", + "Ответ: нажать на кнопку \"Sync fork\" на странице форка, затем \"Update branch\", или вручную через git: git fetch upstream, git merge upstream/main, git push. \n", + "\n", + "\n", + "Добавление участников\n", + "7 Как добавить участников в ваш репозиторий, чтобы команда могла работать над одним репозиторием? (Рисунок 112)\n", + "Ответ: нужно зайти в Settings, выбрать “Collaborators” в меню слева. Напишете имя пользователя в поле для ввода и нажмите “Add collaborator”. \n", + "\n", + "Упоминания и уведомления\n", + "8 Какой символ нужен для упоминания кого-либо? (Рисунок 118)\n", + "Ответ: символ @.\n", + "\n", + "8.1 Где находится Центр уведомлений, напишите ссылку (Рисунок 121)\n", + "Ответ: https://github.com/notifications\n", + "\n", + "Особенные файлы\n", + "9 Что такое и зачем нужен файл README\n", + "Ответ: это особенный файл, который замечает GitHub и отображает его на заглавной странице проекта. Этот файл содержит актуальную информацию о проекте. Он включает следующую информацию: \n", + "для чего предназначен проект;\n", + "Инструкция по конфигурации и установке;\n", + "Примеры использования; \n", + "Используемую лицензию; \n", + "Правила участия в проекте; \n", + "В этот файл можно встраивать изображения и ссылки для простоты восприятия информации. \n", + "\n", + "9.1 Что такое и зачем нужен файл CONTRIBUTING (Рисунок 122)\n", + "Ответ: Этот файл содержит руководство для внешних участников.Он объясняет, как правильно предлагать изменения, оформлять PR, сообщать об ошибках, использовать стиль кода и соблюдать правила проекта. Если в проекте есть файл CONTRIBUTING, то GitHub будет показывать ссылку на него при создании любого запроса на слияние. \n", + "\n", + "Управление проектом\n", + "10 Как изменить основную ветку (Рисунок 123)\n", + "Ответ: в настройках репозитория на вкладке Options в поле “Default branch” нужно выбрать нужную ветку из ниспадающего меню. Это ветка станет основной для большинства операций, включая изменение кода при клонировании репозитория.\n", + "\n", + "10. 1 Как передать проект? какая кнопка? (рисунок 124)\n", + "Ответ: в настройках репозитория на вкладке Options нужно нажать на кнопку “Transfer Ownership”.\n", + "\n", + "10.2 Что такое файл .gitignore?\n", + "Ответ: .gitignore — это текстовый файл, содержащий список имен или шаблонов файлов и папок, которые система контроля версий Git должна игнорировать и не добавлять в репозиторий. Он используется для исключения временных файлов, логов, API-ключей и папок сборки, обеспечивая чистоту проекта. \n", + "\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/github/quiz.py b/github/quiz.py new file mode 100644 index 00000000..fe633886 --- /dev/null +++ b/github/quiz.py @@ -0,0 +1,151 @@ +# %% +"""Quiz Issue 8.""" + +# 1.1. Что такое GitHub? +# +# Ответ: GitHub - это крупнейшее хранилище Git-репозиториев, а также центр сотрудничества для миллионов разработчиков и проектов, позволяющий разработчикам со всего мира работать над одним кодом одновременно, не мешая друг другу. +# +# 1.2. Как GitHub связан с Git? +# Ответ: Git - это инструмент, локальная система контроля версий, установленная на компьютере пользователя, а GitHub - его облачное хранилище, онлайн-сервис. Git отслеживает изменения локально, а GitHub синхронизирует эти изменения через удаленные репозитории. +# +# 1.3. Чем отличается fork репозитория от его клонирования (clone)? +# Ответ: Fork - это создание копии репозитория на GitHub под своим аккаунтом для независимой разработки и внесения изменений (Pull Request). Clone - это загрузка копии репозитория (форкнутого или оригинального) с сервера на локальный компьютер для работы. Форк нужен для внесения вклада в чужие проекты или создание отдельного проекта. Clone - для работы с кодом, локального тестирования и коммитов. +# +# 1.4. Зачем нужны и как работают pull requests? +# Ответ: Pull Request (PR) — это механизм в системе контроля версий на GitHub, позволяющий разработчику уведомить коллег о завершении работы над веткой и предложить слияние изменений в основной код. PR нужны для рецензирования кода (code review), обсуждения, тестирования и контроля качества, обеспечивая защиту от ошибок. +# Pull Request работают следующим образом: разработчик создаёт новую ветку для новой фичи или багфикса, вносит изменения и коммитит их в свою ветку, затем создаёт PR, указывая, что хочет слить изменения из своей ветки в целевую. Коллеги просматривают код, оставляют комментарии, автор вносит правки. После одобрения (approval) ответственным лицом изменения вливаются в целевую ветку. +# +# 1.5. GitHub использует ваш почтовый адрес для привязки ваших Git коммитов к вашей учётной записи? +# Ответ: Да, GitHub использует ваш почтовый адрес для привязки ваших Git коммитов к вашей учётной записи. Если вы используете несколько почтовых адресов в своих коммитах и хотите, чтобы GitHub работал с ними корректно, то вам нужно будет добавить все используемые почтовые адреса в секцию под названием «Почтовые адреса» («Emails»), расположенную на вкладке «Администрирование» («Admin»). +# +# 1.6 Какая команда генерирует SSH ключ для Доступа по SSH к репозиторию (Рисунок 83) +# Ответ: Для генерации SSH-ключа (публичного и приватного) используется команда ssh-keygen. Рекомендуется использовать современный алгоритм Ed25519 для большей безопасности, выполнив в терминале (Linux/MacOS/Git Bash) команду: +# ssh-keygen -t ed25519 -C "your_email@example.com" +# +# Создайте ишьюс и запомните его номер, в https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-SENATOROV/issues, назовите его "UPDATE README", в дескрипшене добавьте список задач (Рисунок 102) +# 2.1. Если вы хотите вносить свой вклад в уже существующие проекты, в которых у нас нет прав на внесения изменений путём отправки (push) изменений, вы можете создать своё собственное ответвление, что нужно сделать чтобы создать собственное ответвление? (Рисунок 88), сделайте ответвление https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-SENATOROV, и вставьте сюда ссылку на ваше ответвление. +# Ответ: нужно создать форк репозитория. +# https://github.com/svetlana-s88/Data-Science-For-Beginners-from-scratch-SENATOROV +# +# 2.2 создайте ветку dev в ФОРКЕ Data-Science-For-Beginners, вставьте сюда ссылку на вашу ветку dev +# Ответ: +# https://github.com/svetlana-s88/Data-Science-For-Beginners-from-scratch-SENATOROV/tree/dev +# 2.3 В README файле вашего ФОРКА, добавьте ссылку на мой телеграм канал https://t.me/RuslanSenatorov, сохраните коммит, название коммита - в тайтле название ишьюса (#номер_ишьюс), в дескрипшене - Closes #NUMBER-ISSUES номер возьмите из пункта 2 +# 2.4 Отправьте пул реквест из ФОРКА в основу В ВАШУ ВЕТКУ, тайтл пул реквеста скопируйте из ISSUES-TITLE, в дескрипшине пул реквеста напишите Closes #NUMBER-ISSUES вставьте номер из пункта 2 +# 2.5 Прокомментириуйте ваш пул реквест перед слиянием, перейдите во вкладку(Рисунок 92) и напишите "ок", потом нажимайте сабмит ревью затем не выходя из этой вкладки, в файле README , добавьте туда ссылку на https://t.me/SENATOROVAI, +# => инструкция +# 2.6 Выполните Merge pull request (Рисунок 116), вставьте сюда ссылку на ваш пул реквест +# Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/pull/586 +# +# 2.7 Вставьте сюда ссылку на закрытые пул реквесты в репозитории, найти можно тут +# Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/pulls?q=is%3Apr+is%3Aclosed +# +# 2.8 Как посмотреть какие файлы были в репозитории на момент определенного коммита? вставьте сюда ссылку на любой коммит, где взять ссылку? подсказка: +# Выбираем любой коммит в ВАШЕЙ ВЕТКЕ +# Нажимаем на Browse +# Убедитесь что слева у вас написан номер коммита, потом смотрим какие файлы были в репозитории, на момент этого коммита, это очень полезно если вы накосячили, и хотите откатиться к этому коммиту. +# Поэтому крайне важно называть коммиты ПРАВИЛЬНО, и в коммите должны быть только те файлы которые соответствуют названию коммита, лишних файлов НЕ ДОЛЖНО БЫТЬ, в одном коммите отправлять НЕСКОЛЬКО файлов не надо! +# Как должна выглядеть ссылка +# Ответ: https://github.com/SENATOROVAI/Data-Science-For-Beginners-from-scratch-course/commit/157a2ecec21a8bc9b5a9ba9c8388db1c6fe2d051 +# +# 2.9 как открыть запрос слияния, указывающий на другой запрос слияния и зачем это нужно? (Рисунок 117) +# +# Ответ: При открытии запроса на слияние вверху страницы вы увидите меню для выбора целевой и исходной веток. Если нажать кнопку Edit справа, то станет доступным выбор не только исходной ветки, а ещё и форка. +# Это нужно в том случае, если вы видите толковый запрос слияния и у вас есть идея как его улучшить или вы не уверены, что это хорошая идея, или у вас просто нет прав записи в целевую ветку. В таком случае вы можете открыть запрос слияния, указывающий на данный запрос. +# +# Рабочий процесс с использованием GitHub +# 3 Напишите 8 пунктов, которые нужно сделать, чтобы внести вклад в чужой проект. +# Ответ: +# Создайте форк проекта +# Создайте тематическую ветку на основании ветки master. +# Создайте один или несколько коммитов с изменениями, улучшающими проект +# Отправьте эту ветку в ваш проект на GitHub +# Откройте запрос на слияние на GitHub +# Обсуждайте его, вносите изменения, если нужно. +# Владелец проекта принимает решение о принятии изменений проекта, либо об их отклонении. +# Получите обновлённую ветку master и отправьте её в свой форк. +# +# 3.1.1 +# Какие практики принято соблюдать при создании Pull Request чтобы закрыть автоматический issues? +# Ответ: В описании PR указать ключевые слова: "Closes #номер, Fixes #номер, Resolves #номер для автоматического закрытия Issues. +# +# 3.1.2 Какие практики принято соблюдать при создании commit чтобы закрыть автоматический issues? +# Ответ: В заголовке и сообщении коммита указать ключевые слова "Closes #номер, Fixes #номер, Resolves #номер. +# +# 3.2 Как отклонить/закрыть пул реквест? (предоставьте скриншот где это в гитхабе) +# Ответ: чтобы отклонить Pull Request, нужно нажать на него в списке, открыть его, в нижней части нажать на кнопку Revert, затем выполнить слияние PR. +# Чтобы закрыть Pull Request, нужно нажать кнопку Close Pull Request. +# +# 3.3 Перед отправкой пул реквеста нужно ли создавать ишьюс? +# Ответ: Не обязательно, но рекомендуется для обсуждения изменений и получения обратной связи перед реализацией. +# +# 3.4 В какой вкладке можно посмотреть список изменений который был в пул реквесте? (Рисунок 92) +# Ответ: во вкладке Files Changed. +# 3.5 В какой вкладке находится страница обсуждений пул реквеста? (Рисунок 94) +# Ответ: во вкладке Conversation. +# +# Создание запроса на слияние +# 4 Можно ли открыть пул реквест, если вы ничего не вносили в FORK? +# Ответ: технически открыть PR можно, но он будет пустым. Если вы хотите обсудить что-то, то лучше использовать Issues, а не PR. +# +# 4.1 Что нужно сделать чтобы открыть пул реквест? (Рисунок 90) +# Ответ: после того, как мы создали тематическую ветку, внесли изменения, зафиксировали изменения в тематическую ветку, и отправили ветку на GitHub, мы увидим, что GitHub предлагает нам открыть PR с помощью зеленой кнопки Compare & Pull request. +# +# 4.2 Что нужно сделать Если ваш Форк устарел? +# Ответ: Синхронизировать форк с оригинальным репозиторием через кнопку "Sync fork" или вручную через git: добавить upstream, выполнить fetch и merge. +# +# 4.3 Что нужно сделать если в пул реквесте имеются конфликты слияния (Рисунок 96) +# Ответ: Разрешить конфликты вручную: нажать Resolve conflicts, отредактировать файлы с конфликтами, пометить конфликты как разрешенные, закоммитить изменения. +# Отрывки кода +# 5 Что нужно сделать Для добавления отрывка кода в комментарии к ишьюсу? (Рисунок 104) +# Ответ: Для добавления отрывка кода в комментарии к ишьюсу код следует обрамить обратными кавычками. Если указать название языка, то GitHub попробует применить к нему подсветку синтаксиса. +# +# 5.1 На какую клавишу нажать клавишу чтобы выделенный текст был включён как цитата в ваш комментарий?(Рисунок 105) +# Ответ: если в комментарии выделить текст, на который вы собираетесь ответить, и нажать клавишу r, то выделенный текст будет включён как цитата в ваш комментарий. +# +# 5.2 Как вставить картинку в ишьюс? (Рисунок 108) +# Ответ: перетищить изображение в поле комментария или исподьзовать ссылку в формате Markdown: ![описание](ссылка_на_изображение). +# +# Поддержание GitHub репозитория в актуальном состоянии +# 6 Как понять что ваш форк устарел? +# Ответ:Форк устарел, если в оригинальном репозитории (upstream) появились новые коммиты, ветки или релизы, которых нет в вашей копии. В GitHub это видно по сообщению «This branch is X commits behind...», а в консоли — по разнице при git fetch upstream. +# +# 6.1 Как обновить форк? +# Ответ: нажать на кнопку "Sync fork" на странице форка, затем "Update branch", или вручную через git: git fetch upstream, git merge upstream/main, git push. +# +# +# Добавление участников +# 7 Как добавить участников в ваш репозиторий, чтобы команда могла работать над одним репозиторием? (Рисунок 112) +# Ответ: нужно зайти в Settings, выбрать “Collaborators” в меню слева. Напишете имя пользователя в поле для ввода и нажмите “Add collaborator”. +# +# Упоминания и уведомления +# 8 Какой символ нужен для упоминания кого-либо? (Рисунок 118) +# Ответ: символ @. +# +# 8.1 Где находится Центр уведомлений, напишите ссылку (Рисунок 121) +# Ответ: https://github.com/notifications +# +# Особенные файлы +# 9 Что такое и зачем нужен файл README +# Ответ: это особенный файл, который замечает GitHub и отображает его на заглавной странице проекта. Этот файл содержит актуальную информацию о проекте. Он включает следующую информацию: +# для чего предназначен проект; +# Инструкция по конфигурации и установке; +# Примеры использования; +# Используемую лицензию; +# Правила участия в проекте; +# В этот файл можно встраивать изображения и ссылки для простоты восприятия информации. +# +# 9.1 Что такое и зачем нужен файл CONTRIBUTING (Рисунок 122) +# Ответ: Этот файл содержит руководство для внешних участников.Он объясняет, как правильно предлагать изменения, оформлять PR, сообщать об ошибках, использовать стиль кода и соблюдать правила проекта. Если в проекте есть файл CONTRIBUTING, то GitHub будет показывать ссылку на него при создании любого запроса на слияние. +# +# Управление проектом +# 10 Как изменить основную ветку (Рисунок 123) +# Ответ: в настройках репозитория на вкладке Options в поле “Default branch” нужно выбрать нужную ветку из ниспадающего меню. Это ветка станет основной для большинства операций, включая изменение кода при клонировании репозитория. +# +# 10. 1 Как передать проект? какая кнопка? (рисунок 124) +# Ответ: в настройках репозитория на вкладке Options нужно нажать на кнопку “Transfer Ownership”. +# +# 10.2 Что такое файл .gitignore? +# Ответ: .gitignore — это текстовый файл, содержащий список имен или шаблонов файлов и папок, которые система контроля версий Git должна игнорировать и не добавлять в репозиторий. Он используется для исключения временных файлов, логов, API-ключей и папок сборки, обеспечивая чистоту проекта. +# +# From d3859162e8f508aacaa93c96a52d383e56eed92d Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Sun, 5 Apr 2026 17:11:04 +0500 Subject: [PATCH 11/24] task1 --- python/makarov/chapter_1_variables.ipynb | 341 +++++++++++++++++++++++ python/makarov/chapter_1_variables.py | 89 ++++++ 2 files changed, 430 insertions(+) create mode 100644 python/makarov/chapter_1_variables.ipynb create mode 100644 python/makarov/chapter_1_variables.py diff --git a/python/makarov/chapter_1_variables.ipynb b/python/makarov/chapter_1_variables.ipynb new file mode 100644 index 00000000..f2e5455c --- /dev/null +++ b/python/makarov/chapter_1_variables.ipynb @@ -0,0 +1,341 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b8179996", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Глава 1. Переменные.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "2c16f7bf", + "metadata": {}, + "source": [ + "Создание (объявление) переменных" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "44ba8f73", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15\n" + ] + } + ], + "source": [ + "# можно создать переменную, присвоив ей числовое значение\n", + "number_1: int = 15\n", + "print(number_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b1cf1112", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Я люблю писать код\n" + ] + } + ], + "source": [ + "# переменной можно создать строковое(текстовое) значение\n", + "string_1: str = \"Я люблю писать код\"\n", + "print(string_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "813e0a01", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python PHP Java\n" + ] + } + ], + "source": [ + "# в Питоне можно присвоить разные значения сразу нескольким переменным\n", + "a_3: str\n", + "b_3: str\n", + "c_3: str\n", + "a_3, b_3, c_3 = \"Python\", \"PHP\", \"Java\"\n", + "print(a_3, b_3, c_3)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6b817706", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "То же самое значение То же самое значение То же самое значение\n" + ] + } + ], + "source": [ + "# а также присвоить одно и то же значение нескольким переменным\n", + "x_4: str\n", + "y_4: str\n", + "z_4: str\n", + "x_4 = y_4 = z_4 = \"То же самое значение\"\n", + "print(x_4, y_4, z_4)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cf75eca7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "сметана молоко кефир\n" + ] + } + ], + "source": [ + "# каждый аргумент функции можно “распаковать” в переменные\n", + "my_list = [\"сметана\", \"молоко\", \"кефир\"]\n", + "a_5: str\n", + "b_5: str\n", + "c_5: str\n", + "a_5, b_5, c_5 = my_list\n", + "print(a_5, b_5, c_5)" + ] + }, + { + "cell_type": "markdown", + "id": "73dc751b", + "metadata": {}, + "source": [ + "Автоматическое определение типа данных" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f009e9e5", + "metadata": {}, + "outputs": [], + "source": [ + "x_6: int\n", + "x_6 = 15 # в этом случае переменной присваивается тип данных int\n", + "y_6: float\n", + "y_6 = 0.25 # присваивается тип float)\\\n", + "z_6: str\n", + "z_6 = \"Просто текст\" # присваивается тип str" + ] + }, + { + "cell_type": "markdown", + "id": "97cb3ccb", + "metadata": {}, + "source": [ + "Как узнать тип переменной в Python:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c904be6d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "# узнаем тип переменных\n", + "print(type(x_6), type(y_6), type(z_6))" + ] + }, + { + "cell_type": "markdown", + "id": "829aacb5", + "metadata": {}, + "source": [ + "Присвоение и преобразование типа данных:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c42fcc66", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "x_7 = str(25) # число 25 превратится в строку\n", + "y_7 = int(25) # число 25 останется целочисленным значением\n", + "z_7 = float(25) # число 25 превратится в десятичную дробь\n", + "print(type(x_7), type(y_7), type(z_7))" + ] + }, + { + "cell_type": "markdown", + "id": "3f036422", + "metadata": {}, + "source": [ + "Изменение типа данных " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c5307919", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# преобразуем строку, похожую на целое число, в настоящее целое число\n", + "print(type(int(\"25\")))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "11a81415", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# или строку, похожую на дробь, в настоящую десятичную дробь\n", + "print(type(float(\"2.5\")))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "83604fc5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "36\n", + "\n" + ] + } + ], + "source": [ + "# преобразуем дробь в целочисленное значение\n", + "# обратите внимание, что округления в большую сторону не происходит\n", + "print(int(36.6))\n", + "print(type(int(36.6)))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "2bcb54cd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n" + ] + } + ], + "source": [ + "# и конечно, и целое число, и дробь можно превратить в строку\n", + "print(type(str(25)))\n", + "print(type(str(35.7)))" + ] + }, + { + "cell_type": "markdown", + "id": "0daf052b", + "metadata": {}, + "source": [ + "Допустимые имена переменных \n", + "\n", + "variable=’просто переменная’\n", + "_variable=’просто переменная’\n", + "variable_=’просто переменная’\n", + "my_variable =’просто переменная’\n", + "My_variable_123=’просто переменная’\n", + "\n", + "Недопустимые названия переменных \n", + "\n", + "my-variable = ‘так делать нельзя’\n", + "123variable =’так делать нельзя’\n", + "my variable =’так делать нельзя’\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_1_variables.py b/python/makarov/chapter_1_variables.py new file mode 100644 index 00000000..7a01e52a --- /dev/null +++ b/python/makarov/chapter_1_variables.py @@ -0,0 +1,89 @@ +"""Глава 1. + +Переменные. +""" + +# Создание (объявление) переменных + +# можно создать переменную, присвоив ей числовое значение +number_1: int = 15 +print(number_1) + +# переменной можно создать строковое(текстовое) значение +string_1: str = "Я люблю писать код" +print(string_1) + +# в Питоне можно присвоить разные значения сразу нескольким переменным +a_3: str +b_3: str +c_3: str +a_3, b_3, c_3 = "Python", "PHP", "Java" +print(a_3, b_3, c_3) + +# а также присвоить одно и то же значение нескольким переменным +x_4: str +y_4: str +z_4: str +x_4 = y_4 = z_4 = "То же самое значение" +print(x_4, y_4, z_4) + +# каждый аргумент функции можно “распаковать” в переменные +my_list = ["сметана", "молоко", "кефир"] +a_5: str +b_5: str +c_5: str +a_5, b_5, c_5 = my_list +print(a_5, b_5, c_5) + +# Автоматическое определение типа данных + +x_6: int +x_6 = 15 # в этом случае переменной присваивается тип данных int +y_6: float +y_6 = 0.25 # присваивается тип float)\ +z_6: str +z_6 = "Просто текст" # присваивается тип str + +# Как узнать тип переменной в Python: + +# узнаем тип переменных +print(type(x_6), type(y_6), type(z_6)) + +# Присвоение и преобразование типа данных: + +x_7 = str(25) # число 25 превратится в строку +y_7 = int(25) # число 25 останется целочисленным значением +z_7 = float(25) # число 25 превратится в десятичную дробь +print(type(x_7), type(y_7), type(z_7)) + +# Изменение типа данных + +# преобразуем строку, похожую на целое число, в настоящее целое число +print(type(int("25"))) + +# или строку, похожую на дробь, в настоящую десятичную дробь +print(type(float("2.5"))) + +# преобразуем дробь в целочисленное значение +# обратите внимание, что округления в большую сторону не происходит +print(int(36.6)) +print(type(int(36.6))) + +# и конечно, и целое число, и дробь можно превратить в строку +print(type(str(25))) +print(type(str(35.7))) + +# Допустимые имена переменных +# +# variable=’просто переменная’ +# _variable=’просто переменная’ +# variable_=’просто переменная’ +# my_variable =’просто переменная’ +# My_variable_123=’просто переменная’ +# +# Недопустимые названия переменных +# +# my-variable = ‘так делать нельзя’ +# 123variable =’так делать нельзя’ +# my variable =’так делать нельзя’ +# From ae1121f83065b23f946dcbe713ac20d727c638de Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Sun, 5 Apr 2026 17:24:26 +0500 Subject: [PATCH 12/24] task1_clean code --- .../clean_code/chapter_4_correct_names.ipynb | 99 +++++++++++++++++++ python/clean_code/chapter_4_correct_names.py | 49 +++++++++ 2 files changed, 148 insertions(+) create mode 100644 python/clean_code/chapter_4_correct_names.ipynb create mode 100644 python/clean_code/chapter_4_correct_names.py diff --git a/python/clean_code/chapter_4_correct_names.ipynb b/python/clean_code/chapter_4_correct_names.ipynb new file mode 100644 index 00000000..36340f5a --- /dev/null +++ b/python/clean_code/chapter_4_correct_names.ipynb @@ -0,0 +1,99 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "dde5fd14", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Чистый код для продолжающих.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Чистый код для продолжающих.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "f7e5c31c", + "metadata": {}, + "source": [ + "Выбор компактных, содержательных имён - важный шаг в подготовке к написанию кода.\n", + "\n", + "Схемы регистра имен: \n", + "Змеиный регистр (snake_case): бывает нижний и верхний. Для констант: UPPER_SNAKE_CASE;\n", + "Верблюжий регистр (camelCase);\n", + "Pascal (PascalCase).\n", + "Змеиный и верблюжий регистры встречаются чаще всего. В одном проекте можно использовать только одну схему.\n", + "\n", + "Соглашение об именах PEP 8: \n", + "все буквы должны входить в ASCII;\n", + "имена модулей - короткие, только из букв нижнего регистра; \n", + "имена классов в схеме Pascal;\n", + "имена констант - верхний змеиный регистр;\n", + "имена функций, методов и переменных - нижний змеиный регистр; \n", + "первый аргумент методов всегда должен называться self в нижнем регистре; \n", + "первый аргумент классов всегда должен называться cls в нижнем регистре;\n", + "приватные атрибуты классов всегда начинаются с символа (_), а публичные, наоборот, не начинаются с (_).\n", + "При необходимости эти правила могут быть нарушены, например, могут быть использованы символы не только латинского алфавита, но и других языков.\n", + "\n", + "Длина имён\n", + "Длина имён не должна быть слишком короткой, или слишком длинной. \n", + "Исключение: i, j для циклов; х, у для декартовых координат. \n", + "Но в случае, когда область видимости переменной большая, содержательность переменной в приоритете над её длиной.\n", + "Например, в коде на 10000 строк вместо “payment” лучше использовать \n", + "salesClientMonthPayment или annual_electric_bill_payment. \n", + "\n", + "Префиксы в именах бывают избыточны: например, strName, iVacationDays - венгерская запись, считается устаревшей.\n", + "Префиксы is и has у переменных, содержащих логические значения, делают эти имена более понятными.\n", + "Включение единиц измерения даёт полезную информацию: weight_kg означает, что вес задаётся в килограммах. \n", + "\n", + "Последовательные числовые суффиксы в именах стоит использовать только тогда, когда в этом действительно есть необходимость. \n", + "Например, вместо переменных payment1, payment2, payment3 лучше использовать список, или преобразовать в кортеж с именем payments, в которой хранятся эти переменные. \n", + "\n", + "Для того, чтобы имена были пригодны для поиска, нужно создавать уникальные имена, содержащие конкретную информацию. Например, вместо email выбирайте конкретное и более содержательное имя: emailAddress, downloadEmailAttachment, emailMessage и т.д.\n", + "\n", + "Избегайте шуток, каламбуров и культурных отсылок. \n", + "\n", + "Никогда не используйте встроенные имена Python для своих переменных. К ним относятся all, any, date, email, file, format, hash, id, input, list, min, max, object, open, random, set, str, sum, test, type. \n", + "\n", + "Чтобы узнать, используется ли имя в Python, нужно ввести его в интерактивной оболочке или попробовать импортировать. \n", + "\n", + "Также нельзя допускать присвоение файлам .py имён, совпадающих с именами сторонних модулей. \n", + "Пример: Pyperclip - сторонний модуль. Файл нельзя называть pyperclip.py, так как тогда при вызове функции copy() или paste() произойдёт ошибка. \n", + "\n", + "Избегайте бессодержательных имён, таких как data, var, temp. \n", + "Таким образом, хотя выбор имён не имеет никакого отношения к компьютерным алгоритмам, это остаётся важным фактором удобочитаемости кода. \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/clean_code/chapter_4_correct_names.py b/python/clean_code/chapter_4_correct_names.py new file mode 100644 index 00000000..a189ae69 --- /dev/null +++ b/python/clean_code/chapter_4_correct_names.py @@ -0,0 +1,49 @@ +"""Чистый код для продолжающих.""" + +# Выбор компактных, содержательных имён - важный шаг в подготовке к написанию кода. +# +# Схемы регистра имен: +# Змеиный регистр (snake_case): бывает нижний и верхний. Для констант: UPPER_SNAKE_CASE; +# Верблюжий регистр (camelCase); +# Pascal (PascalCase). +# Змеиный и верблюжий регистры встречаются чаще всего. В одном проекте можно использовать только одну схему. +# +# Соглашение об именах PEP 8: +# все буквы должны входить в ASCII; +# имена модулей - короткие, только из букв нижнего регистра; +# имена классов в схеме Pascal; +# имена констант - верхний змеиный регистр; +# имена функций, методов и переменных - нижний змеиный регистр; +# первый аргумент методов всегда должен называться self в нижнем регистре; +# первый аргумент классов всегда должен называться cls в нижнем регистре; +# приватные атрибуты классов всегда начинаются с символа (_), а публичные, наоборот, не начинаются с (_). +# При необходимости эти правила могут быть нарушены, например, могут быть использованы символы не только латинского алфавита, но и других языков. +# +# Длина имён +# Длина имён не должна быть слишком короткой, или слишком длинной. +# Исключение: i, j для циклов; х, у для декартовых координат. +# Но в случае, когда область видимости переменной большая, содержательность переменной в приоритете над её длиной. +# Например, в коде на 10000 строк вместо “payment” лучше использовать +# salesClientMonthPayment или annual_electric_bill_payment. +# +# Префиксы в именах бывают избыточны: например, strName, iVacationDays - венгерская запись, считается устаревшей. +# Префиксы is и has у переменных, содержащих логические значения, делают эти имена более понятными. +# Включение единиц измерения даёт полезную информацию: weight_kg означает, что вес задаётся в килограммах. +# +# Последовательные числовые суффиксы в именах стоит использовать только тогда, когда в этом действительно есть необходимость. +# Например, вместо переменных payment1, payment2, payment3 лучше использовать список, или преобразовать в кортеж с именем payments, в которой хранятся эти переменные. +# +# Для того, чтобы имена были пригодны для поиска, нужно создавать уникальные имена, содержащие конкретную информацию. Например, вместо email выбирайте конкретное и более содержательное имя: emailAddress, downloadEmailAttachment, emailMessage и т.д. +# +# Избегайте шуток, каламбуров и культурных отсылок. +# +# Никогда не используйте встроенные имена Python для своих переменных. К ним относятся all, any, date, email, file, format, hash, id, input, list, min, max, object, open, random, set, str, sum, test, type. +# +# Чтобы узнать, используется ли имя в Python, нужно ввести его в интерактивной оболочке или попробовать импортировать. +# +# Также нельзя допускать присвоение файлам .py имён, совпадающих с именами сторонних модулей. +# Пример: Pyperclip - сторонний модуль. Файл нельзя называть pyperclip.py, так как тогда при вызове функции copy() или paste() произойдёт ошибка. +# +# Избегайте бессодержательных имён, таких как data, var, temp. +# Таким образом, хотя выбор имён не имеет никакого отношения к компьютерным алгоритмам, это остаётся важным фактором удобочитаемости кода. +# From a4f17a3494336ec98d8375db223931248ff0d531 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Sun, 5 Apr 2026 20:16:08 +0500 Subject: [PATCH 13/24] task 1 loops --- python/makarov/chapter_3_if_loops.ipynb | 1065 +++++++++++++++++++++++ python/makarov/chapter_3_if_loops.py | 373 ++++++++ 2 files changed, 1438 insertions(+) create mode 100644 python/makarov/chapter_3_if_loops.ipynb create mode 100644 python/makarov/chapter_3_if_loops.py diff --git a/python/makarov/chapter_3_if_loops.ipynb b/python/makarov/chapter_3_if_loops.ipynb new file mode 100644 index 00000000..378e3c4a --- /dev/null +++ b/python/makarov/chapter_3_if_loops.ipynb @@ -0,0 +1,1065 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a432ff79", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Циклы.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "8937e6ef", + "metadata": {}, + "source": [ + "Условия и Циклы. Продолжение \n", + "\n", + "Ещё раз про условия с if\n" + ] + }, + { + "cell_type": "markdown", + "id": "ec91444b", + "metadata": {}, + "source": [ + "Множественные условия (multi-way decisions)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7e2b06aa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "# напишем программу, которая разобьёт все числа на малые, средние и большие\n", + "# импортируем библиотеку numpy\n", + "# импортируем библиотеку numpy\n", + "from typing import Iterable, Union\n", + "\n", + "import numpy as np\n", + "\n", + "x_1: int = 24 # зададим число\n", + "\n", + "# и пропишем условия (не забывайте про двоеточие и отступ)\n", + "if x_1 < 10:\n", + " print(\"Small\")\n", + "elif x_1 < 100:\n", + " print(\"Medium\")\n", + "else:\n", + "\n", + " print(\"Large\")" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b632cfb6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "# запросим число у пользователя\n", + "x_2: str = input(\"Введите число: \")\n", + "\n", + "# преобразуем в тип int\n", + "x_3: int = int(x_2)\n", + "\n", + "# и наконец классифицируем\n", + "if x_3 < 10:\n", + " print(\"Small\")\n", + "elif x_3 < 100:\n", + " print(\"Medium\")\n", + "else:\n", + " print(\"Large\")" + ] + }, + { + "cell_type": "markdown", + "id": "03223d82", + "metadata": {}, + "source": [ + "Вложенные условия (nested decisions)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "04d92bc5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Small\n" + ] + } + ], + "source": [ + "# запрашивает число\n", + "x_4: str = input(\"Введите число: \")\n", + "# проверяем первое условие (не пустая ли строка), если оно выполняется\n", + "if len(x_4) != 0:\n", + " # преобразуем в тип int\n", + " x_5: int = int(x_4)\n", + "\n", + " # и классифицируем\n", + " if x_5 < 10:\n", + " print(\"Small\")\n", + " elif x_5 < 100:\n", + " print(\"Medium\")\n", + " else:\n", + " print(\"Large\")\n", + "\n", + "# в противном, говорим, что ввод пустой\n", + "else:\n", + " print(\"Ввод пустой\")" + ] + }, + { + "cell_type": "markdown", + "id": "ab481778", + "metadata": {}, + "source": [ + "Несколько условий в одном выражении с операторами and или or" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89dbcfe4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Small or Large\n" + ] + } + ], + "source": [ + "# пример с and (логическим И)\n", + "z_5: int = 4\n", + "\n", + "# если z больше 10 и одновременно меньше 100\n", + "if 10 < z_5 < 100:\n", + " # у нас среднее число\n", + " print(\"Medium\")\n", + "# в противном случае оно либо маленькое, либо большое\n", + "else:\n", + " print(\"Small or Large\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a16614f7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "# пример с or (логическим ИЛИ)\n", + "z_6: int = 45\n", + "\n", + "# Если z меньше 10 или больше 100\n", + "if z_6 < 10 or z_6 > 100:\n", + "\n", + " # оно либо маленькое, либо большое\n", + " print(\"Small or Large\")\n", + "# в противном случае оно среднее\n", + "else:\n", + " print(\"Medium\")" + ] + }, + { + "cell_type": "markdown", + "id": "9462a983", + "metadata": {}, + "source": [ + "Проверка вхождения элемента в объект с in / not in" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6224d5b4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Слово найдено\n" + ] + } + ], + "source": [ + "# можно проверить вхождение слова в строку\n", + "sentence: str = \"to be, or not to be, this is a question\"\n", + "word: str = \"question\"\n", + "\n", + "if word in sentence:\n", + " print(\"Слово найдено\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "59bb18ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Такого числа в списке нет\n" + ] + } + ], + "source": [ + "# или отсутствие элемента в списке\n", + "number_list: list[int] = [2, 4, 6, 7, 8]\n", + "number: int = 10\n", + "\n", + "if number not in number_list:\n", + " print(\"Такого числа в списке нет\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2711cc87", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Нашлись\n" + ] + } + ], + "source": [ + "# кроме того, можно проверить вхождения ключа и значения в словарь\n", + "# возьмём очень простой словарь\n", + "d_5: dict[str, int] = {\"apple\": 1, \"carrot\": 5, \"potato\": 9}\n", + "\n", + "# вначале поищем яблоки среди ключей словаря\n", + "if \"apple\" in d_5:\n", + " print(\"Нашлись\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c75535c7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Есть\n" + ] + } + ], + "source": [ + "# а потом посмотрим, нет ли числа 5 среди ключей словаря\n", + "# с помощью метода .values()\n", + "if 5 in d_5.values():\n", + " print(\"Есть\")" + ] + }, + { + "cell_type": "markdown", + "id": "c729bdd4", + "metadata": {}, + "source": [ + "Циклы в Питоне\n", + "Основные операции " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9afb9b3c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n" + ] + } + ], + "source": [ + "# поочерёдно выведем элементы списка\n", + "number_list_6: list[int] = [1, 2, 3, 4, 5, 6, 7]\n", + "\n", + "# не забывая про двоеточие и отступ\n", + "for number in number_list_6:\n", + " print(number)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "cb6fb865", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим словарь, значениями которого будут списки из двух элементов\n", + "d_7: dict[str, list[Union[int, str]]] = {\n", + " \"apple\": [5, \"kg\"],\n", + " \"tomato\": [6, \"pcs\"],\n", + " \"carrot\": [12, \"kg\"],\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "3487f65d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "apple [5, 'kg']\n", + "tomato [6, 'pcs']\n", + "carrot [12, 'kg']\n" + ] + } + ], + "source": [ + "# затем создадим две переменные-контейнера и применим метод .items()\n", + "for key_1, value_1 in d_7.items():\n", + " print(key_1, value_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "54ea3fe3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "6\n", + "12\n" + ] + } + ], + "source": [ + "# возьмем только одну переменную и применим метод .values()\n", + "for value_2 in d_7.values():\n", + " # значение представляет собой список, выведем его первый элемент с индексом [0]\n", + " print(value_2[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b095e3a4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "# создадим массив и поместим в переменную number_array\n", + "number_array: Iterable[int] = np.array([1, 2, 3])\n", + "\n", + "# пройдемся по нему с помощью цикла for\n", + "for number in number_array:\n", + " print(number)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "b597130f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "6\n", + "9\n", + "12\n", + "15\n", + "18\n" + ] + } + ], + "source": [ + "# создадим массив и поместим в переменную number_array_\n", + "number_array_: Iterable[int] = np.array([1, 2, 3, 4, 5, 6])\n", + "for number_ in number_array_:\n", + " print(number_ * 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "9f4d4ee2", + "metadata": {}, + "outputs": [], + "source": [ + "# предположим, что у нас есть следующая база данных клиентов\n", + "clients_5: dict[int, dict[str, Union[str, int]]] = {\n", + " 1: {\"name\": \"Анна\", \"age\": 24, \"sex\": \"male\", \"revenue\": 12000},\n", + " 2: {\"name\": \"Илья\", \"age\": 18, \"sex\": \"female\", \"revenue\": 8000},\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "24f1efec", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "client ID: \n", + "name: Анна\n", + "age: 24\n", + "sex: male\n", + "revenue: 12000\n", + "\n", + "client ID: \n", + "name: Илья\n", + "age: 18\n", + "sex: female\n", + "revenue: 8000\n", + "\n" + ] + } + ], + "source": [ + "# в первом цикле for поместим id и информацию о клиентах в переменные id и info\n", + "for client_id, info in clients_5.items():\n", + "\n", + " # выведем id клиента\n", + " print(\"client ID: \" + str(id))\n", + "\n", + " # во втором цикле возьмем информацию об этом клиенте (это тоже словарь)\n", + " for key_s, value_s in info.items():\n", + "\n", + " # и выведем каждый ключ (название поля) и значение (саму информацию)\n", + " print(key_s + \": \" + str(value_s))\n", + "\n", + " # добавим пустую строку после того, как выведем информацию об одном клиенте\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b2c689bf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n", + "5\n" + ] + } + ], + "source": [ + "# создадим последовательность от 0 до 5\n", + "for i in range(6):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "930b9619", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "2\n", + "4\n", + "6\n" + ] + } + ], + "source": [ + "# и от нуля до 7 с шагом 2\n", + "for i in range(0, 8, 2):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "5000e4d1", + "metadata": {}, + "source": [ + "Последовательность в обратном порядке" + ] + }, + { + "cell_type": "markdown", + "id": "c31de4da", + "metadata": {}, + "source": [ + "Способ 1. Функция reversed()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e4bf2005", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# создадим список my_list\n", + "my_list: list[int] = [0, 1, 2, 3, 4]\n", + "\n", + "# передадим его функции reversed() b\n", + "# выведем каждый из элементов списка с помощью цикла for\n", + "for i in reversed(my_list):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "8f1d2d8a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "for i in reversed(range(5)):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "e01f788e", + "metadata": {}, + "source": [ + "Способ 2. Указать -1 в качестве параметра шага." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "68f3c1e3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n" + ] + } + ], + "source": [ + "# первым параметром укажем конечный элемент списка,\n", + "# а вторым - начальный\n", + "for i in range(4, 0, -1):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "38f39743", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# чтобы вывести 0, вторым параметром нужно указать -1\n", + "for i in range(4, -1, -1):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "04e186eb", + "metadata": {}, + "source": [ + "Способ 3. Функция sorted()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "38a1467f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# создадим последовательность от 0 до 4\n", + "r_1: range = range(5)\n", + "\n", + "# отсортируем ее по убыванию\n", + "sorted_values = sorted(r_1, reverse=True)\n", + "\n", + "# выведем элементы отсортированной последовательности\n", + "for i in sorted_values:\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "7497034b", + "metadata": {}, + "source": [ + "Функция enumerate()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "4e37d892", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 Понедельник\n", + "1 Вторник\n", + "2 Среда\n", + "3 Четверг\n", + "4 Пятница\n", + "5 Суббота\n", + "6 Воскресенье\n" + ] + } + ], + "source": [ + "# пусть дан список с днями недели\n", + "days_11: list[str] = [\n", + " \"Понедельник\",\n", + " \"Вторник\",\n", + " \"Среда\",\n", + " \"Четверг\",\n", + " \"Пятница\",\n", + " \"Суббота\",\n", + " \"Воскресенье\",\n", + "]\n", + "\n", + "# выведем индекс (i) и сами элементы списка (day)\n", + "for i, day in enumerate(days_11):\n", + " print(i, day)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "c8e01d3c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Понедельник\n", + "2 Вторник\n", + "3 Среда\n", + "4 Четверг\n", + "5 Пятница\n", + "6 Суббота\n", + "7 Воскресенье\n" + ] + } + ], + "source": [ + "# так же выведем индекс и элементы списка, но начнем с 1\n", + "for i, day in enumerate(days_11, 1):\n", + " print(i, day)" + ] + }, + { + "cell_type": "markdown", + "id": "d1db15cf", + "metadata": {}, + "source": [ + "Цикл while" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "eaab0979", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Текущее значение счетчика: 0\n", + "Новое значение счетчика: 1\n", + "\n", + "Текущее значение счетчика: 1\n", + "Новое значение счетчика: 2\n", + "\n", + "Текущее значение счетчика: 2\n", + "Новое значение счетчика: 3\n", + "\n" + ] + } + ], + "source": [ + "# зададим начальное значение счетчика\n", + "i_12: int = 0\n", + "\n", + "# пока счетчик меньше трех\n", + "while i_12 < 3:\n", + "\n", + " # в каждом цикле будем выводить его текущее значение\n", + " print(\"Текущее значение счетчика: \" + str(i_12))\n", + "\n", + " # внутри цикла не забудем \"нарастить\" счетчик\n", + " i_12 = i_12 + 1\n", + "\n", + " # и выведем новое значение\n", + " print(\"Новое значение счетчика: \" + str(i_12))\n", + "\n", + " # добавим пустую строку\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "f09ebafe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n" + ] + } + ], + "source": [ + "# тот же код можно упростить\n", + "i_13: int = 0\n", + "\n", + "while i_13 < 3:\n", + " print(i_13)\n", + " # в частности, оператор += сразу увеличивает и присваивает новое значение\n", + " i_13 += 1" + ] + }, + { + "cell_type": "markdown", + "id": "cc9e0a10", + "metadata": {}, + "source": [ + "Break, continue" + ] + }, + { + "cell_type": "markdown", + "id": "e35b4317", + "metadata": {}, + "source": [ + "Оператор break" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ba278647", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 {'name': 'Анна', 'age': 24, 'sex': 'male', 'revenue': 12000}\n" + ] + } + ], + "source": [ + "# вновь возьмем словарь clients\n", + "clients_14: dict[int, dict[str, Union[str, int]]] = {\n", + " 1: {\"name\": \"Анна\", \"age\": 24, \"sex\": \"male\", \"revenue\": 12000},\n", + " 2: {\"name\": \"Илья\", \"age\": 18, \"sex\": \"female\", \"revenue\": 8000},\n", + "}\n", + "\n", + "# в цикле пройдемся по ключам и значениям словаря\n", + "for client_id, info in clients_14.items():\n", + "\n", + " # и выведем их\n", + " print(client_id, info)\n", + "\n", + " # однако уже после первого исполнения цикла, прервем его\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "478ab5eb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n", + "5\n", + "4\n" + ] + } + ], + "source": [ + "# начальное значение счетчика\n", + "x_15: int = 6\n", + "\n", + "# будем исполнять цикл пока x не равен нулю\n", + "while x_15 != 0:\n", + "\n", + " # выведем текущее значение счетчика\n", + " print(x_15)\n", + "\n", + " # и уменьшим (!) его на 1\n", + " x_15 -= 1\n", + "\n", + " # если значение счетчика станет равным 3, прервем цикл\n", + " if x_15 == 3:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "5553b162", + "metadata": {}, + "source": [ + "Оператор continue" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "35b48f9d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "4\n", + "6\n", + "8\n", + "10\n" + ] + } + ], + "source": [ + "# выведем все четные числа в диапазоне от 1 до 10 включительно.\n", + "\n", + "# с помощью функции range() создадим последовательность от 1 до 10\n", + "for i in range(1, 11):\n", + "\n", + " # если остаток от деления на два не равен нулю (то есть число нечетное)\n", + " if i % 2 != 0:\n", + "\n", + " # идем к следующему числу последовательности\n", + " continue\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "43410a78", + "metadata": {}, + "source": [ + "Форматирование строк через f-строки и метод .format()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "b4ea37e0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Понедельник'" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# снова возьмем список с днями недели\n", + "days_16: list[str] = [\n", + " \"Понедельник\",\n", + " \"Вторник\",\n", + " \"Среда\",\n", + " \"Четверг\",\n", + " \"Пятница\",\n", + " \"Суббота\",\n", + " \"Воскресенье\",\n", + "]\n", + "\n", + "# и для простоты поместим слово \"Понедельник\" в переменную Monday\n", + "Monday = days_16[0]\n", + "Monday" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "03feebfb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Понедельник - день тяжелый\n" + ] + } + ], + "source": [ + "# теперь напишем фразу \"Понедельник - день тяжелый\" следующим образом\n", + "print(f\"{Monday} - день тяжелый\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_3_if_loops.py b/python/makarov/chapter_3_if_loops.py new file mode 100644 index 00000000..fdc23588 --- /dev/null +++ b/python/makarov/chapter_3_if_loops.py @@ -0,0 +1,373 @@ +# %% +"""Циклы.""" + +# Условия и Циклы. Продолжение +# +# Ещё раз про условия с if +# + +# Множественные условия (multi-way decisions) + +from collections.abc import Iterable + +# %% +# напишем программу, которая разобьёт все числа на малые, средние и большие +# импортируем библиотеку numpy +# импортируем библиотеку numpy +from typing import Union + +import numpy as np + +x_1: int = 24 # зададим число + +# и пропишем условия (не забывайте про двоеточие и отступ) +if x_1 < 10: + print("Small") +elif x_1 < 100: + print("Medium") +else: + + print("Large") + +# %% +# запросим число у пользователя +x_2: str = input("Введите число: ") + +# преобразуем в тип int +x_3: int = int(x_2) + +# и наконец классифицируем +if x_3 < 10: + print("Small") +elif x_3 < 100: + print("Medium") +else: + print("Large") + +# Вложенные условия (nested decisions) + +# %% +# запрашивает число +x_4: str = input("Введите число: ") +# проверяем первое условие (не пустая ли строка), если оно выполняется +if len(x_4) != 0: + # преобразуем в тип int + x_5: int = int(x_4) + + # и классифицируем + if x_5 < 10: + print("Small") + elif x_5 < 100: + print("Medium") + else: + print("Large") + +# в противном, говорим, что ввод пустой +else: + print("Ввод пустой") + +# Несколько условий в одном выражении с операторами and или or + +# %% +# пример с and (логическим И) +z_5: int = 4 + +# если z больше 10 и одновременно меньше 100 +if 10 < z_5 < 100: + # у нас среднее число + print("Medium") +# в противном случае оно либо маленькое, либо большое +else: + print("Small or Large") + +# %% +# пример с or (логическим ИЛИ) +z_6: int = 45 + +# Если z меньше 10 или больше 100 +if z_6 < 10 or z_6 > 100: + + # оно либо маленькое, либо большое + print("Small or Large") +# в противном случае оно среднее +else: + print("Medium") + +# Проверка вхождения элемента в объект с in / not in + +# %% +# можно проверить вхождение слова в строку +sentence: str = "to be, or not to be, this is a question" +word: str = "question" + +if word in sentence: + print("Слово найдено") + +# %% +# или отсутствие элемента в списке +number_list: list[int] = [2, 4, 6, 7, 8] +number: int = 10 + +if number not in number_list: + print("Такого числа в списке нет") + +# %% +# кроме того, можно проверить вхождения ключа и значения в словарь +# возьмём очень простой словарь +d_5: dict[str, int] = {"apple": 1, "carrot": 5, "potato": 9} + +# вначале поищем яблоки среди ключей словаря +if "apple" in d_5: + print("Нашлись") + +# %% +# а потом посмотрим, нет ли числа 5 среди ключей словаря +# с помощью метода .values() +if 5 in d_5.values(): + print("Есть") + +# Циклы в Питоне +# Основные операции + +# %% +# поочерёдно выведем элементы списка +number_list_6: list[int] = [1, 2, 3, 4, 5, 6, 7] + +# не забывая про двоеточие и отступ +for number in number_list_6: + print(number) + +# %% +# создадим словарь, значениями которого будут списки из двух элементов +d_7: dict[str, list[Union[int, str]]] = { + "apple": [5, "kg"], + "tomato": [6, "pcs"], + "carrot": [12, "kg"], +} + +# %% +# затем создадим две переменные-контейнера и применим метод .items() +for key_1, value_1 in d_7.items(): + print(key_1, value_1) + +# %% +# возьмем только одну переменную и применим метод .values() +for value_2 in d_7.values(): + # значение представляет собой список, выведем его первый элемент с индексом [0] + print(value_2[0]) + +# %% +# создадим массив и поместим в переменную number_array +number_array: Iterable[int] = np.array([1, 2, 3]) + +# пройдемся по нему с помощью цикла for +for number in number_array: + print(number) + +# %% +# создадим массив и поместим в переменную number_array_ +number_array_: Iterable[int] = np.array([1, 2, 3, 4, 5, 6]) +for number_ in number_array_: + print(number_ * 3) + +# %% +# предположим, что у нас есть следующая база данных клиентов +clients_5: dict[int, dict[str, Union[str, int]]] = { + 1: {"name": "Анна", "age": 24, "sex": "male", "revenue": 12000}, + 2: {"name": "Илья", "age": 18, "sex": "female", "revenue": 8000}, +} + +# %% +# в первом цикле for поместим id и информацию о клиентах в переменные id и info +for client_id, info in clients_5.items(): + + # выведем id клиента + print("client ID: " + str(id)) + + # во втором цикле возьмем информацию об этом клиенте (это тоже словарь) + for key_s, value_s in info.items(): + + # и выведем каждый ключ (название поля) и значение (саму информацию) + print(key_s + ": " + str(value_s)) + + # добавим пустую строку после того, как выведем информацию об одном клиенте + print() + +# %% +# создадим последовательность от 0 до 5 +for i in range(6): + print(i) + +# %% +# и от нуля до 7 с шагом 2 +for i in range(0, 8, 2): + print(i) + +# Последовательность в обратном порядке + +# Способ 1. Функция reversed() + +# %% +# создадим список my_list +my_list: list[int] = [0, 1, 2, 3, 4] + +# передадим его функции reversed() b +# выведем каждый из элементов списка с помощью цикла for +for i in reversed(my_list): + print(i) + +# %% +for i in reversed(range(5)): + print(i) + +# Способ 2. Указать -1 в качестве параметра шага. + +# %% +# первым параметром укажем конечный элемент списка, +# а вторым - начальный +for i in range(4, 0, -1): + print(i) + +# %% +# чтобы вывести 0, вторым параметром нужно указать -1 +for i in range(4, -1, -1): + print(i) + +# Способ 3. Функция sorted() + +# %% +# создадим последовательность от 0 до 4 +r_1: range = range(5) + +# отсортируем ее по убыванию +sorted_values = sorted(r_1, reverse=True) + +# выведем элементы отсортированной последовательности +for i in sorted_values: + print(i) + +# Функция enumerate() + +# %% +# пусть дан список с днями недели +days_11: list[str] = [ + "Понедельник", + "Вторник", + "Среда", + "Четверг", + "Пятница", + "Суббота", + "Воскресенье", +] + +# выведем индекс (i) и сами элементы списка (day) +for i, day in enumerate(days_11): + print(i, day) + +# %% +# так же выведем индекс и элементы списка, но начнем с 1 +for i, day in enumerate(days_11, 1): + print(i, day) + +# Цикл while + +# %% +# зададим начальное значение счетчика +i_12: int = 0 + +# пока счетчик меньше трех +while i_12 < 3: + + # в каждом цикле будем выводить его текущее значение + print("Текущее значение счетчика: " + str(i_12)) + + # внутри цикла не забудем "нарастить" счетчик + i_12 = i_12 + 1 + + # и выведем новое значение + print("Новое значение счетчика: " + str(i_12)) + + # добавим пустую строку + print() + +# %% +# тот же код можно упростить +i_13: int = 0 + +while i_13 < 3: + print(i_13) + # в частности, оператор += сразу увеличивает и присваивает новое значение + i_13 += 1 + +# Break, continue + +# Оператор break + +# %% +# вновь возьмем словарь clients +clients_14: dict[int, dict[str, Union[str, int]]] = { + 1: {"name": "Анна", "age": 24, "sex": "male", "revenue": 12000}, + 2: {"name": "Илья", "age": 18, "sex": "female", "revenue": 8000}, +} + +# в цикле пройдемся по ключам и значениям словаря +for client_id, info in clients_14.items(): + + # и выведем их + print(client_id, info) + + # однако уже после первого исполнения цикла, прервем его + break + +# %% +# начальное значение счетчика +x_15: int = 6 + +# будем исполнять цикл пока x не равен нулю +while x_15 != 0: + + # выведем текущее значение счетчика + print(x_15) + + # и уменьшим (!) его на 1 + x_15 -= 1 + + # если значение счетчика станет равным 3, прервем цикл + if x_15 == 3: + break + +# Оператор continue + +# выведем все четные числа в диапазоне от 1 до 10 включительно. + +# с помощью функции range() создадим последовательность от 1 до 10 +for i in range(1, 11): + + # если остаток от деления на два не равен нулю (то есть число нечетное) + if i % 2 != 0: + + # идем к следующему числу последовательности + continue + print(i) + +# Форматирование строк через f-строки и метод .format() + +# %% +# снова возьмем список с днями недели +days_16: list[str] = [ + "Понедельник", + "Вторник", + "Среда", + "Четверг", + "Пятница", + "Суббота", + "Воскресенье", +] + +# и для простоты поместим слово "Понедельник" в переменную Monday +Monday = days_16[0] +Monday + +# %% +# теперь напишем фразу "Понедельник - день тяжелый" следующим образом +print(f"{Monday} - день тяжелый") From 64874d00f88ce8307607a9f736ef0c31fccbd1ab Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 6 Apr 2026 20:31:48 +0500 Subject: [PATCH 14/24] task 1 data_types --- .pre-commit-config.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6341a1aa..19844131 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -158,8 +158,6 @@ repos: - --disallow-any-generics - --local-partial-types - --pretty - - --force-uppercase-builtins - - --force-union-syntax - --warn-unreachable - --warn-redundant-casts - --warn-return-any @@ -188,8 +186,6 @@ repos: - --disallow-any-generics - --local-partial-types - --pretty - - --force-uppercase-builtins - - --force-union-syntax - --warn-unreachable - --warn-redundant-casts - --warn-return-any From 2c78e2e1b73d64044fe97d58bb74dd8996299fad Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 6 Apr 2026 20:33:18 +0500 Subject: [PATCH 15/24] task 1 data_types_python --- python/makarov/chapter_2_data_types.ipynb | 543 ++++++++++++++++++++++ python/makarov/chapter_2_data_types.py | 155 ++++++ 2 files changed, 698 insertions(+) create mode 100644 python/makarov/chapter_2_data_types.ipynb create mode 100644 python/makarov/chapter_2_data_types.py diff --git a/python/makarov/chapter_2_data_types.ipynb b/python/makarov/chapter_2_data_types.ipynb new file mode 100644 index 00000000..412d6e71 --- /dev/null +++ b/python/makarov/chapter_2_data_types.ipynb @@ -0,0 +1,543 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a8c82ccd", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Типы данных.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "618eb2f5", + "metadata": {}, + "source": [ + "Работа с числами " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "15007028", + "metadata": {}, + "outputs": [], + "source": [ + "a_1: int = 25 # целое число (int)\n", + "b_1: float = 34.5 # число с плавающей точкой (float)\n", + "c_1: complex = 25 + 3j # комплексное число (complex)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "38b99002", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2000.0\n", + "\n" + ] + } + ], + "source": [ + "# экспоненциальная часть, 2 умножить на 10 в степени 3\n", + "d_2: float = 2e3\n", + "print(d_2)\n", + "print(type(d_2))" + ] + }, + { + "cell_type": "markdown", + "id": "5486c546", + "metadata": {}, + "source": [ + "Арифметические операции" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7c56c9b8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4 2 4 2.0 8\n" + ] + } + ], + "source": [ + "# сложение, вычитание, умножение, деление,\n", + "# возведение в степень\n", + "print(2 + 2, 4 - 2, 2 * 2, 4 / 2, 2**3)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "39c1b832", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "1\n" + ] + } + ], + "source": [ + "# новая для нас операция: разделим 7 на 2 и найдём целую часть и остаток\n", + "# целая часть\n", + "print(7 // 2)\n", + "# остаток от деления\n", + "print(7 % 2)" + ] + }, + { + "cell_type": "markdown", + "id": "a55112f3", + "metadata": {}, + "source": [ + "Операторы сравнения" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "862e62bc", + "metadata": {}, + "outputs": [], + "source": [ + "# больше, меньше, больше или равно, меньше или равно\n", + "# print(4 > 2, 2 > 4, 4 >= 2, 2 <= 4)\n", + "\n", + "# равенство\n", + "# print(2 == 4)\n", + "\n", + "# и новый для нас оператор неравенства\n", + "# print(2 != 4)" + ] + }, + { + "cell_type": "markdown", + "id": "090caf22", + "metadata": {}, + "source": [ + "Логические операции" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d1fbd9d8", + "metadata": {}, + "outputs": [], + "source": [ + "# логическое И, обе операции должны быть истинны\n", + "# print(4 > 2 and 2 != 3)\n", + "# логическое ИЛИ, хотя бы одна из операций должна быть истинна\n", + "# print(4 < 2 or 2 == 2)\n", + "# логическое НЕ, перевод истинного значения в ложное и наоборот\n", + "# print(4 != 4)" + ] + }, + { + "cell_type": "markdown", + "id": "5413c516", + "metadata": {}, + "source": [ + "Перевод чисел в другую систему счисления" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d4dc90a2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0b11001\n", + "25\n" + ] + } + ], + "source": [ + "# создадим число в десятичной системе\n", + "d_new: int = 25\n", + "# переведём в двоичную (binary)\n", + "bin_d: str = bin(d_new)\n", + "print(bin_d)\n", + "# переведём обратно в десятичную\n", + "print(int(bin_d, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e520b982", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0o125\n", + "85\n" + ] + } + ], + "source": [ + "# создадим число в десятичной системе\n", + "d_3: int = 85\n", + "# переведём в восьмеричную (octal)\n", + "oct_d: str = oct(d_3)\n", + "print(oct_d)\n", + "# переведём обратно в десятичную\n", + "print(int(oct_d, 8))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "575c79d7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x7c\n", + "124\n" + ] + } + ], + "source": [ + "# создадим число в десятичной системе\n", + "d_4: int = 124\n", + "# переведём в шестнадцатеричную\n", + "hex_d = hex(d_4)\n", + "print(hex_d)\n", + "# переведём обратно в десятичную\n", + "print(int(hex_d, 16))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "cd757738", + "metadata": {}, + "outputs": [], + "source": [ + "# строковые данные\n", + "string_1: str = \"это строка\"\n", + "string_2: str = \"это тоже строка\"\n", + "\n", + "multi_string: str = \"\"\"Мы все учились понемногу \n", + "Чему-нибудь и как-нибудь\n", + "Так воспитаньем, Слава Богу\n", + "У нас немудрено блеснуть.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "88cc8e9b", + "metadata": {}, + "source": [ + "Длина строки" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e3dcc208", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "105" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# воспользуемся функцией len()\n", + "len(multi_string)" + ] + }, + { + "cell_type": "markdown", + "id": "045ba3ae", + "metadata": {}, + "source": [ + "Объединение строк" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb7eaf52", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Программирование на Питоне'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# создадим три строки\n", + "a_5: str\n", + "b_5: str\n", + "c_5: str\n", + "a_5, b_5, c_5 = \"Программирование\", \"на\", \"Питоне\"\n", + "# соединим с помощью + и добавим пробелы ‘ ‘\n", + "# а_5 + \" \" + b_5 + \" \" + c_5" + ] + }, + { + "cell_type": "markdown", + "id": "f23b907d", + "metadata": {}, + "source": [ + "Индекс символа в строке" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "bcc583b8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "М\n", + ".\n" + ] + } + ], + "source": [ + "# выведем первый элемент строки multi_string\n", + "print(multi_string[0])\n", + "# теперь выведем последний элемент\n", + "print(multi_string[-1])" + ] + }, + { + "cell_type": "markdown", + "id": "ec80c583", + "metadata": {}, + "source": [ + "Срезы строк" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "60d49f41", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "все\n", + "Мы\n", + "все учились понемногу \n", + "Чему-нибудь и как-нибудь\n", + "Так воспитаньем, Слава Богу\n", + "У нас немудрено блеснуть.\n" + ] + } + ], + "source": [ + "# выберем элементы с четвертого по шестой\n", + "print(multi_string[3:6])\n", + "\n", + "# выберем все элементы вплоть до второго\n", + "print(multi_string[:2])\n", + "# а также все элементы, начиная с четвертого\n", + "print(multi_string[3:])" + ] + }, + { + "cell_type": "markdown", + "id": "7ff6f344", + "metadata": {}, + "source": [ + "Циклы в строках" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b8f96db5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "П\n", + "и\n", + "т\n", + "о\n", + "н\n" + ] + } + ], + "source": [ + "# выведем буквы в слове Питон\n", + "for char in \"Питон\":\n", + " print(char)" + ] + }, + { + "cell_type": "markdown", + "id": "da88c149", + "metadata": {}, + "source": [ + "Методы .strip() и .split()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "af4f8676", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 849 302\n", + "15 849 302\n", + "['Мы', 'все', 'учились', 'понемногу', 'Чему-нибудь', 'и', 'как-нибудь', 'Так', 'воспитаньем,', 'Слава', 'Богу', 'У', 'нас', 'немудрено', 'блеснуть.']\n" + ] + }, + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# применим метод .strip(), чтобы удалить *\n", + "print(\"***15 849 302*****\".strip(\"*\"))\n", + "# если ничего не указать в качестве аргумента, то удаляются пробелы по краям строки\n", + "print(\" 15 849 302 \".strip())\n", + "\n", + "# применим метод .split(), чтобы разделить строку на части\n", + "print(multi_string.split())\n", + "\n", + "# посчитаем количество слов в тексте (длину списка)\n", + "len(multi_string.split())" + ] + }, + { + "cell_type": "markdown", + "id": "2684ae88", + "metadata": {}, + "source": [ + "Логические значения " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9677d47", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "bool" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# создадим переменную и запишем в неё логическое значение True\n", + "# обязательно с большой буквы\n", + "var_1: bool = False\n", + "type(var_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c5e0816a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Значение переменной ложно\n" + ] + } + ], + "source": [ + "# напишем небольшую программу, которая будет показывать\n", + "# какое значение содержится в переменной var\n", + "var_2: bool = False\n", + "if var_2:\n", + " print(\"Значение переменной истинно\")\n", + "else:\n", + " print(\"Значение переменной ложно\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_2_data_types.py b/python/makarov/chapter_2_data_types.py new file mode 100644 index 00000000..4c9347dd --- /dev/null +++ b/python/makarov/chapter_2_data_types.py @@ -0,0 +1,155 @@ +"""Типы данных.""" + +# Работа с числами + +a_1: int = 25 # целое число (int) +b_1: float = 34.5 # число с плавающей точкой (float) +c_1: complex = 25 + 3j # комплексное число (complex) + +# экспоненциальная часть, 2 умножить на 10 в степени 3 +d_2: float = 2e3 +print(d_2) +print(type(d_2)) + +# Арифметические операции + +# сложение, вычитание, умножение, деление, +# возведение в степень +print(2 + 2, 4 - 2, 2 * 2, 4 / 2, 2**3) + +# новая для нас операция: разделим 7 на 2 и найдём целую часть и остаток +# целая часть +print(7 // 2) +# остаток от деления +print(7 % 2) + +# Операторы сравнения + +# + +# больше, меньше, больше или равно, меньше или равно +# print(4 > 2, 2 > 4, 4 >= 2, 2 <= 4) + +# равенство +# print(2 == 4) + +# и новый для нас оператор неравенства +# print(2 != 4) +# - + +# Логические операции + +# + +# логическое И, обе операции должны быть истинны +# print(4 > 2 and 2 != 3) +# логическое ИЛИ, хотя бы одна из операций должна быть истинна +# print(4 < 2 or 2 == 2) +# логическое НЕ, перевод истинного значения в ложное и наоборот +# print(4 != 4) +# - + +# Перевод чисел в другую систему счисления + +# создадим число в десятичной системе +d_new: int = 25 +# переведём в двоичную (binary) +bin_d: str = bin(d_new) +print(bin_d) +# переведём обратно в десятичную +print(int(bin_d, 2)) + +# создадим число в десятичной системе +d_3: int = 85 +# переведём в восьмеричную (octal) +oct_d: str = oct(d_3) +print(oct_d) +# переведём обратно в десятичную +print(int(oct_d, 8)) + +# создадим число в десятичной системе +d_4: int = 124 +# переведём в шестнадцатеричную +hex_d = hex(d_4) +print(hex_d) +# переведём обратно в десятичную +print(int(hex_d, 16)) + +# + +# строковые данные +string_1: str = "это строка" +string_2: str = "это тоже строка" + +multi_string: str = """Мы все учились понемногу +Чему-нибудь и как-нибудь +Так воспитаньем, Слава Богу +У нас немудрено блеснуть.""" +# - + +# Длина строки + +# воспользуемся функцией len() +len(multi_string) + +# Объединение строк + +# создадим три строки +a_5: str +b_5: str +c_5: str +a_5, b_5, c_5 = "Программирование", "на", "Питоне" +# соединим с помощью + и добавим пробелы ‘ ‘ +# а_5 + " " + b_5 + " " + c_5 + +# Индекс символа в строке + +# выведем первый элемент строки multi_string +print(multi_string[0]) +# теперь выведем последний элемент +print(multi_string[-1]) + +# Срезы строк + +# + +# выберем элементы с четвертого по шестой +print(multi_string[3:6]) + +# выберем все элементы вплоть до второго +print(multi_string[:2]) +# а также все элементы, начиная с четвертого +print(multi_string[3:]) +# - + +# Циклы в строках + +# выведем буквы в слове Питон +for char in "Питон": + print(char) + +# Методы .strip() и .split() + +# + +# применим метод .strip(), чтобы удалить * +print("***15 849 302*****".strip("*")) +# если ничего не указать в качестве аргумента, то удаляются пробелы по краям строки +print(" 15 849 302 ".strip()) + +# применим метод .split(), чтобы разделить строку на части +print(multi_string.split()) + +# посчитаем количество слов в тексте (длину списка) +len(multi_string.split()) +# - + +# Логические значения + +# создадим переменную и запишем в неё логическое значение True +# обязательно с большой буквы +var_1: bool = False +type(var_1) + +# напишем небольшую программу, которая будет показывать +# какое значение содержится в переменной var +var_2: bool = False +if var_2: + print("Значение переменной истинно") +else: + print("Значение переменной ложно") From b55492e7fd5398867b978e7d5e5d34b6f01b5c5b Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 6 Apr 2026 22:50:03 +0500 Subject: [PATCH 16/24] task 1 datetime --- python/makarov/chapter_5_datetime.ipynb | 894 ++++++++++++++++++++++++ python/makarov/chapter_5_datetime.py | 255 +++++++ 2 files changed, 1149 insertions(+) create mode 100644 python/makarov/chapter_5_datetime.ipynb create mode 100644 python/makarov/chapter_5_datetime.py diff --git a/python/makarov/chapter_5_datetime.ipynb b/python/makarov/chapter_5_datetime.ipynb new file mode 100644 index 00000000..1abc9ec6 --- /dev/null +++ b/python/makarov/chapter_5_datetime.ipynb @@ -0,0 +1,894 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "71a4efd7", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Дата и время в Питоне.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "9c3fd5b0", + "metadata": {}, + "source": [ + "Модуль datetime" + ] + }, + { + "cell_type": "markdown", + "id": "f5251dd1", + "metadata": {}, + "source": [ + "Импорт модуля и класса datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "9197a526", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-04-06 22:07:55.980053\n" + ] + } + ], + "source": [ + "# импортируем весь модуль\n", + "# import datetime\n", + "\n", + "# для этого вначале импортируем соответствующий класс\n", + "# часто из модуля datetime удобнее импортировать\n", + "# только класс datetime\n", + "from datetime import datetime\n", + "\n", + "# для изменения часового пояса нужно импортировать модуль pytz\n", + "import pytz\n", + "\n", + "# чтобы получить доступ к функции now(), сначала обратимся к модулю, потом к классу\n", + "print(datetime.now())" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "fdaf5014", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-03-18 18:18:30.205923\n" + ] + } + ], + "source": [ + "# и обращаться непосредственно к нему\n", + "print(datetime.now())" + ] + }, + { + "cell_type": "markdown", + "id": "811e6101", + "metadata": {}, + "source": [ + "Объект datetime и функция now()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "dd119989", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-04-06 22:08:43.943164\n" + ] + } + ], + "source": [ + "# поместим созданный с помощью функции now() объект datetime в переменную cur_dt\n", + "cur_dt: datetime = datetime.now()\n", + "print(cur_dt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13eea0c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026 4 6 22 8 43 943164\n" + ] + } + ], + "source": [ + "# с помощью соответствующих атрибутов выведем каждый из\n", + "# компонентов объекта по отдельности\n", + "print(\n", + " cur_dt.year,\n", + " cur_dt.month,\n", + " cur_dt.day,\n", + " cur_dt.hour,\n", + " cur_dt.minute,\n", + " cur_dt.second,\n", + " cur_dt.microsecond,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1d7f3ff3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 3\n" + ] + } + ], + "source": [ + "# также можно посмотреть на день недели\n", + "# метод .weekday() начинает индекс недели с нуля, .isoweekday() - с единицы\n", + "print(cur_dt.weekday(), cur_dt.isoweekday())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8a9d9d40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "# посмотрим на часовой пояс с помощью атрибута tzinfo\n", + "print(cur_dt.tzinfo)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5a14d333", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-04-06 20:09:54.839637+03:00\n" + ] + } + ], + "source": [ + "# выведем текущее время в Москве\n", + "dt_moscow = datetime.now(pytz.timezone(\"Europe/Moscow\"))\n", + "print(dt_moscow)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "26fdc533", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Europe/Moscow\n" + ] + } + ], + "source": [ + "# снова посмотрим на атрибут часового пояса\n", + "print(dt_moscow.tzinfo)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "eff3010e", + "metadata": {}, + "outputs": [], + "source": [ + "# получим timestamp текущего времени с помощью метода .timestamp()\n", + "timestamp = datetime.now().timestamp()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "4144468a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1773840340.828707\n" + ] + } + ], + "source": [ + "# выведем количество секунд, прошедшее с 01.01.1970 до исполнения кода\n", + "print(timestamp)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8e9c14bc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-03-18 18:25:40.828707\n" + ] + } + ], + "source": [ + "# вернем timestamp в прежний формат с помощью метода .fromtimestamp()\n", + "print(datetime.fromtimestamp(timestamp))" + ] + }, + { + "cell_type": "markdown", + "id": "63865db1", + "metadata": {}, + "source": [ + "Создание объекта datetime вручную" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b6929f3b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1988-08-12 00:00:00\n" + ] + } + ], + "source": [ + "# передадим объекту datetime 12 августа 1988 года\n", + "hb: datetime = datetime(1988, 8, 12)\n", + "print(hb)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "5bf500a8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1988\n" + ] + } + ], + "source": [ + "# и извлечем год с помощью атрибута year\n", + "print(hb.year)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "25c04217", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "587329200.0\n" + ] + } + ], + "source": [ + "# создадим timestamp\n", + "print(datetime.timestamp(hb))" + ] + }, + { + "cell_type": "markdown", + "id": "4cc15732", + "metadata": {}, + "source": [ + "Преобразование строки в объект datetime и обратно." + ] + }, + { + "cell_type": "markdown", + "id": "fb92f414", + "metadata": {}, + "source": [ + "Строка ➞ datetime через `.strptime()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "142b296e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "str" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# дана строка с датой 2 декабря 2007 года и временем 12 часов 30 минут и 45 секунд\n", + "str_to_dt: str = \"2007-12-02 12:30:45\"\n", + "type(str_to_dt)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c75b6bbe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2007-12-02 12:30:45\n", + "\n" + ] + } + ], + "source": [ + "# преобразуем ее в datetime с помощью метода .strptime()\n", + "res_dt: datetime = datetime.strptime(str_to_dt, \"%Y-%m-%d %H:%M:%S\")\n", + "\n", + "print(res_dt)\n", + "print(type(res_dt))" + ] + }, + { + "cell_type": "markdown", + "id": "a669ac7e", + "metadata": {}, + "source": [ + "Datetime ➞ строка через .strftime()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d9822abf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# вначале создадим объект datetime и передадим ему 15 февраля 1988 года\n", + "dt_to_str: datetime = datetime(1988, 2, 15)\n", + "type(dt_to_str)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "61b569c6", + "metadata": {}, + "outputs": [], + "source": [ + "# преобразуем объект в строку в формате \"день недели, месяц число, год\"\n", + "# res_str = datetime.strftime(dt_to_str, \"%A, %B %d, %Y\")\n", + "\n", + "# print(res_str)\n", + "# print(type(res_str))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "7dcfa339", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Monday, February 15, 1988'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# .strftime() можно применять непосредственно к объекту datetime\n", + "dt_to_str.strftime(\"%A, %B %d, %Y\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "c3e614ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2026-04-06'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# можно и так\n", + "datetime.now().strftime(\"%Y-%m-%d\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "8c021acd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Mon Apr 6 22:17:09 2026'" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# а еще так\n", + "datetime.now().strftime(\"%c\")" + ] + }, + { + "cell_type": "markdown", + "id": "bd0cac61", + "metadata": {}, + "source": [ + "Форматирование даты и времени через .strptime() и \n", + ".strftime()\n", + "\n", + "%а - Сокращенное название дня недели - Sun, Mon\n", + "%А - Полное название дня недели - Sunday, Monday\n", + "%w - День недели как число - 0, 1, 2...6\n", + "%d - День месяца в виде числа с нулями - 01, 02, ..., 30\n", + "%-d - День месяца в виде числа без нулей " + ] + }, + { + "cell_type": "markdown", + "id": "316609ef", + "metadata": {}, + "source": [ + "Сравнение и арифметика дат" + ] + }, + { + "cell_type": "markdown", + "id": "46c3af4e", + "metadata": {}, + "source": [ + "Сравнение дат" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "10493b7d", + "metadata": {}, + "outputs": [], + "source": [ + "# сравним две даты публикации работ Эйнштейна\n", + "date1: datetime = datetime(1905, 6, 30) # \"К электродинамике движущихся тел\"\n", + "date2: datetime = datetime(1916, 5, 11) # Общая теория относительности" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06d0bd2a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# большей считается более поздняя дата\n", + "# date1 < date2" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "734b72e9", + "metadata": {}, + "outputs": [], + "source": [ + "# обратное будет признано ложным\n", + "# date1 > date2" + ] + }, + { + "cell_type": "markdown", + "id": "44973add", + "metadata": {}, + "source": [ + "Календарный и алфавитный порядок дат" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "74b9f02e", + "metadata": {}, + "outputs": [], + "source": [ + "# если даты записаны в виде строки в формате ГГГГ.ММ.ДД,\n", + "# то мы можем их сравнивать, как если бы мы сравнивали объекты datetime\n", + "\n", + "# вначале запишем даты в виде строки и сравним их\n", + "# \"2007-12-02\" > \"2002-11-19\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "702e4f3e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# теперь в виде объекта datetime\n", + "# datetime(2007, 12, 2) > datetime(2002, 11, 19)" + ] + }, + { + "cell_type": "markdown", + "id": "d3ed28d0", + "metadata": {}, + "source": [ + "Промежуток времени и класс timedelta" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "458d46ed", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3968 days, 0:00:00\n" + ] + }, + { + "data": { + "text/plain": [ + "datetime.timedelta" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# если из большей даты вычесть меньшую, то мы получим временной промежуток между датами\n", + "diff = date2 - date1\n", + "print(diff)\n", + "type(diff)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "83881bf7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3968\n" + ] + } + ], + "source": [ + "# атрибут days позволяет посмотреть только дни\n", + "print(diff.days)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "3502b213", + "metadata": {}, + "outputs": [], + "source": [ + "# объект timedelta можно также создать вручную\n", + "\n", + "\n", + "# а затем создадим объект timedelta продолжительностью 1 день\n", + "# timedelta(days=1)" + ] + }, + { + "cell_type": "markdown", + "id": "82b7f0f1", + "metadata": {}, + "source": [ + "Арифметика дат" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0f383c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime(2070, 1, 1, 0, 0)" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# смотрите, что получается,\n", + "# объединив объекты datetime и timedelta, мы можем \"путешествовать во времени\"\n", + "\n", + "# допустим сейчас 1 января 2070 года\n", + "future: datetime = datetime(2070, 1, 1)\n", + "future" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "566300f4", + "metadata": {}, + "outputs": [], + "source": [ + "# а мы хотим отправиться в 1 января 1900 года, т.е. на 170 лет назад\n", + "\n", + "# сначала просто умножим 365 дней на 170\n", + "# time_travel = timedelta(days=365) * 170\n", + "\n", + "# а потом переместимся из будущего в прошлое\n", + "# past = future - time_travel\n", + "\n", + "# к сожалению, мы немного \"не долетим\", потому что не учли високосные годы, в которых 366 дней\n", + "# past" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "e8142bcf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "62050" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# мы пролетели 62050 дней\n", + "365 * 170" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "f90b2b7a", + "metadata": {}, + "outputs": [], + "source": [ + "# но мы уже умеем вычислять точное количество дней (с учетом високосных годов)\n", + "# datetime(2070, 1, 1) - datetime(1900, 1, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "9a99422b", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь снова совершим путешествие во времени, но на этот раз укажем правильное количество дней\n", + "# time_travel = timedelta(days=62092)\n", + "\n", + "# past = future - time_travel\n", + "# past" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "05095da4", + "metadata": {}, + "outputs": [], + "source": [ + "# иногда бывает удобно воспользоваться циклом while, чтобы создать перечень дат\n", + "# например, список праздничных новогодних дней в 2021 году\n", + "\n", + "# cur_date = datetime(2026, 1, 1) # эту дату мы будем выводить\n", + "# end_date = datetime(2026, 1, 10) # это граница (условие в цикле while)\n", + "\n", + "# пока верно условие\n", + "# while cur_date <= end_date:\n", + "\n", + "# выведем cur_date в формате \"месяц число, год\"\n", + "# print(cur_date.strftime(\"%b %d, %Y\"))\n", + "\n", + "# прибавим к выводимой дате один день\n", + "# cur_date += timedelta(days=1)" + ] + }, + { + "cell_type": "markdown", + "id": "282b6c38", + "metadata": {}, + "source": [ + "Дата и обработка ошибок" + ] + }, + { + "cell_type": "markdown", + "id": "0d3153d8", + "metadata": {}, + "source": [ + "Конструкция try/except и оператор pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6c591e2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# пусть дан список чисел в строковом формате, и мы хотим посчитать их сумму\n", + "# предположим, буква \"а\" попала в список случайно\n", + "# numbers = [\"5\", \"10\", \"a\", \"15\", \"10\"]\n", + "\n", + "# объявим переменную суммы\n", + "# total: int = 0\n", + "\n", + "# пройдемся по числам\n", + "# for number in numbers:\n", + "\n", + "# попробуем прибавить число к переменной total\n", + "# try:\n", + "# total += int(number)\n", + "\n", + "# если же этого сделать не удастся\n", + "# except:\n", + "# перейдем к следующему числу\n", + "# pass\n", + "\n", + "# выведем сумму\n", + "# total" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_5_datetime.py b/python/makarov/chapter_5_datetime.py new file mode 100644 index 00000000..3e3ab151 --- /dev/null +++ b/python/makarov/chapter_5_datetime.py @@ -0,0 +1,255 @@ +"""Дата и время в Питоне.""" + +# Модуль datetime + +# Импорт модуля и класса datetime + +# + +# импортируем весь модуль +# import datetime + +# для этого вначале импортируем соответствующий класс +# часто из модуля datetime удобнее импортировать +# только класс datetime +from datetime import datetime + +# для изменения часового пояса нужно импортировать модуль pytz +import pytz + +# чтобы получить доступ к функции now(), сначала обратимся к модулю, потом к классу +print(datetime.now()) +# - + +# и обращаться непосредственно к нему +print(datetime.now()) + +# Объект datetime и функция now() + +# поместим созданный с помощью функции now() объект datetime в переменную cur_dt +cur_dt: datetime = datetime.now() +print(cur_dt) + +# с помощью соответствующих атрибутов выведем каждый из +# компонентов объекта по отдельности +print( + cur_dt.year, + cur_dt.month, + cur_dt.day, + cur_dt.hour, + cur_dt.minute, + cur_dt.second, + cur_dt.microsecond, +) + +# также можно посмотреть на день недели +# метод .weekday() начинает индекс недели с нуля, .isoweekday() - с единицы +print(cur_dt.weekday(), cur_dt.isoweekday()) + +# посмотрим на часовой пояс с помощью атрибута tzinfo +print(cur_dt.tzinfo) + +# выведем текущее время в Москве +dt_moscow = datetime.now(pytz.timezone("Europe/Moscow")) +print(dt_moscow) + +# снова посмотрим на атрибут часового пояса +print(dt_moscow.tzinfo) + +# получим timestamp текущего времени с помощью метода .timestamp() +timestamp = datetime.now().timestamp() + +# выведем количество секунд, прошедшее с 01.01.1970 до исполнения кода +print(timestamp) + +# вернем timestamp в прежний формат с помощью метода .fromtimestamp() +print(datetime.fromtimestamp(timestamp)) + +# Создание объекта datetime вручную + +# передадим объекту datetime 12 августа 1988 года +hb: datetime = datetime(1988, 8, 12) +print(hb) + +# и извлечем год с помощью атрибута year +print(hb.year) + +# создадим timestamp +print(datetime.timestamp(hb)) + +# Преобразование строки в объект datetime и обратно. + +# Строка ➞ datetime через `.strptime() + +# дана строка с датой 2 декабря 2007 года и временем 12 часов 30 минут и 45 секунд +str_to_dt: str = "2007-12-02 12:30:45" +type(str_to_dt) + +# + +# преобразуем ее в datetime с помощью метода .strptime() +res_dt: datetime = datetime.strptime(str_to_dt, "%Y-%m-%d %H:%M:%S") + +print(res_dt) +print(type(res_dt)) +# - + +# Datetime ➞ строка через .strftime() + +# вначале создадим объект datetime и передадим ему 15 февраля 1988 года +dt_to_str: datetime = datetime(1988, 2, 15) +type(dt_to_str) + +# + +# преобразуем объект в строку в формате "день недели, месяц число, год" +# res_str = datetime.strftime(dt_to_str, "%A, %B %d, %Y") + +# print(res_str) +# print(type(res_str)) +# - + +# .strftime() можно применять непосредственно к объекту datetime +dt_to_str.strftime("%A, %B %d, %Y") + +# можно и так +datetime.now().strftime("%Y-%m-%d") + +# а еще так +datetime.now().strftime("%c") + +# Форматирование даты и времени через .strptime() и +# .strftime() +# +# %а - Сокращенное название дня недели - Sun, Mon +# %А - Полное название дня недели - Sunday, Monday +# # %w - День недели как число - 0, 1, 2...6 +# # %d - День месяца в виде числа с нулями - 01, 02, ..., 30 +# %-d - День месяца в виде числа без нулей + +# Сравнение и арифметика дат + +# Сравнение дат + +# сравним две даты публикации работ Эйнштейна +date1: datetime = datetime(1905, 6, 30) # "К электродинамике движущихся тел" +date2: datetime = datetime(1916, 5, 11) # Общая теория относительности + +# + +# большей считается более поздняя дата +# date1 < date2 + +# + +# обратное будет признано ложным +# date1 > date2 +# - + +# Календарный и алфавитный порядок дат + +# + +# если даты записаны в виде строки в формате ГГГГ.ММ.ДД, +# то мы можем их сравнивать, как если бы мы сравнивали объекты datetime + +# вначале запишем даты в виде строки и сравним их +# "2007-12-02" > "2002-11-19" + +# + +# теперь в виде объекта datetime +# datetime(2007, 12, 2) > datetime(2002, 11, 19) +# - + +# Промежуток времени и класс timedelta + +# если из большей даты вычесть меньшую, то мы получим временной промежуток между датами +diff = date2 - date1 +print(diff) +type(diff) + +# атрибут days позволяет посмотреть только дни +print(diff.days) + +# + +# объект timedelta можно также создать вручную + + +# а затем создадим объект timedelta продолжительностью 1 день +# timedelta(days=1) +# - + +# Арифметика дат + +# + +# смотрите, что получается, +# объединив объекты datetime и timedelta, мы можем "путешествовать во времени" + +# допустим сейчас 1 января 2070 года +future: datetime = datetime(2070, 1, 1) +future + +# + +# а мы хотим отправиться в 1 января 1900 года, т.е. на 170 лет назад + +# сначала просто умножим 365 дней на 170 +# time_travel = timedelta(days=365) * 170 + +# а потом переместимся из будущего в прошлое +# past = future - time_travel + +# к сожалению, мы немного "не долетим", потому что не учли високосные годы, в которых 366 дней +# past +# - + +# мы пролетели 62050 дней +365 * 170 + +# + +# но мы уже умеем вычислять точное количество дней (с учетом високосных годов) +# datetime(2070, 1, 1) - datetime(1900, 1, 1) + +# + +# теперь снова совершим путешествие во времени, но на этот раз укажем правильное количество дней +# time_travel = timedelta(days=62092) + +# past = future - time_travel +# past + +# + +# иногда бывает удобно воспользоваться циклом while, чтобы создать перечень дат +# например, список праздничных новогодних дней в 2021 году + +# cur_date = datetime(2026, 1, 1) # эту дату мы будем выводить +# end_date = datetime(2026, 1, 10) # это граница (условие в цикле while) + +# пока верно условие +# while cur_date <= end_date: + +# выведем cur_date в формате "месяц число, год" +# print(cur_date.strftime("%b %d, %Y")) + +# прибавим к выводимой дате один день +# cur_date += timedelta(days=1) +# - + +# Дата и обработка ошибок + +# Конструкция try/except и оператор pass + +# + +# пусть дан список чисел в строковом формате, и мы хотим посчитать их сумму +# предположим, буква "а" попала в список случайно +# numbers = ["5", "10", "a", "15", "10"] + +# объявим переменную суммы +# total: int = 0 + +# пройдемся по числам +# for number in numbers: + +# попробуем прибавить число к переменной total +# try: +# total += int(number) + +# если же этого сделать не удастся +# except: +# перейдем к следующему числу +# pass + +# выведем сумму +# total From d6eb20a0c82627ea8e18779b4ca3f16a835d46f4 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Wed, 8 Apr 2026 21:17:50 +0500 Subject: [PATCH 17/24] task 1 files --- python/makarov/chapter_4_files.ipynb | 347 +++++++++++++++++++++++++++ python/makarov/chapter_4_files.py | 154 ++++++++++++ 2 files changed, 501 insertions(+) create mode 100644 python/makarov/chapter_4_files.ipynb create mode 100644 python/makarov/chapter_4_files.py diff --git a/python/makarov/chapter_4_files.ipynb b/python/makarov/chapter_4_files.ipynb new file mode 100644 index 00000000..f06a75b6 --- /dev/null +++ b/python/makarov/chapter_4_files.ipynb @@ -0,0 +1,347 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cb987014", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Работа с файлами в Google Colab.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c00fb389", + "metadata": {}, + "outputs": [], + "source": [ + "# импортируем модуль os\n", + "# import os\n", + "\n", + "# импортируем библиотеку\n", + "# import pandas as pd\n", + "\n", + "# из библиотеки google.colab импортируем класс files\n", + "# from google.colab import files" + ] + }, + { + "cell_type": "markdown", + "id": "4bdee963", + "metadata": {}, + "source": [ + "Этап 1. Подгрузка файлов." + ] + }, + { + "cell_type": "markdown", + "id": "8ed18b4c", + "metadata": {}, + "source": [ + "Способ 1. Вручную через вкладку \"Файлы\".\n", + "Нажимаем на иконку загрузки файлов на левой боковой панели и в открывшемся окне выбираем те файлы, которые хотели загрузить. " + ] + }, + { + "cell_type": "markdown", + "id": "2490eef9", + "metadata": {}, + "source": [ + "Способ 2. Через модуль files библиотеки google.colab." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4aa13f71", + "metadata": {}, + "outputs": [], + "source": [ + "# создаем объект этого класса, применяем метод .upload()\n", + "# uploaded = files.upload()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0c1d944", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на содержимое словаря uploaded\n", + "# uploaded" + ] + }, + { + "cell_type": "markdown", + "id": "b9592eb5", + "metadata": {}, + "source": [ + "Этап 2. Чтение файлов.\n", + "\n", + "Просмотр содержимого папки /content/\n", + "\n", + "Модуль os и метод .walk()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e87baf78", + "metadata": {}, + "outputs": [], + "source": [ + "# выводим пути к папкам (dirpath) и наименования файлов (filenames) и после этого\n", + "# for dirpath, _, filenames in os.walk(\"/content/\"):\n", + "\n", + "# во вложенном цикле проходимся по названиям файлов\n", + "# for filename in filenames:\n", + "\n", + "# и соединяем путь до папок и входящие в эти папки файлы\n", + "# с помощью метода path.join()\n", + "# print(os.path.join(dirpath, filename))" + ] + }, + { + "cell_type": "markdown", + "id": "57b3ecd1", + "metadata": {}, + "source": [ + "Команда !ls" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "bed51482", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на содержимое папки content\n", + "# !ls" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9804c3c3", + "metadata": {}, + "outputs": [], + "source": [ + "# заглянем внутрь sample_data\n", + "# !ls /content/sample_data/" + ] + }, + { + "cell_type": "markdown", + "id": "7c48451e", + "metadata": {}, + "source": [ + "Чтение из переменной uploaded" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "3d8be7b8", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на тип значений словаря uploaded\n", + "# type(uploaded[\"test.csv\"])" + ] + }, + { + "cell_type": "markdown", + "id": "666579f6", + "metadata": {}, + "source": [ + "Пример работы с объектом bytes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "321b13c5", + "metadata": {}, + "outputs": [], + "source": [ + "# обратимся к ключу словаря uploaded и применим метод .decode()\n", + "# uploaded_str = uploaded[\"test.csv\"].decode()\n", + "\n", + "# на выходе получаем обычную строку\n", + "# print(type(uploaded_str))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1478e84", + "metadata": {}, + "outputs": [], + "source": [ + "# выведем первые 35 значений\n", + "# print(uploaded_str[:35])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f971efe", + "metadata": {}, + "outputs": [], + "source": [ + "# если разбить строку методом .split() по символам \\r (возврат к началу строки) и \\n (новая строка)\n", + "# uploaded_list = uploaded_str.split(\"\\r\\n\")\n", + "\n", + "# на выходе мы получим список\n", + "# type(uploaded_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6caa04d6", + "metadata": {}, + "outputs": [], + "source": [ + "# пройдемся по этому списку, не забыв создать индекс с помощью функции enumerate()\n", + "# for i, line in enumerate(uploaded_list):\n", + "\n", + "# начнем выводить записи\n", + "# print(line)\n", + "\n", + "# когда дойдем до четвертой строки\n", + "# if i == 3:\n", + "\n", + "# прервемся\n", + "# break" + ] + }, + { + "cell_type": "markdown", + "id": "10657f41", + "metadata": {}, + "source": [ + "#### Использование функции open() и конструкции with open()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cb9d3c23", + "metadata": {}, + "outputs": [], + "source": [ + "# передадим функции open() адрес файла\n", + "# параметр 'r' означает, что мы хотим прочитать (read) файл\n", + "# f1 = open(\"/content/train.csv\")\n", + "\n", + "# метод .read() помещает весь файл в одну строку\n", + "# выведем первые 142 символа (если параметр не указывать, выведется все содержимое)\n", + "# print(f1.read(142))\n", + "\n", + "# в конце файл необходимо закрыть\n", + "# f1.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b71a07a", + "metadata": {}, + "outputs": [], + "source": [ + "# снова откроем файл\n", + "# f2 = open(\"/content/train.csv\")\n", + "\n", + "# пройдемся по нашему объекту в цикле for и параллельно создадим индекс\n", + "# for i, line in enumerate(f2):\n", + "\n", + "# выведем строки без служебных символов по краям\n", + "# print(line.strip())\n", + "\n", + "# дойдя до четвертой строки, прервемся\n", + "# if i == 3:\n", + "# break\n", + "\n", + "# не забудем закрыть файл\n", + "# f2.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d74d70ae", + "metadata": {}, + "outputs": [], + "source": [ + "# скажем Питону: \"открой файл и назови его f3\"\n", + "# with open(\"/content/test.csv\") as f3:\n", + "\n", + "# \"пройдись по строкам без служебных символов\"\n", + "# for i, line in enumerate(f3):\n", + "# print(line.strip())\n", + "\n", + "# и \"прервись на четвертой строке\"\n", + "# if i == 3:\n", + "# break" + ] + }, + { + "cell_type": "markdown", + "id": "d0743408", + "metadata": {}, + "source": [ + "Чтение через библиотеку Pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b4aad6b0", + "metadata": {}, + "outputs": [], + "source": [ + "# применим функцию read_csv() и посмотрим на первые три записи файла train.csv\n", + "# train = pd.read_csv(\"/content/train.csv\")\n", + "# train.head(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcfa06c2", + "metadata": {}, + "outputs": [], + "source": [ + "# сделаем то же самое с файлом test.csv\n", + "# test = pd.read_csv(\"/content/test.csv\")\n", + "# test.head(3)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_4_files.py b/python/makarov/chapter_4_files.py new file mode 100644 index 00000000..86ab1eec --- /dev/null +++ b/python/makarov/chapter_4_files.py @@ -0,0 +1,154 @@ +"""Работа с файлами в Google Colab.""" + +# + +# импортируем модуль os +# import os + +# импортируем библиотеку +# import pandas as pd + +# из библиотеки google.colab импортируем класс files +# from google.colab import files +# - + +# Этап 1. Подгрузка файлов. + +# Способ 1. Вручную через вкладку "Файлы". +# Нажимаем на иконку загрузки файлов на левой боковой панели и в открывшемся окне выбираем те файлы, которые хотели загрузить. + +# Способ 2. Через модуль files библиотеки google.colab. + +# + +# создаем объект этого класса, применяем метод .upload() +# uploaded = files.upload() + +# + +# посмотрим на содержимое словаря uploaded +# uploaded +# - + +# Этап 2. Чтение файлов. +# +# Просмотр содержимого папки /content/ +# +# Модуль os и метод .walk() + +# + +# выводим пути к папкам (dirpath) и наименования файлов (filenames) и после этого +# for dirpath, _, filenames in os.walk("/content/"): + +# во вложенном цикле проходимся по названиям файлов +# for filename in filenames: + +# и соединяем путь до папок и входящие в эти папки файлы +# с помощью метода path.join() +# print(os.path.join(dirpath, filename)) +# - + +# Команда !ls + +# + +# посмотрим на содержимое папки content +# # !ls + +# + +# заглянем внутрь sample_data +# # !ls /content/sample_data/ +# - + +# Чтение из переменной uploaded + +# + +# посмотрим на тип значений словаря uploaded +# type(uploaded["test.csv"]) +# - + +# Пример работы с объектом bytes + +# + +# обратимся к ключу словаря uploaded и применим метод .decode() +# uploaded_str = uploaded["test.csv"].decode() + +# на выходе получаем обычную строку +# print(type(uploaded_str)) + +# + +# выведем первые 35 значений +# print(uploaded_str[:35]) + +# + +# если разбить строку методом .split() по символам \r (возврат к началу строки) и \n (новая строка) +# uploaded_list = uploaded_str.split("\r\n") + +# на выходе мы получим список +# type(uploaded_list) + +# + +# пройдемся по этому списку, не забыв создать индекс с помощью функции enumerate() +# for i, line in enumerate(uploaded_list): + +# начнем выводить записи +# print(line) + +# когда дойдем до четвертой строки +# if i == 3: + +# прервемся +# break +# - + +# #### Использование функции open() и конструкции with open() + +# + +# передадим функции open() адрес файла +# параметр 'r' означает, что мы хотим прочитать (read) файл +# f1 = open("/content/train.csv") + +# метод .read() помещает весь файл в одну строку +# выведем первые 142 символа (если параметр не указывать, выведется все содержимое) +# print(f1.read(142)) + +# в конце файл необходимо закрыть +# f1.close() + +# + +# снова откроем файл +# f2 = open("/content/train.csv") + +# пройдемся по нашему объекту в цикле for и параллельно создадим индекс +# for i, line in enumerate(f2): + +# выведем строки без служебных символов по краям +# print(line.strip()) + +# дойдя до четвертой строки, прервемся +# if i == 3: +# break + +# не забудем закрыть файл +# f2.close() + +# + +# скажем Питону: "открой файл и назови его f3" +# with open("/content/test.csv") as f3: + +# "пройдись по строкам без служебных символов" +# for i, line in enumerate(f3): +# print(line.strip()) + +# и "прервись на четвертой строке" +# if i == 3: +# break +# - + +# Чтение через библиотеку Pandas + +# + +# применим функцию read_csv() и посмотрим на первые три записи файла train.csv +# train = pd.read_csv("/content/train.csv") +# train.head(3) + +# + +# сделаем то же самое с файлом test.csv +# test = pd.read_csv("/content/test.csv") +# test.head(3) From 19089867f878fdbc4456fa978e835690d2becf86 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Thu, 9 Apr 2026 23:25:59 +0500 Subject: [PATCH 18/24] task 1 functions --- python/makarov/chapter_6_functions.ipynb | 1275 ++++++++++++++++++++++ python/makarov/chapter_6_functions.py | 572 ++++++++++ 2 files changed, 1847 insertions(+) create mode 100644 python/makarov/chapter_6_functions.ipynb create mode 100644 python/makarov/chapter_6_functions.py diff --git a/python/makarov/chapter_6_functions.ipynb b/python/makarov/chapter_6_functions.ipynb new file mode 100644 index 00000000..cf6a59ae --- /dev/null +++ b/python/makarov/chapter_6_functions.ipynb @@ -0,0 +1,1275 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f1f999a3", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Функции в Питоне.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "0e82c0ff", + "metadata": {}, + "source": [ + "Встроенные функции" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "id": "54eb4582", + "metadata": {}, + "outputs": [], + "source": [ + "# импортируем библиотеки\n", + "# import matplotlib.pyplot as plt\n", + "\n", + "# перед вызовом функции нужно не забыть импортировать соответствующую библиотеку\n", + "# import numpy as np\n", + "\n", + "# установим точку отсчета\n", + "# np.random.seed(42)\n", + "# и снова сгенерируем данные о росте (как мы делали на восьмом занятии вводного курса)\n", + "# height = list(np.round(np.random.normal(180, 10, 1000)))" + ] + }, + { + "cell_type": "markdown", + "id": "c37eb449", + "metadata": {}, + "source": [ + "Параметры и аргументы функции" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "id": "e788f834", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь построим гистограмму передав ей два параметра, данные о росте и количество интервалов\n", + "# первый параметр у нас позиционный, второй - именованный\n", + "# plt.hist(height, bins=10)\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "id": "2ea99819", + "metadata": {}, + "outputs": [], + "source": [ + "# первый параметр можно также сделать именованным (данные обозначаются через x)\n", + "# и тогда порядок параметров можно менять\n", + "# plt.hist(bins=10, x=height)\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "id": "162fac0f", + "metadata": {}, + "outputs": [], + "source": [ + "# у параметра bins есть аргумент по умолчанию (как раз 10 интервалов),\n", + "# а значит, этот параметр можно не указывать\n", + "# plt.hist(height)\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "id": "feb0d015", + "metadata": {}, + "outputs": [], + "source": [ + "# функция может не принимать параметров\n", + "# print(\"Первая строка\")\n", + "# print()\n", + "# print(\"Третья строка\")" + ] + }, + { + "cell_type": "markdown", + "id": "462bae57", + "metadata": {}, + "source": [ + "Функции и методы" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "id": "7910ba14", + "metadata": {}, + "outputs": [], + "source": [ + "# дана строка\n", + "# some_string = \"machine learning\"\n", + "\n", + "# применим метод .title()\n", + "# some_string.title()" + ] + }, + { + "cell_type": "markdown", + "id": "317bc3eb", + "metadata": {}, + "source": [ + "Собственные функции в Питоне" + ] + }, + { + "cell_type": "markdown", + "id": "a4625d4c", + "metadata": {}, + "source": [ + "Объявление и вызов функций" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aef7907d", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим функцию, которая удваивает любое передаваемое ей значение\n", + "\n", + "\n", + "# def double(x):\n", + "# res = x * 2\n", + "# return res" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0598ed5a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# и вызовем ее, передав число 2\n", + "# double(2)" + ] + }, + { + "cell_type": "markdown", + "id": "075ad872", + "metadata": {}, + "source": [ + "Пустое тело функции" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "03ecf9d9", + "metadata": {}, + "outputs": [], + "source": [ + "# тело функции не может быть пустым\n", + "\n", + "\n", + "# def only_return():\n", + "\n", + "# нужно либо указать ключевое слово return\n", + "# return" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5d942810", + "metadata": {}, + "outputs": [], + "source": [ + "# либо оператор pass\n", + "\n", + "\n", + "# def only_pass():\n", + "# pass" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1ee7a93c", + "metadata": {}, + "outputs": [], + "source": [ + "# такая функция вернет тип данных None (отсутствие значения)\n", + "# print(only_return())" + ] + }, + { + "cell_type": "markdown", + "id": "7c01b6f9", + "metadata": {}, + "source": [ + "Функция print() вместо return" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad88b9b7", + "metadata": {}, + "outputs": [], + "source": [ + "# можно использовать print(), но есть нюансы (см. на странице урока)\n", + "\n", + "\n", + "# def double_print(x):\n", + "# res = x * 2\n", + "# print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fa3d4f2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n" + ] + } + ], + "source": [ + "# double_print(5)" + ] + }, + { + "cell_type": "markdown", + "id": "bb13066e", + "metadata": {}, + "source": [ + "Параметры собственных функций" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4cdb698a", + "metadata": {}, + "outputs": [], + "source": [ + "# объявим функцию с параметрами x и y\n", + "\n", + "\n", + "# def calc_sum(x, y):\n", + "# return x + y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "244e0db2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# вызовем эту функцию с одним позиционным и одним именованным параметром\n", + "# calc_sum(1, y=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "689059f1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "13" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# параметрам функции можно задать аргументы по умолчанию\n", + "\n", + "\n", + "# def calc_sum_default(x=6, y=7):\n", + "# return x + y\n", + "\n", + "\n", + "# и при вызове тогда их указывать не обязательно\n", + "# calc_sum_default()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "efa29ec3", + "metadata": {}, + "outputs": [], + "source": [ + "# функция может не иметь параметров\n", + "\n", + "\n", + "# def print_string():\n", + "# print(\"Some string\")\n", + "\n", + "\n", + "# print_string()" + ] + }, + { + "cell_type": "markdown", + "id": "4362daa7", + "metadata": {}, + "source": [ + "Аннотация функция " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ce48d18", + "metadata": {}, + "outputs": [], + "source": [ + "# укажем, что на входе функция принимает тип float, а возвращает int\n", + "# значение 3,5 - это значение параметра x по умолчанию\n", + "\n", + "\n", + "# def f(x: float = 3.5) -> int:\n", + "# return int(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "2ae02bd1", + "metadata": {}, + "outputs": [], + "source": [ + "# желаемый тип данных можно посмотреть через атрибут __annotations__\n", + "# f.__annotations__" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "9caa69bf", + "metadata": {}, + "outputs": [], + "source": [ + "# вызовем функцию без параметров\n", + "# f()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "3cc4e68b", + "metadata": {}, + "outputs": [], + "source": [ + "# сохраним аннотации, но изменим суть функции\n", + "\n", + "\n", + "# def f(x: float) -> int:\n", + "# теперь вместо int она будет возвращать float\n", + "# return float(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "bd3db98c", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь вызовем функцию, передав ей на входе int, и ожидая на выходе получить # float\n", + "# f(3)" + ] + }, + { + "cell_type": "markdown", + "id": "f4759873", + "metadata": {}, + "source": [ + "Дополнительные возможности" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "53f6f88b", + "metadata": {}, + "outputs": [], + "source": [ + "# вызов функции можно совмещать с арифметическими\n", + "# calc_sum(1, 2) * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "faabdd5b", + "metadata": {}, + "outputs": [], + "source": [ + "# и логическими операциями\n", + "# calc_sum(1, 2) > 2" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "d5393944", + "metadata": {}, + "outputs": [], + "source": [ + "# можно и так\n", + "\n", + "\n", + "# def first_letter():\n", + "# return \"Python\"\n", + "\n", + "\n", + "# first_letter()[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6c08e9ae", + "metadata": {}, + "outputs": [], + "source": [ + "# функция может не принимать параметров, но использовать input()\n", + "\n", + "\n", + "# def use_input():\n", + "\n", + "# запросим у пользователя число и переведем его в тип данных int\n", + "# user_inp = int(input(\"Введите число: \"))\n", + "\n", + "# возведем число в квадрат\n", + "# result = user_inp**2\n", + "\n", + "# вернем результат\n", + "# return result\n", + "\n", + "\n", + "# вызовем функцию\n", + "# use_input()" + ] + }, + { + "cell_type": "markdown", + "id": "8ad8aca1", + "metadata": {}, + "source": [ + "Результат вызова функции" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "64432ca2", + "metadata": {}, + "outputs": [], + "source": [ + "# функция может возвращать также список, кортеж, словарь и др.\n", + "\n", + "\n", + "# объявим функцию, которая на входе получает число,\n", + "# а на выходе формирует список чисел от 0 и до числа, предшествующего заданному\n", + "# def create_list(x):\n", + "\n", + "# создадим пустой список\n", + "# l = []\n", + "\n", + "# в цикле for создадим последовательность\n", + "# for i in range(x):\n", + "\n", + "# и поместим ее в список\n", + "# l.append(i)\n", + "\n", + "# return l\n", + "\n", + "\n", + "# результатом вызова этой функции будет список\n", + "# create_list(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6f7f76dc", + "metadata": {}, + "outputs": [], + "source": [ + "# функция может возвращать сразу два значения\n", + "\n", + "\n", + "# def tuple_f():\n", + "# string = \"Python\"\n", + "# x = 42\n", + "# return string, x" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "ef7cf7d9", + "metadata": {}, + "outputs": [], + "source": [ + "# если использовать две переменные\n", + "# a_12, b_12 = tuple_f()\n", + "\n", + "# на выходе мы получим строку и число\n", + "# print(a_12, b_12)\n", + "# print(type(a_12), type(b_12))" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "30db03e7", + "metadata": {}, + "outputs": [], + "source": [ + "# если одну\n", + "# c_12 = tuple_f()\n", + "\n", + "# получится кортеж\n", + "# print(c_12)\n", + "# print(type(c_12))" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "85df6389", + "metadata": {}, + "outputs": [], + "source": [ + "# выводом может быть логическое значение (True или False)\n", + "\n", + "\n", + "# def if_divisible(x):\n", + "# если остаток от деления на два равен нулю\n", + "# if x % 2 == 0:\n", + "\n", + "# вернем True\n", + "# return True\n", + "\n", + "# else:\n", + "\n", + "# в противном случае False\n", + "# return False\n", + "\n", + "\n", + "# if_divisible(10)" + ] + }, + { + "cell_type": "markdown", + "id": "9dee8c6b", + "metadata": {}, + "source": [ + "Использование библиотеки " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5faed42d", + "metadata": {}, + "outputs": [], + "source": [ + "# применим функцию mean() библиотеки Numpy для расчета среднего арифметического\n", + "\n", + "\n", + "# на входе наша функция примет список или массив x,\n", + "# def mean_f(x):\n", + "# рассчитает среднее арифметическое и прибавит единицу\n", + "# return np.mean(x) + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "805b78ba", + "metadata": {}, + "outputs": [], + "source": [ + "# и подготовить данные\n", + "# x_11 = [1, 2, 3]\n", + "\n", + "# mean_f(x_11)" + ] + }, + { + "cell_type": "markdown", + "id": "3ec3c11a", + "metadata": {}, + "source": [ + "Глобальные и локальные переменные " + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "124aae28", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим глобальную переменную вне функции\n", + "# global_name = \"Петр\"\n", + "\n", + "# а затем используем ее внутри новой функции\n", + "\n", + "\n", + "# def show_name():\n", + "# print(global_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "78068855", + "metadata": {}, + "outputs": [], + "source": [ + "# show_name()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03e88036", + "metadata": {}, + "outputs": [], + "source": [ + "# а теперь вначале создадим функцию,\n", + "# внутри которой объявим локальную переменную\n", + "\n", + "\n", + "# def show_local_name():\n", + "# local_name = \"Светлана\"\n", + "# print(local_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "9f44bc9a", + "metadata": {}, + "outputs": [], + "source": [ + "# show_local_name()" + ] + }, + { + "cell_type": "markdown", + "id": "e63bf52c", + "metadata": {}, + "source": [ + "При попытке обратиться к переменной вне функции мы получим ошибку" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "fecf6cca", + "metadata": {}, + "outputs": [], + "source": [ + "# превратить локальную переменную в глобальную можно через ключевое слово global\n", + "\n", + "\n", + "# def make_global():\n", + "# global local_name\n", + "# local_name = \"Алена\"\n", + "# print(local_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "9259dd84", + "metadata": {}, + "outputs": [], + "source": [ + "# make_global()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "aa7389aa", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь ошибки быть не должно\n", + "# local_name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b67d0d76", + "metadata": {}, + "outputs": [], + "source": [ + "# объявим глобальную переменную\n", + "# global_number = 5\n", + "\n", + "\n", + "# def print_number():\n", + "# затем объявим локальную переменную\n", + "# local_number = 10\n", + "# print(\"Local number:\", local_number)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "d7b5c678", + "metadata": {}, + "outputs": [], + "source": [ + "# функция всегда \"предпочтет\" локальную переменную\n", + "# print_number()" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "a1b6314b", + "metadata": {}, + "outputs": [], + "source": [ + "# при этом значение глобальной переменной для остального кода не изменится\n", + "# print(\"Global number:\", global_number)" + ] + }, + { + "cell_type": "markdown", + "id": "9a78aace", + "metadata": {}, + "source": [ + "Lambda-функции" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34da7ae9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# создадим функцию, которая принимает два числа и перемножает их\n", + "# lf = lambda a, b: a * b\n", + "\n", + "# вызовем функцию и передадим ей числа 2 и 3\n", + "# lf(2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "e5670672", + "metadata": {}, + "outputs": [], + "source": [ + "# этот же функционал можно поместить в обычную функцию\n", + "\n", + "\n", + "# def normal_f(a, b):\n", + "# return a * b\n", + "\n", + "\n", + "# normal_f(2, 3)" + ] + }, + { + "cell_type": "markdown", + "id": "d3ec214f", + "metadata": {}, + "source": [ + "Lambda-функция внутри функции filter()" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "92ff61ce", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим список\n", + "# nums = [15, 27, 9, 18, 3, 1, 4]\n", + "\n", + "# напишем lambda-функцию, которая выведет True, если число больше 10, и False, если меньше\n", + "# criterion = lambda n: True if (n > 10) else False\n", + "\n", + "# поместим список и lambda-функцию в функцию filter() и преобразуем результат в список\n", + "# list(filter(criterion, nums))" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "705335fe", + "metadata": {}, + "outputs": [], + "source": [ + "# все это можно записать в одну строчку\n", + "# list(filter(lambda n: True if (n > 10) else False, nums))" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "854fec8a", + "metadata": {}, + "outputs": [], + "source": [ + "# ту же задачу можно решить через обычную функцию,\n", + "# но придется написать больше кода\n", + "\n", + "\n", + "# def criterion_2(n):\n", + "# if n > 10:\n", + "# return True\n", + "# else:\n", + "# return False\n", + "\n", + "\n", + "# list(filter(criterion_2, nums))" + ] + }, + { + "cell_type": "markdown", + "id": "d28fe808", + "metadata": {}, + "source": [ + "Lambda-функция внутри функции sorted()" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "7dc05ecc", + "metadata": {}, + "outputs": [], + "source": [ + "# напомню, что мы создали список из кортежей,\n", + "# и в каждом кортеже был индекс фильма и расстояние до него\n", + "# indices_distances = [\n", + "# (901, 0.0),\n", + "# (1002, 0.22982440568634488),\n", + "# (442, 0.25401128310081567),\n", + "# ]\n", + "\n", + "# lambda-функция возьмет каждый кортеж и вернет второй [1] его элемент\n", + "# передав эту функцию через параметр key, мы отсортируем список по расстоянию\n", + "# sorted(indices_distances, key=lambda x: x[1], reverse=False)" + ] + }, + { + "cell_type": "markdown", + "id": "5e8a5eb0", + "metadata": {}, + "source": [ + "Немедленно вызываемые функции" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "3c6b9252", + "metadata": {}, + "outputs": [], + "source": [ + "# lambda-функцию можно вызвать сразу в момент объявления\n", + "# (lambda x: x * x)(10)" + ] + }, + { + "cell_type": "markdown", + "id": "959d17cf", + "metadata": {}, + "source": [ + "args и kwargs" + ] + }, + { + "cell_type": "markdown", + "id": "4b637257", + "metadata": {}, + "source": [ + "*args" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "e2a78371", + "metadata": {}, + "outputs": [], + "source": [ + "# напишем функцию для расчета среднего арифметического двух чисел\n", + "\n", + "\n", + "# def mean(a: float, b: float):\n", + "# return (a + b) / 2" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "2b37d0b1", + "metadata": {}, + "outputs": [], + "source": [ + "# mean(1, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b29e45b2", + "metadata": {}, + "outputs": [], + "source": [ + "# объявим функцию, которой нужно передать список\n", + "\n", + "\n", + "# def mean(list_):\n", + "# зададим переменную для суммы,\n", + "# total: int = 0\n", + "\n", + "# в цикле сложим все числа из списка\n", + "# for i in list_:\n", + "# total += i\n", + "\n", + "# и разделим на количество элементов\n", + "# return total / len(list_)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6d57ab6c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# создадим список\n", + "# list_: list[int] = [1, 2, 3, 4]\n", + "# и передадим его в новую функцию\n", + "# mean(list_)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3cd01837", + "metadata": {}, + "outputs": [], + "source": [ + "# однако новая функция уже не может работать с отдельными числами" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16d1ca12", + "metadata": {}, + "outputs": [], + "source": [ + "# объявим функцию с *args\n", + "\n", + "\n", + "# def mean(*nums):\n", + "# в данном случае мы складываем элементы кортежа\n", + "# total_: int = 0\n", + "# for i in nums:\n", + "# total_ += i\n", + "\n", + "# return total_ / len(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0d6cd46", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# теперь мы можем передать функции отдельные числа\n", + "# mean(1, 2, 3, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2256b697", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# или список\n", + "# mean(*list_)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "ad6d9910", + "metadata": {}, + "outputs": [], + "source": [ + "# убедимся, что оператор распаковки * формирует кортеж\n", + "\n", + "\n", + "# def test_type(*nums):\n", + "# print(nums, type(nums))\n", + "\n", + "\n", + "# test_type(1, 2, 3, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "d7de1dbc", + "metadata": {}, + "outputs": [], + "source": [ + "# со списком происходит то же самое\n", + "# test_type(*list_)" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "id": "b2245013", + "metadata": {}, + "outputs": [], + "source": [ + "# для наглядности приведем еще один пример\n", + "# a_1: list[int] = [1, 2, 3]\n", + "# b_1: list[int] = [*a, 4, 5, 6]\n", + "\n", + "# print(b_1)" + ] + }, + { + "cell_type": "markdown", + "id": "10d69877", + "metadata": {}, + "source": [ + "**kwargs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4ddaa3b", + "metadata": {}, + "outputs": [], + "source": [ + "# **kwargs преобразует именованные параметры в словарь\n", + "\n", + "\n", + "# def f(**kwargs):\n", + "# return kwargs.items()" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "a85e628e", + "metadata": {}, + "outputs": [], + "source": [ + "# f(a=1, b=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "36ee3abf", + "metadata": {}, + "outputs": [], + "source": [ + "# *nums превращается в кортеж, **params - в словарь\n", + "\n", + "\n", + "# def simple_stats(*nums, **params):\n", + "\n", + "# если ключ 'mean' есть в словаре params и его значение == True\n", + "# if \"mean\" in params and params[\"mean\"] == True:\n", + "\n", + "# рассчитаем среднее арифметическое и округлим\n", + "# \\t - это символ табуляции\n", + "# print(f\"mean: \\t{np.round(np.mean(nums), 3)}\")\n", + "\n", + "# если ключ 'std' есть в словаре params и его значение == True\n", + "# if \"std\" in params and params[\"std\"] == True:\n", + "\n", + "# рассчитаем СКО и округлим\n", + "# print(f\"std: \\t{np.round(np.std(nums), 3)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "954d70df", + "metadata": {}, + "outputs": [], + "source": [ + "# вызовем функцию simple_stats() и передадим ей числа и именованные аргументы\n", + "# simple_stats(5, 10, 15, 20, mean=True, std=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "482c89fa", + "metadata": {}, + "outputs": [], + "source": [ + "# если для одного из параметров задать значение False,\n", + "# функция не выведет соответствующую метрику\n", + "# simple_stats(5, 10, 15, 20, mean=True, std=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "03e3428f", + "metadata": {}, + "outputs": [], + "source": [ + "# если мы хотим передать параметры списком и словарем,\n", + "# list_ = [5, 10, 15, 20]\n", + "# settings = {\"mean\": True, \"std\": True}\n", + "\n", + "# то нам нужно использовать операторы распаковки * и ** соответственно\n", + "# simple_stats(*list_, **settings)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "bf30d6ef", + "metadata": {}, + "outputs": [], + "source": [ + "# ничто не мешает нам добавить еще один параметр\n", + "# simple_stats(5, 10, 15, 20, mean=True, std=True, median=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_6_functions.py b/python/makarov/chapter_6_functions.py new file mode 100644 index 00000000..51df871d --- /dev/null +++ b/python/makarov/chapter_6_functions.py @@ -0,0 +1,572 @@ +"""Функции в Питоне.""" + +# Встроенные функции + +# + +# импортируем библиотеки +# import matplotlib.pyplot as plt + +# перед вызовом функции нужно не забыть импортировать соответствующую библиотеку +# import numpy as np + +# установим точку отсчета +# np.random.seed(42) +# и снова сгенерируем данные о росте (как мы делали на восьмом занятии вводного курса) +# height = list(np.round(np.random.normal(180, 10, 1000))) +# - + +# Параметры и аргументы функции + +# + +# теперь построим гистограмму передав ей два параметра, данные о росте и количество интервалов +# первый параметр у нас позиционный, второй - именованный +# plt.hist(height, bins=10) +# plt.show() + +# + +# первый параметр можно также сделать именованным (данные обозначаются через x) +# и тогда порядок параметров можно менять +# plt.hist(bins=10, x=height) +# plt.show() + +# + +# у параметра bins есть аргумент по умолчанию (как раз 10 интервалов), +# а значит, этот параметр можно не указывать +# plt.hist(height) +# plt.show() + +# + +# функция может не принимать параметров +# print("Первая строка") +# print() +# print("Третья строка") +# - + +# Функции и методы + +# + +# дана строка +# some_string = "machine learning" + +# применим метод .title() +# some_string.title() +# - + +# Собственные функции в Питоне + +# Объявление и вызов функций + +# + +# создадим функцию, которая удваивает любое передаваемое ей значение + + +# def double(x): +# res = x * 2 +# return res + +# + +# и вызовем ее, передав число 2 +# double(2) +# - + +# Пустое тело функции + +# + +# тело функции не может быть пустым + + +# def only_return(): + +# нужно либо указать ключевое слово return +# return + +# + +# либо оператор pass + + +# def only_pass(): +# pass + +# + +# такая функция вернет тип данных None (отсутствие значения) +# print(only_return()) +# - + +# Функция print() вместо return + +# + +# можно использовать print(), но есть нюансы (см. на странице урока) + + +# def double_print(x): +# res = x * 2 +# print(res) + +# + +# double_print(5) +# - + +# Параметры собственных функций + +# + +# объявим функцию с параметрами x и y + + +# def calc_sum(x, y): +# return x + y + +# + +# вызовем эту функцию с одним позиционным и одним именованным параметром +# calc_sum(1, y=2) + +# + +# параметрам функции можно задать аргументы по умолчанию + + +# def calc_sum_default(x=6, y=7): +# return x + y + + +# и при вызове тогда их указывать не обязательно +# calc_sum_default() + +# + +# функция может не иметь параметров + + +# def print_string(): +# print("Some string") + + +# print_string() +# - + +# Аннотация функция + +# + +# укажем, что на входе функция принимает тип float, а возвращает int +# значение 3,5 - это значение параметра x по умолчанию + + +# def f(x: float = 3.5) -> int: +# return int(x) + +# + +# желаемый тип данных можно посмотреть через атрибут __annotations__ +# f.__annotations__ + +# + +# вызовем функцию без параметров +# f() + +# + +# сохраним аннотации, но изменим суть функции + + +# def f(x: float) -> int: +# теперь вместо int она будет возвращать float +# return float(x) + +# + +# вновь вызовем функцию, передав ей на входе int, и ожидая на выходе получить # float +# f(3) +# - + +# Дополнительные возможности + +# + +# вызов функции можно совмещать с арифметическими +# calc_sum(1, 2) * 2 + +# + +# и логическими операциями +# calc_sum(1, 2) > 2 + +# + +# можно и так + + +# def first_letter(): +# return "Python" + + +# first_letter()[0] + +# + +# функция может не принимать параметров, но использовать input() + + +# def use_input(): + +# запросим у пользователя число и переведем его в тип данных int +# user_inp = int(input("Введите число: ")) + +# возведем число в квадрат +# result = user_inp**2 + +# вернем результат +# return result + + +# вызовем функцию +# use_input() +# - + +# Результат вызова функции + +# + +# функция может возвращать также список, кортеж, словарь и др. + + +# объявим функцию, которая на входе получает число, +# а на выходе формирует список чисел от 0 и до числа, предшествующего заданному +# def create_list(x): + +# создадим пустой список +# l = [] + +# в цикле for создадим последовательность +# for i in range(x): + +# и поместим ее в список +# l.append(i) + +# return l + + +# результатом вызова этой функции будет список +# create_list(5) + +# + +# функция может возвращать сразу два значения + + +# def tuple_f(): +# string = "Python" +# x = 42 +# return string, x + +# + +# если использовать две переменные +# a_12, b_12 = tuple_f() + +# на выходе мы получим строку и число +# print(a_12, b_12) +# print(type(a_12), type(b_12)) + +# + +# если одну +# c_12 = tuple_f() + +# получится кортеж +# print(c_12) +# print(type(c_12)) + +# + +# выводом может быть логическое значение (True или False) + + +# def if_divisible(x): +# если остаток от деления на два равен нулю +# if x % 2 == 0: + +# вернем True +# return True + +# else: + +# в противном случае False +# return False + + +# if_divisible(10) +# - + +# Использование библиотеки + +# + +# применим функцию mean() библиотеки Numpy для расчета среднего арифметического + + +# на входе наша функция примет список или массив x, +# def mean_f(x): +# рассчитает среднее арифметическое и прибавит единицу +# return np.mean(x) + 1 + +# + +# и подготовить данные +# x_11 = [1, 2, 3] + +# mean_f(x_11) +# - + +# Глобальные и локальные переменные + +# + +# создадим глобальную переменную вне функции +# global_name = "Петр" + +# а затем используем ее внутри новой функции + + +# def show_name(): +# print(global_name) + +# + +# show_name() + +# + +# а теперь вначале создадим функцию, +# внутри которой объявим локальную переменную + + +# def show_local_name(): +# local_name = "Светлана" +# print(local_name) + +# + +# show_local_name() +# - + +# При попытке обратиться к переменной вне функции мы получим ошибку + +# + +# превратить локальную переменную в глобальную можно через ключевое слово global + + +# def make_global(): +# global local_name +# local_name = "Алена" +# print(local_name) + +# + +# make_global() + +# + +# теперь ошибки быть не должно +# local_name + +# + +# объявим глобальную переменную +# global_number = 5 + + +# def print_number(): +# затем объявим локальную переменную +# local_number = 10 +# print("Local number:", local_number) + +# + +# функция всегда "предпочтет" локальную переменную +# print_number() + +# + +# при этом значение глобальной переменной для остального кода не изменится +# print("Global number:", global_number) +# - + +# Lambda-функции + +# + +# создадим функцию, которая принимает два числа и перемножает их +# lf = lambda a, b: a * b + +# вызовем функцию и передадим ей числа 2 и 3 +# lf(2, 3) + +# + +# этот же функционал можно поместить в обычную функцию + + +# def normal_f(a, b): +# return a * b + + +# normal_f(2, 3) +# - + +# Lambda-функция внутри функции filter() + +# + +# создадим список +# nums = [15, 27, 9, 18, 3, 1, 4] + +# напишем lambda-функцию, которая выведет True, если число больше 10, и False, если меньше +# criterion = lambda n: True if (n > 10) else False + +# поместим список и lambda-функцию в функцию filter() и преобразуем результат в список +# list(filter(criterion, nums)) + +# + +# все это можно записать в одну строчку +# list(filter(lambda n: True if (n > 10) else False, nums)) + +# + +# ту же задачу можно решить через обычную функцию, +# но придется написать больше кода + + +# def criterion_2(n): +# if n > 10: +# return True +# else: +# return False + + +# list(filter(criterion_2, nums)) +# - + +# Lambda-функция внутри функции sorted() + +# + +# напомню, что мы создали список из кортежей, +# и в каждом кортеже был индекс фильма и расстояние до него +# indices_distances = [ +# (901, 0.0), +# (1002, 0.22982440568634488), +# (442, 0.25401128310081567), +# ] + +# lambda-функция возьмет каждый кортеж и вернет второй [1] его элемент +# передав эту функцию через параметр key, мы отсортируем список по расстоянию +# sorted(indices_distances, key=lambda x: x[1], reverse=False) +# - + +# Немедленно вызываемые функции + +# + +# lambda-функцию можно вызвать сразу в момент объявления +# (lambda x: x * x)(10) +# - + +# args и kwargs + +# *args + +# + +# напишем функцию для расчета среднего арифметического двух чисел + + +# def mean(a: float, b: float): +# return (a + b) / 2 + +# + +# mean(1, 2) + +# + +# объявим функцию, которой нужно передать список + + +# def mean(list_): +# зададим переменную для суммы, +# total: int = 0 + +# в цикле сложим все числа из списка +# for i in list_: +# total += i + +# и разделим на количество элементов +# return total / len(list_) + +# + +# создадим список +# list_: list[int] = [1, 2, 3, 4] +# и передадим его в новую функцию +# mean(list_) + +# + +# однако новая функция уже не может работать с отдельными числами + +# + +# объявим функцию с *args + + +# def mean(*nums): +# в данном случае мы складываем элементы кортежа +# total_: int = 0 +# for i in nums: +# total_ += i + +# return total_ / len(nums) + +# + +# теперь мы можем передать функции отдельные числа +# mean(1, 2, 3, 4) + +# + +# или список +# mean(*list_) + +# + +# убедимся, что оператор распаковки * формирует кортеж + + +# def test_type(*nums): +# print(nums, type(nums)) + + +# test_type(1, 2, 3, 4) + +# + +# со списком происходит то же самое +# test_type(*list_) + +# + +# для наглядности приведем еще один пример +# a_1: list[int] = [1, 2, 3] +# b_1: list[int] = [*a, 4, 5, 6] + +# print(b_1) +# - + +# **kwargs + +# + +# **kwargs преобразует именованные параметры в словарь + + +# def f(**kwargs): +# return kwargs.items() + +# + +# f(a=1, b=2) + +# + +# *nums превращается в кортеж, **params - в словарь + + +# def simple_stats(*nums, **params): + +# если ключ 'mean' есть в словаре params и его значение == True +# if "mean" in params and params["mean"] == True: + +# рассчитаем среднее арифметическое и округлим +# \t - это символ табуляции +# print(f"mean: \t{np.round(np.mean(nums), 3)}") + +# если ключ 'std' есть в словаре params и его значение == True +# if "std" in params and params["std"] == True: + +# рассчитаем СКО и округлим +# print(f"std: \t{np.round(np.std(nums), 3)}") + +# + +# вызовем функцию simple_stats() и передадим ей числа и именованные аргументы +# simple_stats(5, 10, 15, 20, mean=True, std=True) + +# + +# если для одного из параметров задать значение False, +# функция не выведет соответствующую метрику +# simple_stats(5, 10, 15, 20, mean=True, std=False) + +# + +# если мы хотим передать параметры списком и словарем, +# list_ = [5, 10, 15, 20] +# settings = {"mean": True, "std": True} + +# то нам нужно использовать операторы распаковки * и ** соответственно +# simple_stats(*list_, **settings) + +# + +# ничто не мешает нам добавить еще один параметр +# simple_stats(5, 10, 15, 20, mean=True, std=True, median=True) From 4db767c988bbdab6ac5eeaf044d51f503b9d3e75 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 13:31:59 +0500 Subject: [PATCH 19/24] task 1 classes, tuples, lists --- python/makarov/chapter_7_classes.ipynb | 1112 ++++++++++++++ python/makarov/chapter_7_classes.py | 495 ++++++ .../makarov/chapter_8_lists_tuples_sets.ipynb | 1325 +++++++++++++++++ python/makarov/chapter_8_lists_tuples_sets.py | 569 +++++++ 4 files changed, 3501 insertions(+) create mode 100644 python/makarov/chapter_7_classes.ipynb create mode 100644 python/makarov/chapter_7_classes.py create mode 100644 python/makarov/chapter_8_lists_tuples_sets.ipynb create mode 100644 python/makarov/chapter_8_lists_tuples_sets.py diff --git a/python/makarov/chapter_7_classes.ipynb b/python/makarov/chapter_7_classes.ipynb new file mode 100644 index 00000000..f2210bdd --- /dev/null +++ b/python/makarov/chapter_7_classes.ipynb @@ -0,0 +1,1112 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "00c465d5", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Классы.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "b5e518cb", + "metadata": {}, + "source": [ + "Создание класса." + ] + }, + { + "cell_type": "markdown", + "id": "9dca6699", + "metadata": {}, + "source": [ + "Создание класса и метод .__init__()" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9a6edd1a", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс CatClass\n", + "# массивом Numpy и другими объектами\n", + "# import numpy as np\n", + "\n", + "\n", + "# class CatClass:\n", + "\n", + "# и пропишем метод .__init__()\n", + "# def __init__(self):\n", + "# pass" + ] + }, + { + "cell_type": "markdown", + "id": "2d267a5a", + "metadata": {}, + "source": [ + "Создание объекта" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fcb8e837", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект Matroskin класса CatClass\n", + "# Matroskin = CatClass()\n", + "\n", + "# проверим тип данных созданной переменной\n", + "# type(Matroskin)" + ] + }, + { + "cell_type": "markdown", + "id": "dcfa9840", + "metadata": {}, + "source": [ + "Атрибуты класса" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8f94eb0a", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь создадим класс CatClass\n", + "\n", + "\n", + "# class CatClass:\n", + "\n", + "# метод .__init__() на этот раз принимает еще и параметр color\n", + "# def __init__(self, color):\n", + "\n", + "# этот параметр будет записан в переменную атрибута self.color\n", + "# self.color = color\n", + "\n", + "# значение атрибута type_ задается внутри класса\n", + "# self.type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "b38697f3", + "metadata": {}, + "outputs": [], + "source": [ + "# повторно создадим объект класса CatClass, передав ему параметр цвета шерсти\n", + "# Matroskin = CatClass(\"gray\")\n", + "\n", + "# и выведем атрибуты класса\n", + "# Matroskin.color, Matroskin.type_" + ] + }, + { + "cell_type": "markdown", + "id": "79338cc6", + "metadata": {}, + "source": [ + "Методы класса" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bfec9fe5", + "metadata": {}, + "outputs": [], + "source": [ + "# перепишем класс CatClass\n", + "\n", + "\n", + "# class CatClass:\n", + "\n", + "# метод .__init__() и атрибуты оставим без изменений\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# self.type_ = \"cat\"\n", + "\n", + "# однако добавим метод, который позволит коту мяукать\n", + "# def meow(self):\n", + "# for i in range(3):\n", + "# print(\"Мяу\")\n", + "\n", + "# и метод .info() для вывода информации об объекте\n", + "# def info(self):\n", + "# print(self.color, self.type_)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "94a3fdd5", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект\n", + "# Matroskin = CatClass(\"gray\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a9e69c5a", + "metadata": {}, + "outputs": [], + "source": [ + "# применим метод .meow()\n", + "# Matroskin.meow()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "cebffcc5", + "metadata": {}, + "outputs": [], + "source": [ + "# и метод .info()\n", + "# Matroskin.info()" + ] + }, + { + "cell_type": "markdown", + "id": "60a933e8", + "metadata": {}, + "source": [ + "Принципы ООП" + ] + }, + { + "cell_type": "markdown", + "id": "e8f36511", + "metadata": {}, + "source": [ + "Инкапсуляция" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "78dcee29", + "metadata": {}, + "outputs": [], + "source": [ + "# изменим атрибут type_ объекта Matroskin на dog\n", + "# Matroskin.type_ = \"dog\"\n", + "\n", + "# выведем этот атрибут\n", + "# Matroskin.type_" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ef286f65", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# символ подчеркивания ПЕРЕД названием атрибута указывает,\n", + "# что это частный атрибут и изменять его не стоит\n", + "# self._type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "5c419338", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь создадим объект класса CatClass\n", + "# Matroskin = CatClass(\"gray\")\n", + "\n", + "# и изменим значение атрибута _type_\n", + "# Matroskin._type_ = \"dog\"\n", + "# Matroskin._type_" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9470d6f0", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# символ двойного подчеркивания предотвратит доступ извне\n", + "# self.__type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "eed6e6c0", + "metadata": {}, + "outputs": [], + "source": [ + "# при попытке вызова такого атрибута Питон выдаст ошибку\n", + "# Matroskin = CatClass(\"gray\")\n", + "# Matroskin.__type_" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f64fc8e4", + "metadata": {}, + "outputs": [], + "source": [ + "# поставим _CatClass перед __type_\n", + "# Matroskin._CatClass__type_ = \"dog\"\n", + "\n", + "# к сожалению, значение атрибута изменится\n", + "# Matroskin._CatClass__type_" + ] + }, + { + "cell_type": "markdown", + "id": "e128f823", + "metadata": {}, + "source": [ + "Наследование классов" + ] + }, + { + "cell_type": "markdown", + "id": "84d20b74", + "metadata": {}, + "source": [ + "Создание родительского класса и класса-потомка" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d702c4b6", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс Animal\n", + "\n", + "\n", + "# class Animal:\n", + "\n", + "# пропишем метод .__init__() с двумя параметрами: вес (кг) и длина (см)\n", + "# def __init__(self, weight, length):\n", + "\n", + "# поместим аргументы этих параметров в соответствующие переменные\n", + "# self.weight = weight\n", + "# self.length = length\n", + "\n", + "# объявим методы .eat()\n", + "# def eat(self):\n", + "# print(\"Eating\")\n", + "\n", + "# и .sleep()\n", + "# def sleep(self):\n", + "# print(\"Sleeping\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "19c69932", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс Bird\n", + "# родительский класс Animal пропишем в скобках\n", + "\n", + "\n", + "# class Bird(Animal):\n", + "\n", + "# внутри класса Bird объявим новый метод .move()\n", + "# def move(self):\n", + "\n", + "# для птиц .move() будет означать \"летать\"\n", + "# print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e3ecbfd7", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект pigeon и передадим ему значения веса и длины\n", + "# pigeon = Bird(0.3, 30)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "46de9185", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на унаследованные у класса Animal атрибуты\n", + "# pigeon.weight, pigeon.length" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8241dedf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eating\n" + ] + } + ], + "source": [ + "# и методы\n", + "# pigeon.eat()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2633addf", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь вызовем метод, свойственный только классу Bird\n", + "# pigeon.move()" + ] + }, + { + "cell_type": "markdown", + "id": "87c11fed", + "metadata": {}, + "source": [ + "Функция super()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "a0187883", + "metadata": {}, + "outputs": [], + "source": [ + "# снова создадим класс Bird\n", + "\n", + "\n", + "# class Bird(Animal):\n", + "\n", + "# в метод .__init__() добавим параметр скорости полета (км/ч)\n", + "# def __init__(self, weight, length, flying_speed):\n", + "\n", + "# с помощью функции super() вызовем метод .__init__() родительского класса Animal\n", + "# super().__init__(weight, length)\n", + "# self.flying_speed = flying_speed\n", + "\n", + "# вновь пропишем метод .move()\n", + "# def move(self):\n", + "# print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "e80b4028", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь создадим объект pigeon класса Bird, но уже с тремя параметрами\n", + "# pigeon = Bird(0.3, 30, 100)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a8832158", + "metadata": {}, + "outputs": [], + "source": [ + "# вызовем как унаследованные, так и собственные атрибуты класса Bird\n", + "# pigeon.weight, pigeon.length, pigeon.flying_speed" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "60e0e500", + "metadata": {}, + "outputs": [], + "source": [ + "# вызовем унаследованный метод .sleep()\n", + "# pigeon.sleep()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "53fe7b35", + "metadata": {}, + "outputs": [], + "source": [ + "# и собственный метод .move()\n", + "# pigeon.move()" + ] + }, + { + "cell_type": "markdown", + "id": "3afdc5a2", + "metadata": {}, + "source": [ + "Переопределение класса" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "e8b77857", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим подкласс Flightless класса Bird\n", + "\n", + "\n", + "# class Flightless(Bird):\n", + "\n", + "# метод .__init__() этого подкласса \"стирает\" .__init__() родительского класса\n", + "# def __init__(self, running_speed):\n", + "\n", + "# таким образом, у нас остается только один атрибут\n", + "# self.running_speed = running_speed\n", + "\n", + "# кроме того, результатом метода .move() будет 'Running'\n", + "# def move(self):\n", + "# print(\"Running\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e2ab3f4", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект ostrich класса Flightless\n", + "# ostrich = Flightless(60)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "548cc353", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на значение атрбута скорости\n", + "# ostrich.running_speed" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5a7186b7", + "metadata": {}, + "outputs": [], + "source": [ + "# и проверим метод .move()\n", + "# ostrich.move()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "db1b0de0", + "metadata": {}, + "outputs": [], + "source": [ + "# подкласс Flightless сохранил методы всех родительских классов\n", + "# ostrich.eat()" + ] + }, + { + "cell_type": "markdown", + "id": "d5dc20ca", + "metadata": {}, + "source": [ + "Множественное наследование" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf3e60ab", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим родительский класс Fish\n", + "\n", + "\n", + "# class Fish:\n", + "\n", + "# и метод .swim()\n", + "# def swim(self):\n", + "# print(\"Swimming\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "398e9da1", + "metadata": {}, + "outputs": [], + "source": [ + "# и еще один родительский класс Bird\n", + "\n", + "\n", + "# class Bird:\n", + "\n", + "# и метод .fly()\n", + "# def fly(self):\n", + "# print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fb7c19b", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь создадим класс-потомок этих двух классов\n", + "\n", + "\n", + "# class SwimmingBird(Bird, Fish):\n", + "# pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c9546b6", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект duck класса SwimmingBird\n", + "# duck = SwimmingBird()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f876572", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Flying\n" + ] + } + ], + "source": [ + "# как мы видим утка умеет как летать,\n", + "# duck.fly()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4afa38a4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Swimming\n" + ] + } + ], + "source": [ + "# так и плавать\n", + "# duck.swim()" + ] + }, + { + "cell_type": "markdown", + "id": "5d6439e6", + "metadata": {}, + "source": [ + "Полиморфизм" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7667b8f1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# для чисел '+' является оператором сложения\n", + "# 2 + 2" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "30320625", + "metadata": {}, + "outputs": [], + "source": [ + "# для строк - оператором объединения\n", + "# \"классы\" + \" и \" + \"объекты\"" + ] + }, + { + "cell_type": "markdown", + "id": "24dff1c1", + "metadata": {}, + "source": [ + "1 Полиморфизм функций" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4562a522", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "26" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# функцию len() можно применить к строке\n", + "# len(\"Программирование на Питоне\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "638a2cf8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# кроме того, она способна работать со списком\n", + "# len([\"Программирование\", \"на\", \"Питоне\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe867c95", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# словарем\n", + "# len({0: \"Программирование\", 1: \"на\", 2: \"Питоне\"})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a04ded7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# len(np.array([1, 2, 3]))" + ] + }, + { + "cell_type": "markdown", + "id": "3e8966cb", + "metadata": {}, + "source": [ + "2 Полиморфизм классов" + ] + }, + { + "cell_type": "markdown", + "id": "e0b953f1", + "metadata": {}, + "source": [ + "Создадим атрибуты с одинаковыми объектами и методами" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f3beb6a", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс котов\n", + "\n", + "\n", + "# class CatClass:\n", + "\n", + "# определим атрибуты клички, типа и цвета шерсти\n", + "# def __init__(self, name, color):\n", + "# self.name = name\n", + "# self._type_ = \"кот\"\n", + "# self.color = color\n", + "\n", + "# создадим метод .info() для вывода этих атрибутов\n", + "# def info(self):\n", + "# print(f\"Меня зовут {self.name}, я {self._type_},\n", + "# цвет моей шерсти {self.color}\")\n", + "\n", + "# и метод .sound(), показывающий, что коты умеют мяукать\n", + "# def sound(self):\n", + "# print(\"Я умею мяукать\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ed60438", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс собак\n", + "\n", + "\n", + "# class DogClass:\n", + "\n", + "# с такими же атрибутами\n", + "# def __init__(self, name, color):\n", + "# self.name = name\n", + "# self._type_ = \"пес\"\n", + "# self.color = color\n", + "\n", + "# и методами\n", + "# def info(self):\n", + "# print(f\"Меня зовут {self.name}, я {self._type_}, цвет моей шерсти {self.color}\")\n", + "\n", + "# хотя, обратите внимание, действия внутри методов отличаются\n", + "# def sound(self):\n", + "# print(\"Я умею лаять\")" + ] + }, + { + "cell_type": "markdown", + "id": "c1589513", + "metadata": {}, + "source": [ + "Создадим объекты этих классов" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "6b230bd7", + "metadata": {}, + "outputs": [], + "source": [ + "# cat = CatClass(\"Бегемот\", \"черный\")\n", + "# dog = DogClass(\"Барбос\", \"серый\")" + ] + }, + { + "cell_type": "markdown", + "id": "a0fe5f22", + "metadata": {}, + "source": [ + "В цикле for вызовем атрибуты и методы каждого из классов" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "4c1da800", + "metadata": {}, + "outputs": [], + "source": [ + "# for animal in (cat, dog):\n", + "# animal.info()\n", + "# animal.sound()\n", + "# print()" + ] + }, + { + "cell_type": "markdown", + "id": "d7465d5d", + "metadata": {}, + "source": [ + "Парадигмы программирования" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "efe2292a", + "metadata": {}, + "outputs": [], + "source": [ + "# patients = [\n", + "# {\"name\": \"Николай\", \"height\": 178},\n", + "# {\"name\": \"Иван\", \"height\": 182},\n", + "# {\"name\": \"Алексей\", \"height\": 190},\n", + "# ]" + ] + }, + { + "cell_type": "markdown", + "id": "19ca6c04", + "metadata": {}, + "source": [ + "Процедурное программирование " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31c5dc1a", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим переменные для общего роста и количества пациентов\n", + "# total, count = 0, 0\n", + "\n", + "# в цикле for пройдемся по пациентам (отдельным словарям)\n", + "# for patient in patients:\n", + "# достанем значение роста и прибавим к текущему значению переменной total\n", + "# total += patient[\"height\"]\n", + "# на каждой итерации будем увеличивать счетчик пациентов на один\n", + "# count += 1\n", + "\n", + "# разделим общий рост на количество пациентов,\n", + "# чтобы получить среднее значение\n", + "# total / count" + ] + }, + { + "cell_type": "markdown", + "id": "3bb60945", + "metadata": {}, + "source": [ + "Объектно-ориентированное программирование " + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "e61bb7fb", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс для работы с данными DataClass\n", + "\n", + "\n", + "# class DataClass:\n", + "\n", + "# при создании объекта будем передавать ему данные для анализа\n", + "# def __init__(self, data):\n", + "# self.data = data\n", + "\n", + "# кроме того, создадим метод для расчета среднего значения\n", + "# def count_average(self, metric):\n", + "\n", + "# параметр metric определит, по какому столбцу считать среднее\n", + "# self.metric = metric\n", + "\n", + "# объявим два частных атрибута\n", + "# self.__total = 0\n", + "# self.__count = 0\n", + "\n", + "# в цикле for пройдемся по списку словарей\n", + "# for item in self.data:\n", + "\n", + "# рассчитем общую сумму по указанному в metric\n", + "# значению каждого словаря\n", + "# self.__total += item[self.metric]\n", + "\n", + "# и количество таких записей\n", + "# self.__count += 1\n", + "\n", + "# разделим общую сумму показателя на количество записей\n", + "# return self.__total / self.__count" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "835a5842", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект класса DataClass и передадим ему данные о пациентах\n", + "# data_object = DataClass(patients)\n", + "\n", + "# вызовем метод .count_average() с метрикой 'height'\n", + "# data_object.count_average(\"height\")" + ] + }, + { + "cell_type": "markdown", + "id": "57f10081", + "metadata": {}, + "source": [ + "Функциональное программирование" + ] + }, + { + "cell_type": "markdown", + "id": "e2ce9c42", + "metadata": {}, + "source": [ + "Функция map()" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "c08ff8d7", + "metadata": {}, + "outputs": [], + "source": [ + "# lambda-функция достанет значение по ключу height\n", + "# функция map() применит lambda-функцию к каждому вложенному в patients словарю\n", + "# функция list() преобразует результат в список\n", + "# heights = list(map(lambda x: x[\"height\"], patients))\n", + "# heights" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "8163ae72", + "metadata": {}, + "outputs": [], + "source": [ + "# воспользуемся функциями sum() и len() для нахождения среднего значения\n", + "# sum(heights) / len(heights)" + ] + }, + { + "cell_type": "markdown", + "id": "eead0483", + "metadata": {}, + "source": [ + "Функция einsum()" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "7df0661c", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем два двумерных массива\n", + "# a = np.array([[0, 1, 2], [3, 4, 5]])\n", + "\n", + "# b = np.array([[5, 4], [3, 2], [1, 0]])" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "39bc2a9d", + "metadata": {}, + "outputs": [], + "source": [ + "# перемножим a и b по индексу j через функцию np.einsum()\n", + "# np.einsum(\"ij, jk -> ik\", a, b)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_7_classes.py b/python/makarov/chapter_7_classes.py new file mode 100644 index 00000000..398e33a1 --- /dev/null +++ b/python/makarov/chapter_7_classes.py @@ -0,0 +1,495 @@ +"""Классы.""" + +# Создание класса. + +# Создание класса и метод .__init__() + +# + +# создадим класс CatClass +# массивом Numpy и другими объектами +# import numpy as np + + +# class CatClass: + +# и пропишем метод .__init__() +# def __init__(self): +# pass +# - + +# Создание объекта + +# + +# создадим объект Matroskin класса CatClass +# Matroskin = CatClass() + +# проверим тип данных созданной переменной +# type(Matroskin) +# - + +# Атрибуты класса + +# + +# вновь создадим класс CatClass + + +# class CatClass: + +# метод .__init__() на этот раз принимает еще и параметр color +# def __init__(self, color): + +# этот параметр будет записан в переменную атрибута self.color +# self.color = color + +# значение атрибута type_ задается внутри класса +# self.type_ = "cat" + +# + +# повторно создадим объект класса CatClass, передав ему параметр цвета шерсти +# Matroskin = CatClass("gray") + +# и выведем атрибуты класса +# Matroskin.color, Matroskin.type_ +# - + +# Методы класса + +# + +# перепишем класс CatClass + + +# class CatClass: + +# метод .__init__() и атрибуты оставим без изменений +# def __init__(self, color): +# self.color = color +# self.type_ = "cat" + +# однако добавим метод, который позволит коту мяукать +# def meow(self): +# for i in range(3): +# print("Мяу") + +# и метод .info() для вывода информации об объекте +# def info(self): +# print(self.color, self.type_) + +# + +# создадим объект +# Matroskin = CatClass("gray") + +# + +# применим метод .meow() +# Matroskin.meow() + +# + +# и метод .info() +# Matroskin.info() +# - + +# Принципы ООП + +# Инкапсуляция + +# + +# изменим атрибут type_ объекта Matroskin на dog +# Matroskin.type_ = "dog" + +# выведем этот атрибут +# Matroskin.type_ + +# + +# class CatClass: + +# def __init__(self, color): +# self.color = color +# символ подчеркивания ПЕРЕД названием атрибута указывает, +# что это частный атрибут и изменять его не стоит +# self._type_ = "cat" + +# + +# вновь создадим объект класса CatClass +# Matroskin = CatClass("gray") + +# и изменим значение атрибута _type_ +# Matroskin._type_ = "dog" +# Matroskin._type_ + +# + +# class CatClass: + +# def __init__(self, color): +# self.color = color +# символ двойного подчеркивания предотвратит доступ извне +# self.__type_ = "cat" + +# + +# при попытке вызова такого атрибута Питон выдаст ошибку +# Matroskin = CatClass("gray") +# Matroskin.__type_ + +# + +# поставим _CatClass перед __type_ +# Matroskin._CatClass__type_ = "dog" + +# к сожалению, значение атрибута изменится +# Matroskin._CatClass__type_ +# - + +# Наследование классов + +# Создание родительского класса и класса-потомка + +# + +# создадим класс Animal + + +# class Animal: + +# пропишем метод .__init__() с двумя параметрами: вес (кг) и длина (см) +# def __init__(self, weight, length): + +# поместим аргументы этих параметров в соответствующие переменные +# self.weight = weight +# self.length = length + +# объявим методы .eat() +# def eat(self): +# print("Eating") + +# и .sleep() +# def sleep(self): +# print("Sleeping") + +# + +# создадим класс Bird +# родительский класс Animal пропишем в скобках + + +# class Bird(Animal): + +# внутри класса Bird объявим новый метод .move() +# def move(self): + +# для птиц .move() будет означать "летать" +# print("Flying") + +# + +# создадим объект pigeon и передадим ему значения веса и длины +# pigeon = Bird(0.3, 30) + +# + +# посмотрим на унаследованные у класса Animal атрибуты +# pigeon.weight, pigeon.length + +# + +# и методы +# pigeon.eat() + +# + +# теперь вызовем метод, свойственный только классу Bird +# pigeon.move() +# - + +# Функция super() + +# + +# снова создадим класс Bird + + +# class Bird(Animal): + +# в метод .__init__() добавим параметр скорости полета (км/ч) +# def __init__(self, weight, length, flying_speed): + +# с помощью функции super() вызовем метод .__init__() родительского класса Animal +# super().__init__(weight, length) +# self.flying_speed = flying_speed + +# вновь пропишем метод .move() +# def move(self): +# print("Flying") + +# + +# вновь создадим объект pigeon класса Bird, но уже с тремя параметрами +# pigeon = Bird(0.3, 30, 100) + +# + +# вызовем как унаследованные, так и собственные атрибуты класса Bird +# pigeon.weight, pigeon.length, pigeon.flying_speed + +# + +# вызовем унаследованный метод .sleep() +# pigeon.sleep() + +# + +# и собственный метод .move() +# pigeon.move() +# - + +# Переопределение класса + +# + +# создадим подкласс Flightless класса Bird + + +# class Flightless(Bird): + +# метод .__init__() этого подкласса "стирает" .__init__() родительского класса +# def __init__(self, running_speed): + +# таким образом, у нас остается только один атрибут +# self.running_speed = running_speed + +# кроме того, результатом метода .move() будет 'Running' +# def move(self): +# print("Running") + +# + +# создадим объект ostrich класса Flightless +# ostrich = Flightless(60) + +# + +# посмотрим на значение атрбута скорости +# ostrich.running_speed + +# + +# и проверим метод .move() +# ostrich.move() + +# + +# подкласс Flightless сохранил методы всех родительских классов +# ostrich.eat() +# - + +# Множественное наследование + +# + +# создадим родительский класс Fish + + +# class Fish: + +# и метод .swim() +# def swim(self): +# print("Swimming") + +# + +# и еще один родительский класс Bird + + +# class Bird: + +# и метод .fly() +# def fly(self): +# print("Flying") + +# + +# теперь создадим класс-потомок этих двух классов + + +# class SwimmingBird(Bird, Fish): +# pass + +# + +# создадим объект duck класса SwimmingBird +# duck = SwimmingBird() + +# + +# как мы видим утка умеет как летать, +# duck.fly() + +# + +# так и плавать +# duck.swim() +# - + +# Полиморфизм + +# + +# для чисел '+' является оператором сложения +# 2 + 2 + +# + +# для строк - оператором объединения +# "классы" + " и " + "объекты" +# - + +# 1 Полиморфизм функций + +# + +# функцию len() можно применить к строке +# len("Программирование на Питоне") + +# + +# кроме того, она способна работать со списком +# len(["Программирование", "на", "Питоне"]) + +# + +# словарем +# len({0: "Программирование", 1: "на", 2: "Питоне"}) + +# + +# len(np.array([1, 2, 3])) +# - + +# 2 Полиморфизм классов + +# Создадим атрибуты с одинаковыми объектами и методами + +# + +# создадим класс котов + + +# class CatClass: + +# определим атрибуты клички, типа и цвета шерсти +# def __init__(self, name, color): +# self.name = name +# self._type_ = "кот" +# self.color = color + +# создадим метод .info() для вывода этих атрибутов +# def info(self): +# print(f"Меня зовут {self.name}, я {self._type_}, +# цвет моей шерсти {self.color}") + +# и метод .sound(), показывающий, что коты умеют мяукать +# def sound(self): +# print("Я умею мяукать") + +# + +# создадим класс собак + + +# class DogClass: + +# с такими же атрибутами +# def __init__(self, name, color): +# self.name = name +# self._type_ = "пес" +# self.color = color + +# и методами +# def info(self): +# print(f"Меня зовут {self.name}, я {self._type_}, цвет моей шерсти {self.color}") + +# хотя, обратите внимание, действия внутри методов отличаются +# def sound(self): +# print("Я умею лаять") +# - + +# Создадим объекты этих классов + +# + +# cat = CatClass("Бегемот", "черный") +# dog = DogClass("Барбос", "серый") +# - + +# В цикле for вызовем атрибуты и методы каждого из классов + +# + +# for animal in (cat, dog): +# animal.info() +# animal.sound() +# print() +# - + +# Парадигмы программирования + +# + +# patients = [ +# {"name": "Николай", "height": 178}, +# {"name": "Иван", "height": 182}, +# {"name": "Алексей", "height": 190}, +# ] +# - + +# Процедурное программирование + +# + +# создадим переменные для общего роста и количества пациентов +# total, count = 0, 0 + +# в цикле for пройдемся по пациентам (отдельным словарям) +# for patient in patients: +# достанем значение роста и прибавим к текущему значению переменной total +# total += patient["height"] +# на каждой итерации будем увеличивать счетчик пациентов на один +# count += 1 + +# разделим общий рост на количество пациентов, +# чтобы получить среднее значение +# total / count +# - + +# Объектно-ориентированное программирование + +# + +# создадим класс для работы с данными DataClass + + +# class DataClass: + +# при создании объекта будем передавать ему данные для анализа +# def __init__(self, data): +# self.data = data + +# кроме того, создадим метод для расчета среднего значения +# def count_average(self, metric): + +# параметр metric определит, по какому столбцу считать среднее +# self.metric = metric + +# объявим два частных атрибута +# self.__total = 0 +# self.__count = 0 + +# в цикле for пройдемся по списку словарей +# for item in self.data: + +# рассчитем общую сумму по указанному в metric +# значению каждого словаря +# self.__total += item[self.metric] + +# и количество таких записей +# self.__count += 1 + +# разделим общую сумму показателя на количество записей +# return self.__total / self.__count + +# + +# создадим объект класса DataClass и передадим ему данные о пациентах +# data_object = DataClass(patients) + +# вызовем метод .count_average() с метрикой 'height' +# data_object.count_average("height") +# - + +# Функциональное программирование + +# Функция map() + +# + +# lambda-функция достанет значение по ключу height +# функция map() применит lambda-функцию к каждому вложенному в patients словарю +# функция list() преобразует результат в список +# heights = list(map(lambda x: x["height"], patients)) +# heights + +# + +# воспользуемся функциями sum() и len() для нахождения среднего значения +# sum(heights) / len(heights) +# - + +# Функция einsum() + +# + +# возьмем два двумерных массива +# a = np.array([[0, 1, 2], [3, 4, 5]]) + +# b = np.array([[5, 4], [3, 2], [1, 0]]) + +# + +# перемножим a и b по индексу j через функцию np.einsum() +# np.einsum("ij, jk -> ik", a, b) diff --git a/python/makarov/chapter_8_lists_tuples_sets.ipynb b/python/makarov/chapter_8_lists_tuples_sets.ipynb new file mode 100644 index 00000000..d10d1499 --- /dev/null +++ b/python/makarov/chapter_8_lists_tuples_sets.ipynb @@ -0,0 +1,1325 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "28cfce9e", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Списки, кортежи и множества.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "892e5038", + "metadata": {}, + "source": [ + "Списки. Основы работы со списками." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b4bfd57", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[] []\n" + ] + } + ], + "source": [ + "# пустой список можно создать через [] или функцию list()\n", + "# импортируем класс стеммера и создаем объект\n", + "# from nltk.stem import PorterStemmer\n", + "\n", + "# some_list_1 = []\n", + "# some_list_2 = list()\n", + "\n", + "# print(some_list_1, some_list_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "624b8a99", + "metadata": {}, + "outputs": [], + "source": [ + "# элементами списка могут, в частности, быть числа, строки, другие списки\n", + "# и словари\n", + "# number_three = [3, \"число три\", [\"число\", \"три\"], {\"число\": 3}]\n", + "# number_three" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6d0f2291", + "metadata": {}, + "outputs": [], + "source": [ + "# длина списка рассчитывается через функцию len()\n", + "# len(number_three)" + ] + }, + { + "cell_type": "markdown", + "id": "46a45528", + "metadata": {}, + "source": [ + "Индекс и срез списка " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "6873e1bf", + "metadata": {}, + "outputs": [], + "source": [ + "# у списка есть положительный и отрицательный индексы\n", + "# abc_list = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n", + "\n", + "# воспользуемся ими для вывода первого и последнего элементов\n", + "# print(abc_list[0], abc_list[-1])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6ec19992", + "metadata": {}, + "outputs": [], + "source": [ + "# при работе с вложенным списком\n", + "# salary_list = [[\"Анна\", 90000], [\"Игорь\", 85000], [\"Алексей\", 95000]]\n", + "\n", + "# мы вначале указываем индекс вложенного списка, а затем индекс элемента в нем\n", + "# salary_list[1][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4a3f1c34", + "metadata": {}, + "outputs": [], + "source": [ + "# индекс можно узнать с помощью метода .index()\n", + "# abc_list.index(\"c\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6516a4c0", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .index() можно применить и ко вложенному списку\n", + "# salary_list[0].index(90000)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3c5dc338", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим список с днями недели\n", + "# days_list = [\"Пн\", \"Вт\", \"Ср\", \"Чт\", \"Пт\", \"Сб\", \"Вс\"]\n", + "\n", + "# и выведем со второго по пятый элемент включительно\n", + "# days_list[1:5]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "5a8baf92", + "metadata": {}, + "outputs": [], + "source": [ + "# выведем каждый второй элемент в срезе с первого по пятый\n", + "# days_list[:5:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "80d6c64f", + "metadata": {}, + "outputs": [], + "source": [ + "# проверим есть ли \"Пн\" в списке\n", + "# \"Пн\" in days_list" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7bfbaac6", + "metadata": {}, + "outputs": [], + "source": [ + "# если \"Вт\" есть в списке\n", + "# if \"Вт\" in days_list:\n", + "\n", + "# выведем сообщение\n", + "# print(\"Такое слово есть\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "49cba7eb", + "metadata": {}, + "outputs": [], + "source": [ + "# students = [\"Svetlana\", \"Andrey\", \"Luda\", \"Ruslan\", \"Dima\"]\n", + "# if \"Ruslan\" in students:\n", + "# print(\"He is a student\")\n", + "# else:\n", + "# print(\"none\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "16705c27", + "metadata": {}, + "outputs": [], + "source": [ + "# del students[3]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5ba895b7", + "metadata": {}, + "outputs": [], + "source": [ + "# print(students)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "47f970fe", + "metadata": {}, + "outputs": [], + "source": [ + "# students.pop(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "4ba0bf88", + "metadata": {}, + "outputs": [], + "source": [ + "# students" + ] + }, + { + "cell_type": "markdown", + "id": "ad095812", + "metadata": {}, + "source": [ + "Добавление, замена и удаление элементов списка" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "dd74361f", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим список\n", + "# weekdays = [\"Понедельник\", \"Вторник\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e28f83fa", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим один элемент в конец списка с помощью метода .append()\n", + "# weekdays.append(\"Четверг\")\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "10159a02", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим элемент в определенное место в списке через желаемый индекс этого элемента\n", + "# weekdays.insert(2, \"Среда\")\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "49833bdd", + "metadata": {}, + "outputs": [], + "source": [ + "# изменим четвертый элемент в списке\n", + "# weekdays[3] = \"Пятница\"\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "ee89b7ce", + "metadata": {}, + "outputs": [], + "source": [ + "# удалим элемент по его значению\n", + "# weekdays.remove(\"Пятница\")\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "aa9b87e4", + "metadata": {}, + "outputs": [], + "source": [ + "# удалим элемент по его индексу через ключевое слово del\n", + "# del weekdays[2]\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a0497cc4", + "metadata": {}, + "outputs": [], + "source": [ + "# сделаем то же самое с помощью метода .pop()\n", + "# этот метод выводит удаляемый элемент\n", + "# weekdays.pop(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "ca17b5d6", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим, что осталось в нашем списке\n", + "# weekdays" + ] + }, + { + "cell_type": "markdown", + "id": "c9ff07a1", + "metadata": {}, + "source": [ + "Сложение списков" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "01da2f75", + "metadata": {}, + "outputs": [], + "source": [ + "# соединить два списка можно с помощью метода .extend()\n", + "# more_weekdays = [\"Вторник\", \"Среда\", \"Четверг\", \"Пятница\"]\n", + "\n", + "# weekdays.extend(more_weekdays)\n", + "# weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "251e625a", + "metadata": {}, + "outputs": [], + "source": [ + "# weekend = [\"Суббота\", \"Воскресенье\"]\n", + "\n", + "# или просто сложив два списка\n", + "# print(weekdays + weekend)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "107722be", + "metadata": {}, + "outputs": [], + "source": [ + "# иногда бывает полезно \"размножить\" элементы списка\n", + "# [\"Понедельник\"] * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "a5aea70e", + "metadata": {}, + "outputs": [], + "source": [ + "# такие \"произведения\" также можно складывать\n", + "# [\"Понедельник\"] * 2 + [\"Вторник\"] * 2" + ] + }, + { + "cell_type": "markdown", + "id": "5f22bc89", + "metadata": {}, + "source": [ + "Распаковка списков" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ca5bade8", + "metadata": {}, + "outputs": [], + "source": [ + "# дан список\n", + "# week = [\n", + "# \"Понедельник\",\n", + "# \"Вторник\",\n", + "# \"Среда\",\n", + "# \"Четверг\",\n", + "# \"Пятница\",\n", + "# \"Суббота\",\n", + "# \"Воскресенье\",\n", + "# ]" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "11f1e53b", + "metadata": {}, + "outputs": [], + "source": [ + "# указав индекс элемента, его можно записать в переменную\n", + "# Mon = week[0]\n", + "# Mon" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "13c02ae4", + "metadata": {}, + "outputs": [], + "source": [ + "# срез можно поместить в несколько переменных\n", + "# Mon, Tue, Wed = week[:3]\n", + "\n", + "# важно, чтобы количество элементов среза было равно количеству переменных\n", + "# Mon, Tue, Wed" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "61e7e480", + "metadata": {}, + "outputs": [], + "source": [ + "# можно выделить первый элемент, а остальные поместить\n", + "# в переменную со звездочкой\n", + "# Mon, *_ = week\n", + "# Mon" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "a2848f1c", + "metadata": {}, + "outputs": [], + "source": [ + "# также можно поступить, например, с первым и последним элементом\n", + "# Mon, *days, Sun = week\n", + "# Mon, Sun" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "0ea42515", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим, какие элементы остались в переменной со звездочкой\n", + "# days" + ] + }, + { + "cell_type": "markdown", + "id": "335bcb58", + "metadata": {}, + "source": [ + "Сортировка списков" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "c1300e5b", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем список чисел\n", + "# nums = [25, 10, 30, 20, 5, 15]" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "f6538f86", + "metadata": {}, + "outputs": [], + "source": [ + "# и отсортируем с помощью функции sorted(), результат выводится сразу\n", + "# sorted(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "b48403a8", + "metadata": {}, + "outputs": [], + "source": [ + "# исходный список при этом не изменился\n", + "# nums" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "e27b3a07", + "metadata": {}, + "outputs": [], + "source": [ + "# если поместить результат в переменную, изменения сохранятся\n", + "# sorted_nums = sorted(nums)\n", + "# sorted_nums" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "5f01339c", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .sort() сохраняет результат, но не выводит его сразу\n", + "# reverse = True задает сортировку по убыванию\n", + "# nums.sort(reverse=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "6a280153", + "metadata": {}, + "outputs": [], + "source": [ + "# выведем результат\n", + "# nums" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "f47c1904", + "metadata": {}, + "outputs": [], + "source": [ + "# set_of_numbers = [12, 15, 54, 98, 3, 14, 47, 19, 89, 27, 14, 11]\n", + "# set_of_numbers.sort()\n", + "# set_of_numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "6fb369d4", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .reverse() задает обратный порядок, сохраняет, но не выводит результат\n", + "# nums.reverse()\n", + "\n", + "# его также нужно вывести отдельно\n", + "# nums" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "76797be7", + "metadata": {}, + "outputs": [], + "source": [ + "# функция reversed() возвращает итератор\n", + "# reversed(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "3b403e4f", + "metadata": {}, + "outputs": [], + "source": [ + "# вывести результат можно с помощью функции list()\n", + "# list(reversed(nums))" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "f221f56a", + "metadata": {}, + "outputs": [], + "source": [ + "# результат при этом не сохраняется\n", + "# nums" + ] + }, + { + "cell_type": "markdown", + "id": "e6b568f8", + "metadata": {}, + "source": [ + "Преобразование списка в строку" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "e70e0a6f", + "metadata": {}, + "outputs": [], + "source": [ + "# дан список из строковых элементов\n", + "# str_list = [\"P\", \"y\", \"t\", \"h\", \"o\", \"n\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "bae77fc5", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью метода .join() можно соединить все элементы\n", + "# joined_str = \"\".join(str_list)\n", + "# joined_str" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "3de9f5c7", + "metadata": {}, + "outputs": [], + "source": [ + "# если в кавычках ничего не указывать, элементы просто соединятся, но можно указать любой другой элемент\n", + "# joined_str_ = \"_\".join(str_list)\n", + "# joined_str_" + ] + }, + { + "cell_type": "markdown", + "id": "65a0c102", + "metadata": {}, + "source": [ + "Арифметика в списках " + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "32c7ddc4", + "metadata": {}, + "outputs": [], + "source": [ + "# дан список чисел\n", + "# nums_ = [3, 2, 1, 4, 5, 12, 3, 3, 7, 9, 11, 15]" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "85004bcc", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью метода .count() мы можем посчитать частоту вхождения элемента в список\n", + "# nums_.count(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "27edbdef", + "metadata": {}, + "outputs": [], + "source": [ + "# кроме того мы можем найти минимальное и максимальное\n", + "# значения и сумму элементов\n", + "# print(min(nums_), max(nums_), sum(nums_))" + ] + }, + { + "cell_type": "markdown", + "id": "72c1b53a", + "metadata": {}, + "source": [ + "List comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "d44bb2b4", + "metadata": {}, + "outputs": [], + "source": [ + "# дан список имен\n", + "# оставим имена, начинающиеся с буквы \"А\"\n", + "# names = [\"Тахир\", \"Тимур\", \"Тигран\", \"Борис\", \"Виктор\", \"Геннадий\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "cd3deb30", + "metadata": {}, + "outputs": [], + "source": [ + "# вначале решим эту задачу с помощью цикла for\n", + "\n", + "# создадим пустой список\n", + "# a_names = []\n", + "\n", + "# пройдемся по исходному списку в цикле for\n", + "# for name in names:\n", + "\n", + "# с помощью метода .startswith() проверим, начинается ли слово с \"А\"\n", + "# if name.startswith(\"Т\"):\n", + "\n", + "# если да, добавим в новый список\n", + "# a_names.append(name)\n", + "\n", + "# выведем результат\n", + "# a_names" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "1b260376", + "metadata": {}, + "outputs": [], + "source": [ + "# эту же задачу можно решить через list comprehension\n", + "# по сути мы пишем: \"что сделать, пока есть элемент в списке, при каком условии\"\n", + "# a_names = [name for name in names if name.startswith(\"Т\")]\n", + "# a_names" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "4535212a", + "metadata": {}, + "outputs": [], + "source": [ + "# переведем все буквы в строчные, условие здесь не нужно\n", + "# lower_names = [name.lower() for name in names]\n", + "# lower_names" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "5165d9c8", + "metadata": {}, + "outputs": [], + "source": [ + "# схема условия if-else немного отличается\n", + "# оставляем имя, если это не Виктор, если Виктор - заменяем на Вадим\n", + "# replace_name = [name if name != \"Виктор\" else \"Вадим\" for name in names]\n", + "# replace_name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4125c339", + "metadata": {}, + "outputs": [], + "source": [ + "# на занятии по обработке естественного языка с помощью list comprehension\n", + "# мы применили стеммер Портера к списку слов\n", + "# lemmatized = [\n", + "# \"paris\",\n", + "# \"visited\",\n", + "# \"lot\",\n", + "# \"museum\",\n", + "# \"first\",\n", + "# \"went\",\n", + "# \"louvre\",\n", + "# \"largest\",\n", + "# \"art\",\n", + "# \"museum\",\n", + "# \"world\",\n", + "# \"always\",\n", + "# \"interested\",\n", + "# \"art\",\n", + "# \"spent\",\n", + "# \"many\",\n", + "# \"hour\",\n", + "# \"museum\",\n", + "# \"enormous\",\n", + "# \"week\",\n", + "# \"would\",\n", + "# \"enough\",\n", + "# ]\n", + "\n", + "\n", + "# porter = PorterStemmer()\n", + "\n", + "# применяем стеммер к элементу s, пока есть элементы s в списке lemmatized\n", + "# stemmed_p = [porter.stem(s) for s in lemmatized]\n", + "# print(stemmed_p)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ea91c3", + "metadata": {}, + "source": [ + "Кортежи\n", + "Основы работы с кортежами" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "1cf986c4", + "metadata": {}, + "outputs": [], + "source": [ + "# пустой кортеж можно создать с помощью пустых\n", + "# круглых скобок () или функции tuple()\n", + "# tuple_1, tuple_2 = (), tuple()\n", + "# print(tuple_1, tuple_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "d6d91874", + "metadata": {}, + "outputs": [], + "source": [ + "# в кортеже элементы упорядочены, а значит есть индекс\n", + "# letters = (\"a\", \"b\", \"c\")\n", + "# letters[0]" + ] + }, + { + "cell_type": "markdown", + "id": "417da14d", + "metadata": {}, + "source": [ + "В кортеже нельзя изменить элемент, как мы делали в списке." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "15149f18", + "metadata": {}, + "outputs": [], + "source": [ + "# для изменения элемента кортеж вначале нужно\n", + "# преобразовать в список\n", + "# letters = list(letters)\n", + "# letters[0] = \"d\"\n", + "# letters" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "844c7345", + "metadata": {}, + "outputs": [], + "source": [ + "# tuple_my = (11, 15, 17, 19, 23, 25, 29)\n", + "# tuple_my = list(tuple_my)\n", + "# tuple_my[5] = 31\n", + "# tuple_my" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "d5c7c9de", + "metadata": {}, + "outputs": [], + "source": [ + "# кортеж из одного элемента можно создать с помощью\n", + "# запятой\n", + "# let_a = (\"a\",)\n", + "# type(let_a)" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "28a34c88", + "metadata": {}, + "outputs": [], + "source": [ + "# если запятую не указывать, получится строка\n", + "# let_a = \"a\"\n", + "# type(let_a)" + ] + }, + { + "cell_type": "markdown", + "id": "f64e734a", + "metadata": {}, + "source": [ + "Функция enumerate()" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "fb315f07", + "metadata": {}, + "outputs": [], + "source": [ + "# companies = [\"Microsoft\", \"Apple\", \"Tesla\"]\n", + "\n", + "# если записать результат функции enumerate() в одну переменную,\n", + "# for company in enumerate(companies):\n", + "\n", + "# то мы получим кортежи\n", + "# print(company, type(company))" + ] + }, + { + "cell_type": "markdown", + "id": "c263124a", + "metadata": {}, + "source": [ + "Просмотр элементов словаря" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "6bef2ca1", + "metadata": {}, + "outputs": [], + "source": [ + "# shopping_dict = {\"onion\": 10, \"potato\": 12, \"apple\": 24, \"orange\": 30}" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "4b0dff3c", + "metadata": {}, + "outputs": [], + "source": [ + "# то же самое со словарем и методом .items()\n", + "# for item in shopping_dict.items():\n", + "# print(item)" + ] + }, + { + "cell_type": "markdown", + "id": "ee36e6a0", + "metadata": {}, + "source": [ + "Распаковка кортежей " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d917be8e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n" + ] + } + ], + "source": [ + "# как и список, кортеж можно распаковать в несколько переменных\n", + "# a, b, c = (\"a\", \"b\", \"c\")\n", + "# print(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "293a7da7", + "metadata": {}, + "outputs": [], + "source": [ + "# companies = [\"Microsoft\", \"Apple\", \"Tesla\"]\n", + "\n", + "# распаковку в две переменные с функцией enumerate() мы делать уже умеем\n", + "# for i, company in enumerate(companies):\n", + "# print(i, company)" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "727b4d1e", + "metadata": {}, + "outputs": [], + "source": [ + "# то же самое с ключами и значениями словаря\n", + "# for k, v in shopping_dict.items():\n", + "# print(k, v)" + ] + }, + { + "cell_type": "markdown", + "id": "6627f015", + "metadata": {}, + "source": [ + "Функция zip()" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "6e41429b", + "metadata": {}, + "outputs": [], + "source": [ + "# если есть два и более списка\n", + "# names = [\"Артем\", \"Антон\", \"Александр\", \"Борис\", \"Виктор\", \"Геннадий\"]\n", + "# income = [97000, 110000, 95000, 84000, 140000, 120000]\n", + "# age_of_workers = [27, 30, 25, 47, 52, 36]\n", + "\n", + "# функция zip() соединит первые элементы списков, вторые элементы списков и т.д.\n", + "# zip(names, income, age_of_workers)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "9c8df4d6", + "metadata": {}, + "outputs": [], + "source": [ + "# для вывода результата нужно передать zip-объект в функцию list()\n", + "# на выходе мы получим список из кортежей\n", + "# list(zip(names, income, age_of_workers))" + ] + }, + { + "cell_type": "markdown", + "id": "f60c3bb1", + "metadata": {}, + "source": [ + "Множества" + ] + }, + { + "cell_type": "markdown", + "id": "384c4031", + "metadata": {}, + "source": [ + "Создание множества" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "ffbf2333", + "metadata": {}, + "outputs": [], + "source": [ + "# пустое множество задается через функцию set()\n", + "# set_1 = set()\n", + "\n", + "# непустое множество задается через функцию set() и список элементов\n", + "# set_2 = {\"a\", \"b\", \"c\", \"c\"}\n", + "\n", + "# или путем перечисления элементов в фигурных скобках {}\n", + "# set_3 = {\"a\", \"b\", \"c\", \"c\"}\n", + "\n", + "# множество содержит только уникальные элементы, поэтому дубликаты удаляются\n", + "# print(set_1, set_2, set_3)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "e58805f0", + "metadata": {}, + "outputs": [], + "source": [ + "# создать множество через пустые фигурные скобки нельзя\n", + "# not_a_set = {}\n", + "\n", + "# так создается словарь\n", + "# type(not_a_set)" + ] + }, + { + "cell_type": "markdown", + "id": "d2d54077", + "metadata": {}, + "source": [ + "Добавление и удаление элементов" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "0ea2ad2d", + "metadata": {}, + "outputs": [], + "source": [ + "# предположим, что мы хотим создать множество делителей числа 24\n", + "# factors = {1, 2, 3, 4, 6, 8, 12, 24}\n", + "# добавим число 9 методом .add()\n", + "# factors.add(9)\n", + "# factors" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "7c38df77", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим числа 7 и 11 методом .update()\n", + "# factors.update([7, 11])\n", + "# factors" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "ebe9c17c", + "metadata": {}, + "outputs": [], + "source": [ + "# удалить число можно методом .remove()\n", + "# factors.remove(7)\n", + "# factors" + ] + }, + { + "cell_type": "markdown", + "id": "0dd1f02e", + "metadata": {}, + "source": [ + "Теория множеств в Питоне" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "1123141c", + "metadata": {}, + "outputs": [], + "source": [ + "# два множества равны, если содержат одинаковые\n", + "# элементы, при этом порядок элементов не важен\n", + "# {\"a\", \"b\", \"c\"} == {\"c\", \"b\", \"a\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "4297e537", + "metadata": {}, + "outputs": [], + "source": [ + "# выведем мощность множества с помощью функции len()\n", + "# len({\"a\", \"b\", \"c\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "634e2de3", + "metadata": {}, + "outputs": [], + "source": [ + "# проверим, содержится ли элемент во множестве\n", + "# \"a\" in {\"a\", \"b\", \"c\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "faeb49f7", + "metadata": {}, + "outputs": [], + "source": [ + "# возможна и обратная операция\n", + "# \"a\" not in {\"a\", \"b\", \"c\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "2a3f7db9", + "metadata": {}, + "outputs": [], + "source": [ + "# проверим является ли А подмножеством В\n", + "# set_A = {\"a\", \"b\", \"c\"}\n", + "# set_B = {\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"}\n", + "\n", + "# set_A.issubset(set_B)" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "21e361ce", + "metadata": {}, + "outputs": [], + "source": [ + "# проверим является ли B надмножеством А\n", + "# set_B.issuperset(set_A)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "29c00fcc", + "metadata": {}, + "outputs": [], + "source": [ + "# даны участники команд по обработке естественного языка (nlp)\n", + "# и компьютерному зрению (cv)\n", + "# nlp = {\"Анна\", \"Николай\", \"Павел\", \"Оксана\"}\n", + "# cv = {\"Николай\", \"Евгений\", \"Ольга\", \"Оксана\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "24dbb9ae", + "metadata": {}, + "outputs": [], + "source": [ + "# найдем тех, кто работает или в nlp, или в cv, или в обеих командах\n", + "\n", + "# можно использовать метод .union()\n", + "# print(nlp.union(cv))\n", + "\n", + "# или символ |\n", + "# print(nlp | cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "f22897ec", + "metadata": {}, + "outputs": [], + "source": [ + "# найдем пересечение множеств, то есть тех, кто работает и в nlp, и в cv\n", + "# print(nlp.intersection(cv))\n", + "# print(nlp & cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "id": "7c590296", + "metadata": {}, + "outputs": [], + "source": [ + "# выведем тех, кто работает только в nlp, но не в cv или cv и nlp одновременно\n", + "# print(nlp.difference(cv))\n", + "# print(nlp - cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "id": "1d32a2e8", + "metadata": {}, + "outputs": [], + "source": [ + "# найдем тех, кто работает или в cv, или в nlp, но не\n", + "# в обеих областях одновременно\n", + "# print(nlp.symmetric_difference(cv))\n", + "# print(nlp ^ cv)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_8_lists_tuples_sets.py b/python/makarov/chapter_8_lists_tuples_sets.py new file mode 100644 index 00000000..d32aa7d1 --- /dev/null +++ b/python/makarov/chapter_8_lists_tuples_sets.py @@ -0,0 +1,569 @@ +"""Списки, кортежи и множества.""" + +# Списки. Основы работы со списками. + +# + +# пустой список можно создать через [] или функцию list() +# импортируем класс стеммера и создаем объект +# from nltk.stem import PorterStemmer + +# some_list_1 = [] +# some_list_2 = list() + +# print(some_list_1, some_list_2) + +# + +# элементами списка могут, в частности, быть числа, строки, другие списки +# и словари +# number_three = [3, "число три", ["число", "три"], {"число": 3}] +# number_three + +# + +# длина списка рассчитывается через функцию len() +# len(number_three) +# - + +# Индекс и срез списка + +# + +# у списка есть положительный и отрицательный индексы +# abc_list = ["a", "b", "c", "d", "e"] + +# воспользуемся ими для вывода первого и последнего элементов +# print(abc_list[0], abc_list[-1]) + +# + +# при работе с вложенным списком +# salary_list = [["Анна", 90000], ["Игорь", 85000], ["Алексей", 95000]] + +# мы вначале указываем индекс вложенного списка, а затем индекс элемента в нем +# salary_list[1][0] + +# + +# индекс можно узнать с помощью метода .index() +# abc_list.index("c") + +# + +# метод .index() можно применить и ко вложенному списку +# salary_list[0].index(90000) + +# + +# создадим список с днями недели +# days_list = ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"] + +# и выведем со второго по пятый элемент включительно +# days_list[1:5] + +# + +# выведем каждый второй элемент в срезе с первого по пятый +# days_list[:5:2] + +# + +# проверим есть ли "Пн" в списке +# "Пн" in days_list + +# + +# если "Вт" есть в списке +# if "Вт" in days_list: + +# выведем сообщение +# print("Такое слово есть") + +# + +# students = ["Svetlana", "Andrey", "Luda", "Ruslan", "Dima"] +# if "Ruslan" in students: +# print("He is a student") +# else: +# print("none") + +# + +# del students[3] + +# + +# print(students) + +# + +# students.pop(0) + +# + +# students +# - + +# Добавление, замена и удаление элементов списка + +# + +# создадим список +# weekdays = ["Понедельник", "Вторник"] + +# + +# добавим один элемент в конец списка с помощью метода .append() +# weekdays.append("Четверг") +# weekdays + +# + +# добавим элемент в определенное место в списке через желаемый индекс этого элемента +# weekdays.insert(2, "Среда") +# weekdays + +# + +# изменим четвертый элемент в списке +# weekdays[3] = "Пятница" +# weekdays + +# + +# удалим элемент по его значению +# weekdays.remove("Пятница") +# weekdays + +# + +# удалим элемент по его индексу через ключевое слово del +# del weekdays[2] +# weekdays + +# + +# сделаем то же самое с помощью метода .pop() +# этот метод выводит удаляемый элемент +# weekdays.pop(1) + +# + +# посмотрим, что осталось в нашем списке +# weekdays +# - + +# Сложение списков + +# + +# соединить два списка можно с помощью метода .extend() +# more_weekdays = ["Вторник", "Среда", "Четверг", "Пятница"] + +# weekdays.extend(more_weekdays) +# weekdays + +# + +# weekend = ["Суббота", "Воскресенье"] + +# или просто сложив два списка +# print(weekdays + weekend) + +# + +# иногда бывает полезно "размножить" элементы списка +# ["Понедельник"] * 2 + +# + +# такие "произведения" также можно складывать +# ["Понедельник"] * 2 + ["Вторник"] * 2 +# - + +# Распаковка списков + +# + +# дан список +# week = [ +# "Понедельник", +# "Вторник", +# "Среда", +# "Четверг", +# "Пятница", +# "Суббота", +# "Воскресенье", +# ] + +# + +# указав индекс элемента, его можно записать в переменную +# Mon = week[0] +# Mon + +# + +# срез можно поместить в несколько переменных +# Mon, Tue, Wed = week[:3] + +# важно, чтобы количество элементов среза было равно количеству переменных +# Mon, Tue, Wed + +# + +# можно выделить первый элемент, а остальные поместить +# в переменную со звездочкой +# Mon, *_ = week +# Mon + +# + +# также можно поступить, например, с первым и последним элементом +# Mon, *days, Sun = week +# Mon, Sun + +# + +# посмотрим, какие элементы остались в переменной со звездочкой +# days +# - + +# Сортировка списков + +# + +# возьмем список чисел +# nums = [25, 10, 30, 20, 5, 15] + +# + +# и отсортируем с помощью функции sorted(), результат выводится сразу +# sorted(nums) + +# + +# исходный список при этом не изменился +# nums + +# + +# если поместить результат в переменную, изменения сохранятся +# sorted_nums = sorted(nums) +# sorted_nums + +# + +# метод .sort() сохраняет результат, но не выводит его сразу +# reverse = True задает сортировку по убыванию +# nums.sort(reverse=True) + +# + +# выведем результат +# nums + +# + +# set_of_numbers = [12, 15, 54, 98, 3, 14, 47, 19, 89, 27, 14, 11] +# set_of_numbers.sort() +# set_of_numbers + +# + +# метод .reverse() задает обратный порядок, сохраняет, но не выводит результат +# nums.reverse() + +# его также нужно вывести отдельно +# nums + +# + +# функция reversed() возвращает итератор +# reversed(nums) + +# + +# вывести результат можно с помощью функции list() +# list(reversed(nums)) + +# + +# результат при этом не сохраняется +# nums +# - + +# Преобразование списка в строку + +# + +# дан список из строковых элементов +# str_list = ["P", "y", "t", "h", "o", "n"] + +# + +# с помощью метода .join() можно соединить все элементы +# joined_str = "".join(str_list) +# joined_str + +# + +# если в кавычках ничего не указывать, элементы просто соединятся, но можно указать любой другой элемент +# joined_str_ = "_".join(str_list) +# joined_str_ +# - + +# Арифметика в списках + +# + +# дан список чисел +# nums_ = [3, 2, 1, 4, 5, 12, 3, 3, 7, 9, 11, 15] + +# + +# с помощью метода .count() мы можем посчитать частоту вхождения элемента в список +# nums_.count(3) + +# + +# кроме того мы можем найти минимальное и максимальное +# значения и сумму элементов +# print(min(nums_), max(nums_), sum(nums_)) +# - + +# List comprehension + +# + +# дан список имен +# оставим имена, начинающиеся с буквы "А" +# names = ["Тахир", "Тимур", "Тигран", "Борис", "Виктор", "Геннадий"] + +# + +# вначале решим эту задачу с помощью цикла for + +# создадим пустой список +# a_names = [] + +# пройдемся по исходному списку в цикле for +# for name in names: + +# с помощью метода .startswith() проверим, начинается ли слово с "А" +# if name.startswith("Т"): + +# если да, добавим в новый список +# a_names.append(name) + +# выведем результат +# a_names + +# + +# эту же задачу можно решить через list comprehension +# по сути мы пишем: "что сделать, пока есть элемент в списке, при каком условии" +# a_names = [name for name in names if name.startswith("Т")] +# a_names + +# + +# переведем все буквы в строчные, условие здесь не нужно +# lower_names = [name.lower() for name in names] +# lower_names + +# + +# схема условия if-else немного отличается +# оставляем имя, если это не Виктор, если Виктор - заменяем на Вадим +# replace_name = [name if name != "Виктор" else "Вадим" for name in names] +# replace_name + +# + +# на занятии по обработке естественного языка с помощью list comprehension +# мы применили стеммер Портера к списку слов +# lemmatized = [ +# "paris", +# "visited", +# "lot", +# "museum", +# "first", +# "went", +# "louvre", +# "largest", +# "art", +# "museum", +# "world", +# "always", +# "interested", +# "art", +# "spent", +# "many", +# "hour", +# "museum", +# "enormous", +# "week", +# "would", +# "enough", +# ] + + +# porter = PorterStemmer() + +# применяем стеммер к элементу s, пока есть элементы s в списке lemmatized +# stemmed_p = [porter.stem(s) for s in lemmatized] +# print(stemmed_p) +# - + +# Кортежи +# Основы работы с кортежами + +# + +# пустой кортеж можно создать с помощью пустых +# круглых скобок () или функции tuple() +# tuple_1, tuple_2 = (), tuple() +# print(tuple_1, tuple_2) + +# + +# в кортеже элементы упорядочены, а значит есть индекс +# letters = ("a", "b", "c") +# letters[0] +# - + +# В кортеже нельзя изменить элемент, как мы делали в списке. + +# + +# для изменения элемента кортеж вначале нужно +# преобразовать в список +# letters = list(letters) +# letters[0] = "d" +# letters + +# + +# tuple_my = (11, 15, 17, 19, 23, 25, 29) +# tuple_my = list(tuple_my) +# tuple_my[5] = 31 +# tuple_my + +# + +# кортеж из одного элемента можно создать с помощью +# запятой +# let_a = ("a",) +# type(let_a) + +# + +# если запятую не указывать, получится строка +# let_a = "a" +# type(let_a) +# - + +# Функция enumerate() + +# + +# companies = ["Microsoft", "Apple", "Tesla"] + +# если записать результат функции enumerate() в одну переменную, +# for company in enumerate(companies): + +# то мы получим кортежи +# print(company, type(company)) +# - + +# Просмотр элементов словаря + +# + +# shopping_dict = {"onion": 10, "potato": 12, "apple": 24, "orange": 30} + +# + +# то же самое со словарем и методом .items() +# for item in shopping_dict.items(): +# print(item) +# - + +# Распаковка кортежей + +# + +# как и список, кортеж можно распаковать в несколько переменных +# a, b, c = ("a", "b", "c") +# print(a) + +# + +# companies = ["Microsoft", "Apple", "Tesla"] + +# распаковку в две переменные с функцией enumerate() мы делать уже умеем +# for i, company in enumerate(companies): +# print(i, company) + +# + +# то же самое с ключами и значениями словаря +# for k, v in shopping_dict.items(): +# print(k, v) +# - + +# Функция zip() + +# + +# если есть два и более списка +# names = ["Артем", "Антон", "Александр", "Борис", "Виктор", "Геннадий"] +# income = [97000, 110000, 95000, 84000, 140000, 120000] +# age_of_workers = [27, 30, 25, 47, 52, 36] + +# функция zip() соединит первые элементы списков, вторые элементы списков и т.д. +# zip(names, income, age_of_workers) + +# + +# для вывода результата нужно передать zip-объект в функцию list() +# на выходе мы получим список из кортежей +# list(zip(names, income, age_of_workers)) +# - + +# Множества + +# Создание множества + +# + +# пустое множество задается через функцию set() +# set_1 = set() + +# непустое множество задается через функцию set() и список элементов +# set_2 = {"a", "b", "c", "c"} + +# или путем перечисления элементов в фигурных скобках {} +# set_3 = {"a", "b", "c", "c"} + +# множество содержит только уникальные элементы, поэтому дубликаты удаляются +# print(set_1, set_2, set_3) + +# + +# создать множество через пустые фигурные скобки нельзя +# not_a_set = {} + +# так создается словарь +# type(not_a_set) +# - + +# Добавление и удаление элементов + +# + +# предположим, что мы хотим создать множество делителей числа 24 +# factors = {1, 2, 3, 4, 6, 8, 12, 24} +# добавим число 9 методом .add() +# factors.add(9) +# factors + +# + +# добавим числа 7 и 11 методом .update() +# factors.update([7, 11]) +# factors + +# + +# удалить число можно методом .remove() +# factors.remove(7) +# factors +# - + +# Теория множеств в Питоне + +# + +# два множества равны, если содержат одинаковые +# элементы, при этом порядок элементов не важен +# {"a", "b", "c"} == {"c", "b", "a"} + +# + +# выведем мощность множества с помощью функции len() +# len({"a", "b", "c"}) + +# + +# проверим, содержится ли элемент во множестве +# "a" in {"a", "b", "c"} + +# + +# возможна и обратная операция +# "a" not in {"a", "b", "c"} + +# + +# проверим является ли А подмножеством В +# set_A = {"a", "b", "c"} +# set_B = {"a", "b", "c", "d", "e", "f"} + +# set_A.issubset(set_B) + +# + +# проверим является ли B надмножеством А +# set_B.issuperset(set_A) + +# + +# даны участники команд по обработке естественного языка (nlp) +# и компьютерному зрению (cv) +# nlp = {"Анна", "Николай", "Павел", "Оксана"} +# cv = {"Николай", "Евгений", "Ольга", "Оксана"} + +# + +# найдем тех, кто работает или в nlp, или в cv, или в обеих командах + +# можно использовать метод .union() +# print(nlp.union(cv)) + +# или символ | +# print(nlp | cv) + +# + +# найдем пересечение множеств, то есть тех, кто работает и в nlp, и в cv +# print(nlp.intersection(cv)) +# print(nlp & cv) + +# + +# выведем тех, кто работает только в nlp, но не в cv или cv и nlp одновременно +# print(nlp.difference(cv)) +# print(nlp - cv) + +# + +# найдем тех, кто работает или в cv, или в nlp, но не +# в обеих областях одновременно +# print(nlp.symmetric_difference(cv)) +# print(nlp ^ cv) From 72b17592a5331adfd8272f38bdd1ebdf0251f5d3 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 13:33:36 +0500 Subject: [PATCH 20/24] Create countries.csv --- python/makarov/countries.csv | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 python/makarov/countries.csv diff --git a/python/makarov/countries.csv b/python/makarov/countries.csv new file mode 100644 index 00000000..ec502732 --- /dev/null +++ b/python/makarov/countries.csv @@ -0,0 +1,8 @@ +country,capital,population,area,sea +China,Beijing,1400,9.6,1 +Vietnam,Hanoi,97,0.3,1 +United Kingdom,London,67,0.2,1 +Russia,Moscow,144,17.1,1 +Argentina,Buenos Aires,45,2.8,1 +Bolivia,Sucre,12,1.1,0 +South Africa,Pretoria,59,1.2,1 From f0a9be034db25722d9ba9794fc8dbb97e8bd4073 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 13:34:23 +0500 Subject: [PATCH 21/24] Create cpython.py --- python/cpython.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 python/cpython.py diff --git a/python/cpython.py b/python/cpython.py new file mode 100644 index 00000000..981098f6 --- /dev/null +++ b/python/cpython.py @@ -0,0 +1,129 @@ +"""Quiz 4.""" + +# 1. Что такое CPython и чем он отличается от Python? +# Python - это язык программирования, а CPython - это и язык программирования, и интерпретатор одновременно. +# 3. Сколько существует реализаций Python, и какая из них самая популярная? +# Существует 6 реализаций Python, самая популярная из них-CPython +# 4. На каком языке написан CPython? +# CPython написан на языке С. +# 5. (опционально) Кто создал CPython? +# CPython создал голландский программист Гвидо ван Россум. +# +# 6. Почему Python считается быстрым, несмотря на то, что это интерпретируемый язык? +# Потому что ядро CPython написано на языке С, и он вызывает инструкции из С. +# +# 7. Напишите путь к Интерпретатору CPython на вашем компьютере +# C:\Users\user\anaconda3\python.exe +# +# 8. Что содержится в папке include в CPython? +# В папке include в CPython находятся заголовочные файлы на языке С. +# +# 9. Где можно найти исходный код CPython дайте ссылку на репозиторий гитхаб. +# Ссылка на репозиторий гитхаб: https://github.com/python/cpython +# +# 10. (опционально) Как работает интерпретатор CPython при выполнении кода? +# Интерпретатор CPython выполняет код пошагово, преобразуя его в машинные инструкции для компьютера. +# +# 11. Какая команда используется для запуска файла с помощью CPython? +# python filename +# +# 12. Можно ли запускать текстовые файлы через интерпретатор Python? Почему? +# Можно, так как интерпретатору неважно, какие файлы запускать, главное – валидный пайтон-код. +# +# 13. Как указать путь к интерпретатору и файлу для выполнения кода? +# Через абсолютный или относительный путь. +# +# 14. Чем PyPy отличается от CPython? +# Этот интерпретатор работает в 10 раз быстрее, чем CPython. +# +# 15. Почему PyPy не может использоваться для всех проектов на Python? +# Это достаточно новый интерпретатор, и он ещё не совместим со всеми проектами на Python. +# +# 16. Где можно скачать PyPy? +# По ссылке: https://pypy.org/download.html +# +# 17. Как установить PyPy после скачивания? +# Извлечь папку и прописать пути в переменных средах. +# +# 18. Как запустить файл с помощью PyPy? +# В командной строке Windows ввести абсолютный путь до интерпретатора, пробел, абсолютный путь до файла, нажать Enter. +# +# 19. Почему PyPy выполняет код быстрее, чем CPython? +# PyPy использует Just-In-Time компилятор для компиляции Python в машинный код во время выполнения, что ускоряет работу. +# +# Практические задания +# Задание 1: Поиск и установка CPython +# Проверьте, установлен ли CPython на вашем компьютере: +# Используйте поиск в меню "Пуск" (Windows) или терминале (Linux/Mac). +# Введите команду python --version или python3 --version в терминале. +# Если CPython не установлен, скачайте его с официального сайта Python https://www.python.org/downloads/ и установите. +# +# C:\Users\user>python --version +# Python 3.13.9 +# +# +# Задание 2: Исследование структуры CPython +# Найдите папку, где установлен Python (например, через команду where python в терминале или свойства ярлыка). +# Откройте папку include и изучите её содержимое. Какое количество файлов на C там есть? +# Перейдите на [GitHub-репозиторий CPython](https://github.com/python/cpython) и найдите файл README. Прочитайте информацию о проекте. +# +# В папке include количество файлов на C: 77. +# +# C:\Users\user>where python +# C:\Users\user\anaconda3\python.exe +# C:\Users\user\AppData\Local\Programs\Python\Python310\python.exe +# C:\Users\user\AppData\Local\Programs\Python\Python312\python.exe +# C:\Users\user\AppData\Local\Microsoft\WindowsApps\python.exe +# +# C:\Users\user> +# +# Задание 3: Запуск файла с помощью CPython +# Создайте текстовый файл example.txt с содержимым: +# print("Hello from CPython!") +# Запустите файл через команду python <путь_до_файла> (замените <путь_до_файла> на фактический путь к вашему файлу). +# Проверьте, что выводится на экран. Попробуйте изменить расширение файла на .py и повторите запуск. +# C:\Users\user>C:\Users\user\anaconda3\Scripts\ipython3.exe C:\Users\user\Desktop\Test1\example.txt +# Hello from CPython! +# +# C:\Users\user>C:\Users\user\anaconda3\Scripts\ipython3.exe +# C:\Users\user\Desktop\Test1\example.py +# Hello from CPython! +# +# +# Задание 4: Установка и использование PyPy +# Перейдите на [официальный сайт PyPy](https://www.pypy.org/) и скачайте подходящую версию для вашей операционной системы. +# Распакуйте скачанный архив в удобное место. +# Создайте файл example_pypy.py с кодом: +# print("Hello from pypy!") +# Запустите файл через PyPy +# pypy <путь_до_файла> (замените <путь_до_файла> на фактический путь к вашему файлу). +# Проверьте, что выводится на экран. Попробуйте изменить расширение файла на .py и повторите запуск. +# Вывод: +# C:\Users\user>C:\Users\user\Downloads\pypy3.11-v7.3.20-win64\pypy.exe C:\Users\user\Desktop\Test1\example_pypy.py +# Hello from PyPy +# C:\Users\user> +# Задание 5: Сравнение производительности CPython и PyPy +# Создайте файл performance_test.py с кодом: +# import time +# start_time = time.time() +# total = 0 +# for i in range(1, 10000000): +# total += i +# end_time = time.time() +# +# print("Result:", total) +# print("Execution time:", end_time - start_time, "seconds") +# Запустите этот файл сначала через CPython, а затем через PyPy. Запишите результаты времени выполнения для обоих интерпретаторов. +# Сделайте вывод о разнице в производительности. +# +# Результат запуска через PyPy: +# C:\Users\user>C:\Users\user\Downloads\pypy3.11-v7.3.20-win64\pypy.exe C:\Users\user\Desktop\Test1\performance_test.py +# Result: 49999995000000 +# Execution time: 0.015625715255737305 seconds +# +# Результат запуска через iPython: +# C:\Users\user>C:\Users\user\anaconda3\Scripts\ipython.exe C:\Users\user\Desktop\Test1\ performance_test.py +# Result: 49999995000000 +# Execution time: 2.2144627571105957 seconds +# Вывод: Время выполнения через интерпретатор iPython в 142 раза больше. +# From ce99f49a52b12ced856b9b5fa09e2739c7c6d959 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 20:38:34 +0500 Subject: [PATCH 22/24] task 1 dictionaries and iterators --- python/makarov/chapter_15_iterators.ipynb | 782 ++++++++++ python/makarov/chapter_15_iterators.py | 338 +++++ python/makarov/chapter_9_dictionaries.ipynb | 1412 +++++++++++++++++++ python/makarov/chapter_9_dictionaries.py | 650 +++++++++ 4 files changed, 3182 insertions(+) create mode 100644 python/makarov/chapter_15_iterators.ipynb create mode 100644 python/makarov/chapter_15_iterators.py create mode 100644 python/makarov/chapter_9_dictionaries.ipynb create mode 100644 python/makarov/chapter_9_dictionaries.py diff --git a/python/makarov/chapter_15_iterators.ipynb b/python/makarov/chapter_15_iterators.ipynb new file mode 100644 index 00000000..986dec45 --- /dev/null +++ b/python/makarov/chapter_15_iterators.ipynb @@ -0,0 +1,782 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6d66c571", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Итераторы и генераторы.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "27c9b41f", + "metadata": {}, + "source": [ + "Итерируемый объект - это любой объект в Питон, который может возвращать свои элементы по одному. Это любая сущность, по которой можно пройтись циклом for. Ключевая особенность - наличие метода __iter__(). \n", + "Итератор - это объект, который непосредственно осуществляет перебор. " + ] + }, + { + "cell_type": "markdown", + "id": "4ca372f2", + "metadata": {}, + "source": [ + "Протокол итератора включает два метода:\n", + "1. __iter__() - возвращает сам объект-итератор;\n", + "2. __next__() - возвращает следующий элемент. В конце последовательности возбуждает исключение StopIteration." + ] + }, + { + "cell_type": "markdown", + "id": "53a10bb4", + "metadata": {}, + "source": [ + "Генератор - это объект, реализующий протокол итератора, но позволяющий получать элементы последовательности по одному, не храня всю коллекцию в памяти. " + ] + }, + { + "cell_type": "markdown", + "id": "dd91d85f", + "metadata": {}, + "source": [ + "Каждый генератор является итератором, но не каждый итератор - это генератор. " + ] + }, + { + "cell_type": "markdown", + "id": "f5ca9ca5", + "metadata": {}, + "source": [ + "Генераторы позволяют писать масштабируемый код, который одинаково хорошо работает как с десятью, так и с десятками миллионов элементов. " + ] + }, + { + "cell_type": "markdown", + "id": "7e597d02", + "metadata": {}, + "source": [ + "Создание генераторов \n", + "1 способ - функции-генераторы. Когда логика вычислений более сложная, требует использования циклов и т.д.\n", + "2 способ - генераторные выражения. Для простых, однострочных операций преобразования последовательностей. " + ] + }, + { + "cell_type": "markdown", + "id": "02c01ad4", + "metadata": {}, + "source": [ + "Жизненный цикл генератора:\n", + "- Создание\n", + "- Итерация \n", + "- Истощение\n", + "Генераторы одноразовые, их невозможно \"перезапустить\". Чтобы снова получить ту же последовательность, необходимо создать новый экземпляр генератора. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2530cd19", + "metadata": {}, + "outputs": [], + "source": [ + "# встроенная функция iter() вызывает метод .__iter__(),\n", + "# создающий итератор\n", + "# from collections.abc import Iterator\n", + "# from itertools import chain, count, cycle\n", + "\n", + "# iter([1, 2, 3, 4, 5])" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e985a7b3", + "metadata": {}, + "outputs": [], + "source": [ + "# iterable_object = [1, 2, 3, 4, 5]\n", + "\n", + "# iterator = iter(iterable_object)\n", + "# print(iterator)\n", + "# print()\n", + "# print(next(iterator))\n", + "# print(next(iterator))\n", + "# print(next(iterator))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "694cb074", + "metadata": {}, + "outputs": [], + "source": [ + "# for iterator in iterable_object:\n", + "# print(iterator)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0e45abfd", + "metadata": {}, + "outputs": [], + "source": [ + "# iterable_object = [1, 2, 3, 4, 5]\n", + "\n", + "# iterator_a = iter(iterable_object)\n", + "# iterator_b = iter(iterable_object)\n", + "\n", + "# print(f\"A: {next(iterator_a)}\")\n", + "# print(f\"A: {next(iterator_a)}\")\n", + "# print(f\"A: {next(iterator_a)}\")\n", + "# print(f\"B: {next(iterator_b)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9bc49210", + "metadata": {}, + "outputs": [], + "source": [ + "# iterable_object" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d9c7055e", + "metadata": {}, + "outputs": [], + "source": [ + "# Функция list() позволяет обойти и вернуть все\n", + "# (оставшиеся) элементы конкретного итератора\n", + "# list(iterator_a), list(iterator_b)" + ] + }, + { + "cell_type": "markdown", + "id": "6c12d8a3", + "metadata": {}, + "source": [ + "Отсутствие обратного хода" + ] + }, + { + "cell_type": "markdown", + "id": "ba1d2884", + "metadata": {}, + "source": [ + "Логично, что итератор не позволяет двигаться в обратном направлении от последующего элемента к предыдущему." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7c295490", + "metadata": {}, + "outputs": [], + "source": [ + "# iterator_c = iter(iterable_object)\n", + "\n", + "# for i in iterator_c:\n", + "# print(i)\n", + "# break\n", + "\n", + "# for j in iterator_c:\n", + "# print(j)" + ] + }, + { + "cell_type": "markdown", + "id": "f98f4080", + "metadata": {}, + "source": [ + "Функция zip()\n", + "Помимо функции iter() еще одной функцией, возвращающей итератор из итерируемого объекта, является функция zip()." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "95c33fe3", + "metadata": {}, + "outputs": [], + "source": [ + "# zip(iterable_object, iterable_object)" + ] + }, + { + "cell_type": "markdown", + "id": "fd2d4aa0", + "metadata": {}, + "source": [ + "Если говорить более точно, функция zip() объединяет несколько итерируемых объектов и создает итератор кортежей (iterator of tuples) или объект zip. Метод .__next__() объекта zip выдает первые, вторые и т.д. элементы соответствующих объектов." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "33a9fec9", + "metadata": {}, + "outputs": [], + "source": [ + "# iterator_tuple = zip(iterable_object, iterable_object)\n", + "\n", + "# print(next(iterator_tuple))\n", + "# print(next(iterator_tuple))\n", + "# print(next(iterator_tuple))" + ] + }, + { + "cell_type": "markdown", + "id": "f080c61f", + "metadata": {}, + "source": [ + "На практике конечно удобнее передать итерируемые объекты в функцию zip() и создавать и вызывать метод .__next__() итератора в цикле." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "2ffa52e7", + "metadata": {}, + "outputs": [], + "source": [ + "# for i in zip(iterable_object, iterable_object):\n", + "# print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "eb578126", + "metadata": {}, + "source": [ + "Примеры итераторов" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f49f383e", + "metadata": {}, + "outputs": [], + "source": [ + "# Возведение в квадрат\n", + "\n", + "\n", + "# class Square:\n", + "# def __init__(self, seq):\n", + "# self._seq = seq\n", + "# self._idx = 0\n", + "\n", + "# def __iter__(self):\n", + "# return self\n", + "\n", + "# def __next__(self):\n", + "# if self._idx < len(self._seq):\n", + "# square = self._seq[self._idx] ** 2\n", + "# self._idx += 1\n", + "# return square\n", + "# else:\n", + "# raise StopIteration" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b375553a", + "metadata": {}, + "outputs": [], + "source": [ + "# square = Square([1, 2, 3, 4, 5])\n", + "# square" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7a8c7a01", + "metadata": {}, + "outputs": [], + "source": [ + "# for s in square:\n", + "# print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "943d09cd", + "metadata": {}, + "outputs": [], + "source": [ + "# Счетчик\n", + "\n", + "\n", + "# class Counter:\n", + "# def __init__(self, start=3, stop=9):\n", + "# self._current = start - 1\n", + "# self._stop = stop\n", + "\n", + "# def __iter__(self):\n", + "# return self\n", + "\n", + "# def __next__(self):\n", + "# self._current += 1\n", + "# if self._current < self._stop:\n", + "# return self._current\n", + "# else:\n", + "# raise StopIteration" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "cc58b206", + "metadata": {}, + "outputs": [], + "source": [ + "# counter = Counter()\n", + "# counter" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "5e231fc7", + "metadata": {}, + "outputs": [], + "source": [ + "# print(next(counter))\n", + "# print(next(counter))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e9e22a33", + "metadata": {}, + "outputs": [], + "source": [ + "# for c in counter:\n", + "# print(c)" + ] + }, + { + "cell_type": "markdown", + "id": "fe82afaa", + "metadata": {}, + "source": [ + "Класс Iterator модуля collections.abc" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "a9eb3f68", + "metadata": {}, + "outputs": [], + "source": [ + "# class Counter2(Iterator):\n", + "# def __init__(self, start=3, stop=9):\n", + "# self._current = start - 1\n", + "# self._stop = stop\n", + "\n", + "# def __next__(self):\n", + "# self._current += 1\n", + "# if self._current < self._stop:\n", + "# return self._current\n", + "# else:\n", + "# raise StopIteration" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "e89651ab", + "metadata": {}, + "outputs": [], + "source": [ + "# for c in Counter2():\n", + "# print(c)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "b5e3fb8d", + "metadata": {}, + "outputs": [], + "source": [ + "# бесконечный итератор\n", + "\n", + "\n", + "# class FibIterator:\n", + "# def __init__(self):\n", + "# self._idx = 0\n", + "# self._current = 0\n", + "# self._next = 1\n", + "\n", + "# def __iter__(self):\n", + "# return self\n", + "\n", + "# def __next__(self):\n", + "# self._idx += 1\n", + "# self._current, self._next = (self._next, self._current + self._next)\n", + "# return self._current" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "d085188e", + "metadata": {}, + "outputs": [], + "source": [ + "# limit = 10\n", + "\n", + "# for f in FibIterator():\n", + "# print(f)\n", + "# limit -= 1\n", + "# if limit == 0:\n", + "# break" + ] + }, + { + "cell_type": "markdown", + "id": "1860faed", + "metadata": {}, + "source": [ + "Генератор" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14c01435", + "metadata": {}, + "outputs": [], + "source": [ + "# Простой пример" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e48a51ae", + "metadata": {}, + "outputs": [], + "source": [ + "# def sequence(n):\n", + "# res = [x for x in range(1, n + 1)]\n", + "# return res" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "54e41821", + "metadata": {}, + "outputs": [], + "source": [ + "# sequence(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "f4644e27", + "metadata": {}, + "outputs": [], + "source": [ + "# def sequence_gen(n):\n", + "# yield from range(1, n + 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "40b607c8", + "metadata": {}, + "outputs": [], + "source": [ + "# sequence_gen(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "ee429d2b", + "metadata": {}, + "outputs": [], + "source": [ + "# seq_5 = sequence_gen(5)\n", + "\n", + "# print(next(seq_5))\n", + "# print(next(seq_5))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "73f7e1a4", + "metadata": {}, + "outputs": [], + "source": [ + "# for i in seq_5:\n", + "# print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "bc984fc3", + "metadata": {}, + "source": [ + "Generator comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "e8f4818f", + "metadata": {}, + "outputs": [], + "source": [ + "# (x for x in range(1, 5 + 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "60f0ab9e", + "metadata": {}, + "outputs": [], + "source": [ + "# list(x for x in range(1, 5 + 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "8a0c6b51", + "metadata": {}, + "outputs": [], + "source": [ + "# sum(x for x in range(1, 5 + 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "6f2d3f8c", + "metadata": {}, + "outputs": [], + "source": [ + "# 5 in (x for x in range(1, 5 + 1))" + ] + }, + { + "cell_type": "markdown", + "id": "a812d0b1", + "metadata": {}, + "source": [ + "Модуль itertools" + ] + }, + { + "cell_type": "markdown", + "id": "2807f314", + "metadata": {}, + "source": [ + "Функция count()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "f6d5cdb8", + "metadata": {}, + "outputs": [], + "source": [ + "# natural_numbers = count(start=1, step=0.5)\n", + "\n", + "# for num in natural_numbers:\n", + "# print(num)\n", + "# if num == 3:\n", + "# break" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "86d6a0f8", + "metadata": {}, + "outputs": [], + "source": [ + "# list_ = [\"A\", \"B\", \"C\", \"D\"]\n", + "# for i in zip(count(), list_):\n", + "# print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "bdf7c5f8", + "metadata": {}, + "outputs": [], + "source": [ + "# def f(x):\n", + "# return x**2 + x - 2\n", + "\n", + "\n", + "# f_x = map(f, count())\n", + "# next(f_x)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "4d08c63e", + "metadata": {}, + "outputs": [], + "source": [ + "# for val in f_x:\n", + "# print(val)\n", + "# if val > 10:\n", + "# break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44900a18", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "88de089f", + "metadata": {}, + "source": [ + "Функция cycle()\n", + "\n", + "Функция cycle() принимает в качестве аргумента итерируемый объект и создает итератор, содержащий все его элементы. Кроме этого, создается копия этих элементов.\n", + "\n", + "После перебора всех элементов итератора начинается перебор скопированных элементов и одновременно создается новая копия. Затем цикл перебора и копирования продолжается до бесконечности." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "ffad6362", + "metadata": {}, + "outputs": [], + "source": [ + "# list_ = [1, 2, 3]\n", + "# iterator = cycle(list_)\n", + "\n", + "# limit = 5\n", + "# for i in iterator:\n", + "# print(i)\n", + "# limit -= 1\n", + "# if limit == 0:\n", + "# break" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "454e8ab3", + "metadata": {}, + "outputs": [], + "source": [ + "# string = \"Python\"\n", + "# iterator = cycle(string)\n", + "\n", + "# limit = 10\n", + "# for i in iterator:\n", + "# print(i)\n", + "# limit -= 1\n", + "# if limit == 0:\n", + "# break" + ] + }, + { + "cell_type": "markdown", + "id": "07c9171c", + "metadata": {}, + "source": [ + "Функция chain()\n", + "Функция chain() объединяет (сцепляет) несколько итерируемых объектов в один итератор." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "ff001da5", + "metadata": {}, + "outputs": [], + "source": [ + "# iterator = chain([\"abc\", \"d\", \"e\", \"f\"], \"abc\", [1, 2, 3])\n", + "# iterator" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "895602a7", + "metadata": {}, + "outputs": [], + "source": [ + "# list(iterator)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "0693fbf3", + "metadata": {}, + "outputs": [], + "source": [ + "# list(chain.from_iterable([\"abc\", \"def\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "532c76d7", + "metadata": {}, + "outputs": [], + "source": [ + "# sum(chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_15_iterators.py b/python/makarov/chapter_15_iterators.py new file mode 100644 index 00000000..e889d004 --- /dev/null +++ b/python/makarov/chapter_15_iterators.py @@ -0,0 +1,338 @@ +"""Итераторы и генераторы.""" + +# Итерируемый объект - это любой объект в Питон, который может возвращать свои элементы по одному. Это любая сущность, по которой можно пройтись циклом for. Ключевая особенность - наличие метода __iter__(). +# Итератор - это объект, который непосредственно осуществляет перебор. + +# Протокол итератора включает два метода: +# 1. __iter__() - возвращает сам объект-итератор; +# 2. __next__() - возвращает следующий элемент. В конце последовательности возбуждает исключение StopIteration. + +# Генератор - это объект, реализующий протокол итератора, но позволяющий получать элементы последовательности по одному, не храня всю коллекцию в памяти. + +# Каждый генератор является итератором, но не каждый итератор - это генератор. + +# Генераторы позволяют писать масштабируемый код, который одинаково хорошо работает как с десятью, так и с десятками миллионов элементов. + +# Создание генераторов +# 1 способ - функции-генераторы. Когда логика вычислений более сложная, требует использования циклов и т.д. +# 2 способ - генераторные выражения. Для простых, однострочных операций преобразования последовательностей. + +# Жизненный цикл генератора: +# - Создание +# - Итерация +# - Истощение +# Генераторы одноразовые, их невозможно "перезапустить". Чтобы снова получить ту же последовательность, необходимо создать новый экземпляр генератора. + +# + +# встроенная функция iter() вызывает метод .__iter__(), +# создающий итератор +# from collections.abc import Iterator +# from itertools import chain, count, cycle + +# iter([1, 2, 3, 4, 5]) + +# + +# iterable_object = [1, 2, 3, 4, 5] + +# iterator = iter(iterable_object) +# print(iterator) +# print() +# print(next(iterator)) +# print(next(iterator)) +# print(next(iterator)) + +# + +# for iterator in iterable_object: +# print(iterator) + +# + +# iterable_object = [1, 2, 3, 4, 5] + +# iterator_a = iter(iterable_object) +# iterator_b = iter(iterable_object) + +# print(f"A: {next(iterator_a)}") +# print(f"A: {next(iterator_a)}") +# print(f"A: {next(iterator_a)}") +# print(f"B: {next(iterator_b)}") + +# + +# iterable_object + +# + +# Функция list() позволяет обойти и вернуть все +# (оставшиеся) элементы конкретного итератора +# list(iterator_a), list(iterator_b) +# - + +# Отсутствие обратного хода + +# Логично, что итератор не позволяет двигаться в обратном направлении от последующего элемента к предыдущему. + +# + +# iterator_c = iter(iterable_object) + +# for i in iterator_c: +# print(i) +# break + +# for j in iterator_c: +# print(j) +# - + +# Функция zip() +# Помимо функции iter() еще одной функцией, возвращающей итератор из итерируемого объекта, является функция zip(). + +# + +# zip(iterable_object, iterable_object) +# - + +# Если говорить более точно, функция zip() объединяет несколько итерируемых объектов и создает итератор кортежей (iterator of tuples) или объект zip. Метод .__next__() объекта zip выдает первые, вторые и т.д. элементы соответствующих объектов. + +# + +# iterator_tuple = zip(iterable_object, iterable_object) + +# print(next(iterator_tuple)) +# print(next(iterator_tuple)) +# print(next(iterator_tuple)) +# - + +# На практике конечно удобнее передать итерируемые объекты в функцию zip() и создавать и вызывать метод .__next__() итератора в цикле. + +# + +# for i in zip(iterable_object, iterable_object): +# print(i) +# - + +# Примеры итераторов + +# + +# Возведение в квадрат + + +# class Square: +# def __init__(self, seq): +# self._seq = seq +# self._idx = 0 + +# def __iter__(self): +# return self + +# def __next__(self): +# if self._idx < len(self._seq): +# square = self._seq[self._idx] ** 2 +# self._idx += 1 +# return square +# else: +# raise StopIteration + +# + +# square = Square([1, 2, 3, 4, 5]) +# square + +# + +# for s in square: +# print(s) + +# + +# Счетчик + + +# class Counter: +# def __init__(self, start=3, stop=9): +# self._current = start - 1 +# self._stop = stop + +# def __iter__(self): +# return self + +# def __next__(self): +# self._current += 1 +# if self._current < self._stop: +# return self._current +# else: +# raise StopIteration + +# + +# counter = Counter() +# counter + +# + +# print(next(counter)) +# print(next(counter)) + +# + +# for c in counter: +# print(c) +# - + +# Класс Iterator модуля collections.abc + +# + +# class Counter2(Iterator): +# def __init__(self, start=3, stop=9): +# self._current = start - 1 +# self._stop = stop + +# def __next__(self): +# self._current += 1 +# if self._current < self._stop: +# return self._current +# else: +# raise StopIteration + +# + +# for c in Counter2(): +# print(c) + +# + +# бесконечный итератор + + +# class FibIterator: +# def __init__(self): +# self._idx = 0 +# self._current = 0 +# self._next = 1 + +# def __iter__(self): +# return self + +# def __next__(self): +# self._idx += 1 +# self._current, self._next = (self._next, self._current + self._next) +# return self._current + +# + +# limit = 10 + +# for f in FibIterator(): +# print(f) +# limit -= 1 +# if limit == 0: +# break +# - + +# Генератор + +# + +# Простой пример + +# + +# def sequence(n): +# res = [x for x in range(1, n + 1)] +# return res + +# + +# sequence(5) + +# + +# def sequence_gen(n): +# yield from range(1, n + 1) + +# + +# sequence_gen(5) + +# + +# seq_5 = sequence_gen(5) + +# print(next(seq_5)) +# print(next(seq_5)) + +# + +# for i in seq_5: +# print(i) +# - + +# Generator comprehension + +# + +# (x for x in range(1, 5 + 1)) + +# + +# list(x for x in range(1, 5 + 1)) + +# + +# sum(x for x in range(1, 5 + 1)) + +# + +# 5 in (x for x in range(1, 5 + 1)) +# - + +# Модуль itertools + +# Функция count() + +# + +# natural_numbers = count(start=1, step=0.5) + +# for num in natural_numbers: +# print(num) +# if num == 3: +# break + +# + +# list_ = ["A", "B", "C", "D"] +# for i in zip(count(), list_): +# print(i) + +# + +# def f(x): +# return x**2 + x - 2 + + +# f_x = map(f, count()) +# next(f_x) + +# + +# for val in f_x: +# print(val) +# if val > 10: +# break +# - + + +# Функция cycle() +# +# Функция cycle() принимает в качестве аргумента итерируемый объект и создает итератор, содержащий все его элементы. Кроме этого, создается копия этих элементов. +# +# После перебора всех элементов итератора начинается перебор скопированных элементов и одновременно создается новая копия. Затем цикл перебора и копирования продолжается до бесконечности. + +# + +# list_ = [1, 2, 3] +# iterator = cycle(list_) + +# limit = 5 +# for i in iterator: +# print(i) +# limit -= 1 +# if limit == 0: +# break + +# + +# string = "Python" +# iterator = cycle(string) + +# limit = 10 +# for i in iterator: +# print(i) +# limit -= 1 +# if limit == 0: +# break +# - + +# Функция chain() +# Функция chain() объединяет (сцепляет) несколько итерируемых объектов в один итератор. + +# + +# iterator = chain(["abc", "d", "e", "f"], "abc", [1, 2, 3]) +# iterator + +# + +# list(iterator) + +# + +# list(chain.from_iterable(["abc", "def"])) + +# + +# sum(chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) diff --git a/python/makarov/chapter_9_dictionaries.ipynb b/python/makarov/chapter_9_dictionaries.ipynb new file mode 100644 index 00000000..81544600 --- /dev/null +++ b/python/makarov/chapter_9_dictionaries.ipynb @@ -0,0 +1,1412 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 16, + "id": "667faac8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Словари в Питоне.'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Словари в Питоне.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "6eb74f5f", + "metadata": {}, + "source": [ + "Словари, наряду со списками, кортежами и множествами, относятся к коллекциям, то есть типам данных, содержащим несколько элементов." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "46e5c3c9", + "metadata": {}, + "outputs": [], + "source": [ + "# пустой словарь можно создать с помощью {} или функции dict()\n", + "# импортируем класс Counter\n", + "# from collections import Counter\n", + "\n", + "# импортируем функцию pprint() из модуля pprint\n", + "# некоторые структуры данных она выводит лучше, чем обычная print()\n", + "# from pprint import pprint\n", + "\n", + "# import numpy as np\n", + "\n", + "# dict_1 = {}\n", + "# dict_2 = dict()\n", + "# print(dict_1, dict_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1d79c907", + "metadata": {}, + "outputs": [], + "source": [ + "# словарь можно сразу заполнить ключами и значениями\n", + "# company = {\"name\": \"Toyota\", \"founded\": 1937, \"founder\": \"Kiichiro Toyoda\"}\n", + "# company" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1bcb20c0", + "metadata": {}, + "outputs": [], + "source": [ + "# словарь можно создать из вложенных списков\n", + "# tickers = dict([[\"TYO\", \"Toyota\"], [\"TSLA\", \"Tesla\"], [\"F\", \"Ford\"]])\n", + "# tickers" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d1c1ff2a", + "metadata": {}, + "outputs": [], + "source": [ + "# если поместить ключи в кортеж\n", + "# keys = (\"k1\", \"k2\", \"k3\")\n", + "# и задать значение\n", + "# value = 0\n", + "\n", + "# то с помощью метода .fromkeys() можно создать словарь\n", + "# с этими ключами и заданным значением для каждого из них\n", + "# empty_values = dict.fromkeys(keys, value)\n", + "# empty_values" + ] + }, + { + "cell_type": "markdown", + "id": "e0b5e011", + "metadata": {}, + "source": [ + "Ключи и значения словаря " + ] + }, + { + "cell_type": "markdown", + "id": "ea005cbe", + "metadata": {}, + "source": [ + "Виды значений словаря" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fc7831b3", + "metadata": {}, + "outputs": [], + "source": [ + "# приведем пример того, какими могут быть значения словаря\n", + "# value_types = {\n", + "# \"k1\": 123,\n", + "# \"k2\": \"string\",\n", + "# \"k3\": np.nan, # тип \"Пропущенное значение\"\n", + "# \"k4\": True, # логическое значение\n", + "# \"k5\": None,\n", + "# \"k6\": [1, 2, 3],\n", + "# \"k7\": np.array([1, 2, 3]),\n", + "# \"k8\": {1: \"v1\", 2: \"v2\", 3: \"v3\"},\n", + "# }\n", + "\n", + "# value_types" + ] + }, + { + "cell_type": "markdown", + "id": "46d072e5", + "metadata": {}, + "source": [ + "Методы .keys(), .values() и .items()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "bf4b03df", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим несложный словарь с информацией о сотруднике\n", + "# person = {\"first name\": \"Иван\", \"last name\": \"Иванов\", \"born\": 1980, \"dept\": \"IT\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a5835084", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на ключи и\n", + "# person.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "27255aa7", + "metadata": {}, + "outputs": [], + "source": [ + "# значения\n", + "# person.values()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "3d9480f3", + "metadata": {}, + "outputs": [], + "source": [ + "# а также на пары ключ-значение в виде списка из кортежей\n", + "# person.items()" + ] + }, + { + "cell_type": "markdown", + "id": "cbbe3c9a", + "metadata": {}, + "source": [ + "Использование цикла for" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "28c80c2c", + "metadata": {}, + "outputs": [], + "source": [ + "# ключи и значения можно вывести в цикле for\n", + "# for k, v in person.items():\n", + "# print(k, v)" + ] + }, + { + "cell_type": "markdown", + "id": "44e64cc1", + "metadata": {}, + "source": [ + "Доступ по ключу и метод .get()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "e5836dda", + "metadata": {}, + "outputs": [], + "source": [ + "# значение можно посмотреть по ключу\n", + "# person[\"last name\"]\n", + "# если такого ключа нет, Питон выдаст ошибку" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "b33e5365", + "metadata": {}, + "outputs": [], + "source": [ + "# чтобы этого не произошло, можно использовать метод .get()\n", + "# по умолчанию при отсутствии ключа он выводит значение None\n", + "# print(person.get(\"education\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "a7458467", + "metadata": {}, + "outputs": [], + "source": [ + "# если ключ все-таки есть, .get() выведет соответствующее значение\n", + "# person.get(\"born\")" + ] + }, + { + "cell_type": "markdown", + "id": "c82ac61f", + "metadata": {}, + "source": [ + "Проверка вхождения ключа и значения в словарь" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4f617b36", + "metadata": {}, + "outputs": [], + "source": [ + "# проверим есть ли такой ключ\n", + "# \"born\" in person" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1d71b7c1", + "metadata": {}, + "outputs": [], + "source": [ + "# и такое значение\n", + "# 1980 in person.values()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "230315ab", + "metadata": {}, + "outputs": [], + "source": [ + "# можно также проверить наличие и ключа, и значения одновременно\n", + "# (\"born\", 1980) in person.items()" + ] + }, + { + "cell_type": "markdown", + "id": "58e887d1", + "metadata": {}, + "source": [ + "Операции со словарями" + ] + }, + { + "cell_type": "markdown", + "id": "3dbd2b7d", + "metadata": {}, + "source": [ + "Добавление и изменение элементов" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "fec48529", + "metadata": {}, + "outputs": [], + "source": [ + "# добавить элемент можно, передав новому ключу новое значение\n", + "# обратите внимание, в данном случае новое значение - это список\n", + "# person[\"languages\"] = [\"Python\", \"C++\"]\n", + "# person" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "8aeff2d2", + "metadata": {}, + "outputs": [], + "source": [ + "# изменить элемент можно, передав существующему ключу новое значение,\n", + "# значение - это по-прежнему список, но из одного элемента\n", + "# person[\"languages\"] = [\"Python\"]\n", + "# person" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "222f4444", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем еще один словарь\n", + "# new_elements = {\"job\": \"программист\", \"experience\": 7}\n", + "\n", + "# и присоединим его к существующему словарю с помощью метода .update()\n", + "# person.update(new_elements)\n", + "# person" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "4d3f6f99", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .setdefault() проверит есть ли ключ в словаре,\n", + "# если \"да\", значение не изменится\n", + "# person.setdefault(\"last name\", \"Петров\")\n", + "# person" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "aeb45ff9", + "metadata": {}, + "outputs": [], + "source": [ + "# если нет, будет добавлен новый ключ и соответствующее значение\n", + "# person.setdefault(\"f_languages\", [\"русский\", \"английский\"])\n", + "# person" + ] + }, + { + "cell_type": "markdown", + "id": "5fda9f5b", + "metadata": {}, + "source": [ + "Удаление элементов " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "f9d1dc96", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .pop() удаляет элемент по ключу и выводит удаляемое значение\n", + "# person.pop(\"dept\")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "c69b7178", + "metadata": {}, + "outputs": [], + "source": [ + "# мы видим, что пары 'dept' : 'IT' больше нет\n", + "# person" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "935cef48", + "metadata": {}, + "outputs": [], + "source": [ + "# ключевое слово del также удаляет элемент по ключу\n", + "# удаляемое значение не выводится\n", + "# del person[\"born\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "9742da6e", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .popitem() удаляет последний добавленный элемент и выводит его\n", + "# person.popitem()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "eb078eb5", + "metadata": {}, + "outputs": [], + "source": [ + "# метод .clear() удаляет все элементы словаря\n", + "# person.clear()\n", + "# person" + ] + }, + { + "cell_type": "markdown", + "id": "8bd2ce37", + "metadata": {}, + "source": [ + "Сортировка словарей " + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "8292f293", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем несложный словарь\n", + "# dict_to_sort = {\"k2\": 30, \"k1\": 20, \"k3\": 10, \"k4\": 85}\n", + "\n", + "# отсортируем ключи\n", + "# sorted(dict_to_sort)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "bdde0f28", + "metadata": {}, + "outputs": [], + "source": [ + "# отсортируем значения\n", + "# sorted(dict_to_sort.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "327a1062", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на пары ключ : значение\n", + "# dict_to_sort.items()" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "f21617b3", + "metadata": {}, + "outputs": [], + "source": [ + "# для их сортировки по ключу (индекс [0])\n", + "# воспользуемся методом .items() и lambda-функцией\n", + "# sorted(dict_to_sort.items(), key=lambda x: x[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "fb3086ec", + "metadata": {}, + "outputs": [], + "source": [ + "# сортировка по значению выполняется так же, однако\n", + "# lambda-функции мы передаем индекс [1]\n", + "# sorted(dict_to_sort.items(), key=lambda x: x[1])" + ] + }, + { + "cell_type": "markdown", + "id": "d207b24e", + "metadata": {}, + "source": [ + "Копирование словарей " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "7c8a6d29", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим исходный словарь с количеством студентов на\n", + "# первом и втором курсах университета\n", + "# original = {\"Первый курс\": 174, \"Второй курс\": 131}" + ] + }, + { + "cell_type": "markdown", + "id": "8cbba736", + "metadata": {}, + "source": [ + "Копирование с помощью метода .copy()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "f766d7c0", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим копию этого словаря с помощью метода .copy()\n", + "# new_1 = original.copy()\n", + "\n", + "# добавим информацию о третьем курсе в новый словарь\n", + "# new_1[\"Третий курс\"] = 117\n", + "\n", + "# исходный словарь не изменился\n", + "# print(original)\n", + "# print(new_1)" + ] + }, + { + "cell_type": "markdown", + "id": "7fc08cf7", + "metadata": {}, + "source": [ + "Копирование через оператор присваивания `=` (так делать не стоит!)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "8b496bfe", + "metadata": {}, + "outputs": [], + "source": [ + "# передадим исходный словарь в новую переменную\n", + "# new_2 = original\n", + "\n", + "# удалим элементы нового словаря\n", + "# new_2.clear()\n", + "\n", + "# из исходного словаря данные также удалились\n", + "# print(original)\n", + "# print(new_2)" + ] + }, + { + "cell_type": "markdown", + "id": "ab9c87ba", + "metadata": {}, + "source": [ + "Функция dir()" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "7961c056", + "metadata": {}, + "outputs": [], + "source": [ + "# функция dir() возвращает все методы передаваемого ей объекта\n", + "# some_dict = {\"k\": 1}\n", + "\n", + "# вначале идут специальные методы,\n", + "# они начинаются и заканчиваются символом '__'\n", + "# выведем первые 11 элементов\n", + "# dir(some_dict)[:11]" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "22616bfe", + "metadata": {}, + "outputs": [], + "source": [ + "# когда мы передаем наш словарь функции print(),\n", + "# print(some_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "9cbfc23f", + "metadata": {}, + "outputs": [], + "source": [ + "# на самом деле мы применяем к объекту метод .__str__()\n", + "# some_dict.__str__()" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "20cf6392", + "metadata": {}, + "outputs": [], + "source": [ + "# в большинстве случаев нас будут интересовать методы без '__'\n", + "# dir(some_dict)[-11:]" + ] + }, + { + "cell_type": "markdown", + "id": "d78934fe", + "metadata": {}, + "source": [ + "Dict comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "d9426dda", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим еще один несложный словарь\n", + "# source_dict = {\"k1\": 2, \"k2\": 4, \"k3\": 6}" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "b3ad6f58", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью dict comprehension умножим каждое значение на два\n", + "# {k: v * 2 for (k, v) in source_dict.items()}" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "1bfd4dcd", + "metadata": {}, + "outputs": [], + "source": [ + "# сделаем символы всех ключей заглавными\n", + "# {k.upper(): v for (k, v) in source_dict.items()}" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "b62bb403", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим условие, что значение должно быть больше двух И меньше шести\n", + "# {k: v for (k, v) in source_dict.items() if v > 2 if v < 6}" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "b842931c", + "metadata": {}, + "outputs": [], + "source": [ + "# new_dict = {}\n", + "\n", + "# при решении этой же задачи в цикле for\n", + "# for k, v in source_dict.items():\n", + "\n", + "# мы бы использовали логическое И (and)\n", + "# if v > 2 and v < 6:\n", + "\n", + "# если условия верны, записываем ключ и значение в новый словарь\n", + "# new_dict[k] = v\n", + "\n", + "# new_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "4f2722ca", + "metadata": {}, + "outputs": [], + "source": [ + "# условие с if-else ставится в самом начале схемы dict comprehension\n", + "# заменим значение на слово even, если оно четное, и odd, если нечетное\n", + "# {k: (\"even\" if v % 2 == 0 else \"odd\") for (k, v) in source_dict.items()}" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "45a31892", + "metadata": {}, + "outputs": [], + "source": [ + "# dict comprehension можно использовать вместо метода .fromkeys()\n", + "# keys = (\"k1\", \"k2\", \"k3\")\n", + "\n", + "# передадим словарю ключи из кортежа keys и зададим значение 0 каждому из них\n", + "# {k: 0 for k in keys}" + ] + }, + { + "cell_type": "markdown", + "id": "22fc7a5f", + "metadata": {}, + "source": [ + "Дополнительные примеры" + ] + }, + { + "cell_type": "markdown", + "id": "70e24843", + "metadata": {}, + "source": [ + "lambda-функции, функции map() и zip()" + ] + }, + { + "cell_type": "markdown", + "id": "4c4e21ca", + "metadata": {}, + "source": [ + "Пример со списком " + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "773c8e13", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем список слов\n", + "# words = [\"apple\", \"banana\", \"fig\", \"blackberry\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "08d278da", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим lambda-функцию, которая посчитает длину\n", + "# передаваемого ей слова\n", + "# с помощью функции map() применим lambda-функцию\n", + "# к каждому элементу списка words\n", + "# и поместим длины слов в новый список length с помощью\n", + "# функции list()\n", + "# length = list(map(lambda word: len(word), words))\n", + "# length" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d269fe3e", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью функции zip() поэлементно соединим оба\n", + "# списка и преобразуем в словарь\n", + "# dict(zip(words, length))" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "90c39ca1", + "metadata": {}, + "outputs": [], + "source": [ + "# то же самое можно сделать с помощью функции zip()\n", + "# и list comprehension\n", + "# dict(zip(words, [len(word) for word in words]))" + ] + }, + { + "cell_type": "markdown", + "id": "35cbf479", + "metadata": {}, + "source": [ + "Пример со словарем " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1157c8f7", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем словарь с ростом людей в футах\n", + "# height_feet = {\"Alex\": 6.1, \"Jerry\": 5.4, \"Ben\": 5.8}" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "61fd967c", + "metadata": {}, + "outputs": [], + "source": [ + "# для преобразования футов в метры создадим lambda-функцию\n", + "# lambda m: m * 0.3048\n", + "# применим эту функцию к значениям словаря с помощью\n", + "# функции map()\n", + "# преобразуем в список\n", + "# metres = list(map(lambda m: m * 0.3048, height_feet.values()))\n", + "# metres" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "3f95f4a4", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью функции zip() соединим ключи исходного\n", + "# словаря с элементами списка metres\n", + "# dict(zip(height_feet.keys(), np.round(metres, 2)))" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "c9baa8f9", + "metadata": {}, + "outputs": [], + "source": [ + "# то же самое можно выполнить с помощью dict\n", + "# comprehensions всего в одну строчку\n", + "# мы просто преобразуем значения словаря в метры\n", + "# {k: np.round(v * 0.3048, 2) for (k, v) in height_feet.items()}" + ] + }, + { + "cell_type": "markdown", + "id": "21a080da", + "metadata": {}, + "source": [ + "Вложенные словари" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "3290938b", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем словарь, ключами которого будут id сотрудников\n", + "# employees = {\n", + "# \"id1\": {\n", + "# \"first name\": \"Александр\",\n", + "# \"last name\": \"Иванов\",\n", + "# \"age\": 30,\n", + "# \"job\": \"программист\",\n", + "# },\n", + "# \"id2\": {\n", + "# \"first name\": \"Ольга\",\n", + "# \"last name\": \"Петрова\",\n", + "# \"age\": 35,\n", + "# \"job\": \"ML-engineer\",\n", + "# },\n", + "# }" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "acbbbe6b", + "metadata": {}, + "outputs": [], + "source": [ + "# а значениями - вложенные словари с информацией о них\n", + "# for v in employees.values():\n", + "# print(v)" + ] + }, + { + "cell_type": "markdown", + "id": "4efdefdf", + "metadata": {}, + "source": [ + "Базовые операции" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "70c64324", + "metadata": {}, + "outputs": [], + "source": [ + "# для того чтобы вывести значение элемента вложенного словаря,\n", + "# воспользуемся двойным ключом\n", + "# employees[\"id1\"][\"age\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "5c440a24", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим информацию о новом сотруднике\n", + "# employees[\"id3\"] = {\n", + "# \"first name\": \"Дарья\",\n", + "# \"last name\": \"Некрасова\",\n", + "# \"age\": 27,\n", + "# \"job\": \"веб-дизайнер\",\n", + "# }\n", + "\n", + "# и выведем обновленный словарь с помощью функции pprint()\n", + "# pprint(employees)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "74425d47", + "metadata": {}, + "outputs": [], + "source": [ + "# изменить значение вложенного словаря можно также с помощью двойного ключа\n", + "# employees[\"id3\"][\"age\"] = 26\n", + "# pprint(employees)" + ] + }, + { + "cell_type": "markdown", + "id": "6cd7b46e", + "metadata": {}, + "source": [ + "Циклы for" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "2c07eaec", + "metadata": {}, + "outputs": [], + "source": [ + "# заменим тип данных в информации о возрасте с int на float\n", + "\n", + "# для этого вначале пройдемся по вложенным словарям,\n", + "# т.е. по значениям info внешнего словаря employees\n", + "# for info in employees.values():\n", + "\n", + "# затем по ключам и значениям вложенного словаря info\n", + "# for k, v in info.items():\n", + "\n", + "# # если ключ совпадет со словом 'age'\n", + "# if k == \"age\":\n", + "\n", + "# преобразуем значение в тип float\n", + "# info[k] = float(v)\n", + "\n", + "# pprint(employees)" + ] + }, + { + "cell_type": "markdown", + "id": "4a3a0644", + "metadata": {}, + "source": [ + "Вложенные словари и dict comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e737480", + "metadata": {}, + "outputs": [], + "source": [ + "# преобразуем обратно из float в int, но уже через\n", + "# dict comprehension\n", + "# для начала просто выведем словарь employees\n", + "# без изменений\n", + "# pprint({id: info for id, info in employees.items()})" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "d2ce28d1", + "metadata": {}, + "outputs": [], + "source": [ + "# а затем заменим значение внешнего словаря info\n", + "# (т.е. вложенный словарь)\n", + "# на еще один dict comprehension с условием if-else\n", + "# pprint(\n", + "# {\n", + "# id: {k: (int(v) if k == \"age\" else v) for k, v in info.items()}\n", + "# for id, info in employees.items()\n", + "# }\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "202ee358", + "metadata": {}, + "outputs": [], + "source": [ + "# а затем заменим значение внешнего словаря info\n", + "# (т.е. вложенный словарь)\n", + "# на еще один dict comprehension с условием if-else\n", + "# pprint(\n", + "# {\n", + "# id: {k: (int(v) if k == \"age\" else v) for k, v in info.items()}\n", + "# for id, info in employees.items()\n", + "# }\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "id": "9529230f", + "metadata": {}, + "source": [ + "Частота слов в тексте" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9ff8bd4", + "metadata": {}, + "outputs": [], + "source": [ + "# возьмем знакомый нам текст\n", + "# corpus = \"When we were in Paris we visited a lot\n", + "# of museums. We first went to the Louvre, the largest\n", + "# art museum in the world. I have always been\n", + "# interested in art so I spent many hours there.\n", + "# The museum is enormous, so a week there would\n", + "# not be enough.\"" + ] + }, + { + "cell_type": "markdown", + "id": "ee361018", + "metadata": {}, + "source": [ + "Предварительная обработка текста " + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "f89a8319", + "metadata": {}, + "outputs": [], + "source": [ + "# разделим его на слова\n", + "# words = corpus.split()\n", + "# print(words)" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "48e6cb87", + "metadata": {}, + "outputs": [], + "source": [ + "# с помощью list comprehension удалим точки,\n", + "# запятые и переведем все слова в нижний регистр\n", + "# words = [word.strip(\".\").strip(\",\").lower() for\n", + "# word in words]\n", + "# print(words)" + ] + }, + { + "cell_type": "markdown", + "id": "8dd71300", + "metadata": {}, + "source": [ + "Способ 1. Условие if-else" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "92431a3a", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим пустой словарь для мешка слов bow\n", + "# bow_1 = {}\n", + "\n", + "# пройдемся по словам текста\n", + "# for word in words:\n", + "\n", + "# если нам встретилось слово, которое уже есть в\n", + "# словаре\n", + "# if word in bow_1:\n", + "\n", + "# увеличим его значение (частоту) на 1\n", + "# bow_1[word] = bow_1[word] + 1\n", + "\n", + "# в противном случае, если слово встречается впервые\n", + "# else:\n", + "\n", + "# зададим ему значение 1\n", + "# bow_1[word] = 1\n", + "\n", + "# отсортируем словарь по значению в убываюем порядке\n", + "# (reverse = True)\n", + "# и выведем шесть наиболее частотных слов\n", + "# sorted(bow_1.items(), key=lambda x: x[1], reverse=True)[:6]" + ] + }, + { + "cell_type": "markdown", + "id": "4ee22ac1", + "metadata": {}, + "source": [ + "Способ 2. Метод .get()" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "0ab552c2", + "metadata": {}, + "outputs": [], + "source": [ + "# bow_2 = {}\n", + "\n", + "# # снова пройдемся в цикле по словам\n", + "# for word in words:\n", + "\n", + "# если слова еще нет в словаре, .get() выведет значение 0, к которому мы прибавим единицу\n", + "# если слово есть, метод .get() выведет существующее значение, например, 2 или 3,\n", + "# и мы также увеличим счетчик на 1\n", + "# bow_2[word] = bow_2.get(word, 0) + 1\n", + "\n", + "# выведем наиболее популярные слова\n", + "# sorted(bow_2.items(), key=lambda x: x[1], reverse=True)[:6]" + ] + }, + { + "cell_type": "markdown", + "id": "54aa8e8a", + "metadata": {}, + "source": [ + "Способ 3. Модуль collections" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "caccbe2e", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим объект этого класса, передав ему список слов\n", + "# bow_3 = Counter(words)\n", + "\n", + "# выведем шесть наиболее часто встречающихся слов с помощью метода .most_common()\n", + "# bow_3.most_common(6)" + ] + }, + { + "cell_type": "markdown", + "id": "a973b0a8", + "metadata": {}, + "source": [ + "Дополнительные материалы" + ] + }, + { + "cell_type": "markdown", + "id": "818862af", + "metadata": {}, + "source": [ + "Неизменяемый тип данных" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "4b0525b8", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим строковый объект\n", + "# string = \"Python\"\n", + "\n", + "# посмотрим на identity, type и value\n", + "# функция id() выводит адрес объекта в памяти компьютера\n", + "# id(string), type(string), string" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "fdc97723", + "metadata": {}, + "outputs": [], + "source": [ + "# попробуем изменить этот объект\n", + "# string = string + \" is cool\"\n", + "\n", + "# посмотрим на identity, type и value\n", + "# id(string), type(string), string" + ] + }, + { + "cell_type": "markdown", + "id": "f7748789", + "metadata": {}, + "source": [ + "Изменяемый тип данных " + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "1af0170f", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим список\n", + "# lst = [1, 2, 3]\n", + "\n", + "# посмотрим на identity, type и value\n", + "# id(lst), type(lst), lst" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "cfa2b1a2", + "metadata": {}, + "outputs": [], + "source": [ + "# добавим элемент в список\n", + "# lst.append(4)\n", + "\n", + "# снова выведем identity, type и value\n", + "# id(lst), type(lst), lst" + ] + }, + { + "cell_type": "markdown", + "id": "086b49c3", + "metadata": {}, + "source": [ + "Копирование объектов" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "7f0909fa", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь создадим строку\n", + "# string = \"Python\"\n", + "\n", + "# скопируем через присваивание\n", + "# string2 = string\n", + "\n", + "# изменим копию\n", + "# string2 = string2 + \" is cool\"\n", + "\n", + "# посмотрим на результат\n", + "# string, string2" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "71649f4e", + "metadata": {}, + "outputs": [], + "source": [ + "# оператор == сравнивает значения (values)\n", + "# оператор is сравнивает identities\n", + "# string == string2, string is string2" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "fcbf8a87", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим список\n", + "# lst = [1, 2, 3]\n", + "\n", + "# скопируем его в новую переменную через присваивание\n", + "# lst2 = lst\n", + "\n", + "# добавим новый элемент в скопированный список\n", + "# lst2.append(4)\n", + "\n", + "# выведем исходный список и копию\n", + "# lst, lst2" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "3897077d", + "metadata": {}, + "outputs": [], + "source": [ + "# убедимся, что речь идет об одном и том же объекте\n", + "# lst == lst2, lst is lst2" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "ea510463", + "metadata": {}, + "outputs": [], + "source": [ + "# вновь создадим список\n", + "# lst = [1, 2, 3]\n", + "\n", + "# скопируем с помощью метода .copy()\n", + "# lst2 = lst.copy()\n", + "\n", + "# добавим новый элемент в скопированный список\n", + "# lst2.append(4)\n", + "\n", + "# выведем исходный список и копию\n", + "# lst, lst2" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "305e71a7", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь сделаем значения списков одинаковыми\n", + "# lst.append(4)\n", + "\n", + "# и убедимся, что это по-прежнему разные объекты\n", + "# lst, lst2, lst == lst2, lst is lst2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_9_dictionaries.py b/python/makarov/chapter_9_dictionaries.py new file mode 100644 index 00000000..de5151a3 --- /dev/null +++ b/python/makarov/chapter_9_dictionaries.py @@ -0,0 +1,650 @@ +"""Словари в Питоне.""" + +# Словари, наряду со списками, кортежами и множествами, относятся к коллекциям, то есть типам данных, содержащим несколько элементов. + +# + +# пустой словарь можно создать с помощью {} или функции dict() +# импортируем класс Counter +# from collections import Counter + +# импортируем функцию pprint() из модуля pprint +# некоторые структуры данных она выводит лучше, чем обычная print() +# from pprint import pprint + +# import numpy as np + +# dict_1 = {} +# dict_2 = dict() +# print(dict_1, dict_2) + +# + +# словарь можно сразу заполнить ключами и значениями +# company = {"name": "Toyota", "founded": 1937, "founder": "Kiichiro Toyoda"} +# company + +# + +# словарь можно создать из вложенных списков +# tickers = dict([["TYO", "Toyota"], ["TSLA", "Tesla"], ["F", "Ford"]]) +# tickers + +# + +# если поместить ключи в кортеж +# keys = ("k1", "k2", "k3") +# и задать значение +# value = 0 + +# то с помощью метода .fromkeys() можно создать словарь +# с этими ключами и заданным значением для каждого из них +# empty_values = dict.fromkeys(keys, value) +# empty_values +# - + +# Ключи и значения словаря + +# Виды значений словаря + +# + +# приведем пример того, какими могут быть значения словаря +# value_types = { +# "k1": 123, +# "k2": "string", +# "k3": np.nan, # тип "Пропущенное значение" +# "k4": True, # логическое значение +# "k5": None, +# "k6": [1, 2, 3], +# "k7": np.array([1, 2, 3]), +# "k8": {1: "v1", 2: "v2", 3: "v3"}, +# } + +# value_types +# - + +# Методы .keys(), .values() и .items() + +# + +# создадим несложный словарь с информацией о сотруднике +# person = {"first name": "Иван", "last name": "Иванов", "born": 1980, "dept": "IT"} + +# + +# посмотрим на ключи и +# person.keys() + +# + +# значения +# person.values() + +# + +# а также на пары ключ-значение в виде списка из кортежей +# person.items() +# - + +# Использование цикла for + +# + +# ключи и значения можно вывести в цикле for +# for k, v in person.items(): +# print(k, v) +# - + +# Доступ по ключу и метод .get() + +# + +# значение можно посмотреть по ключу +# person["last name"] +# если такого ключа нет, Питон выдаст ошибку + +# + +# чтобы этого не произошло, можно использовать метод .get() +# по умолчанию при отсутствии ключа он выводит значение None +# print(person.get("education")) + +# + +# если ключ все-таки есть, .get() выведет соответствующее значение +# person.get("born") +# - + +# Проверка вхождения ключа и значения в словарь + +# + +# проверим есть ли такой ключ +# "born" in person + +# + +# и такое значение +# 1980 in person.values() + +# + +# можно также проверить наличие и ключа, и значения одновременно +# ("born", 1980) in person.items() +# - + +# Операции со словарями + +# Добавление и изменение элементов + +# + +# добавить элемент можно, передав новому ключу новое значение +# обратите внимание, в данном случае новое значение - это список +# person["languages"] = ["Python", "C++"] +# person + +# + +# изменить элемент можно, передав существующему ключу новое значение, +# значение - это по-прежнему список, но из одного элемента +# person["languages"] = ["Python"] +# person + +# + +# возьмем еще один словарь +# new_elements = {"job": "программист", "experience": 7} + +# и присоединим его к существующему словарю с помощью метода .update() +# person.update(new_elements) +# person + +# + +# метод .setdefault() проверит есть ли ключ в словаре, +# если "да", значение не изменится +# person.setdefault("last name", "Петров") +# person + +# + +# если нет, будет добавлен новый ключ и соответствующее значение +# person.setdefault("f_languages", ["русский", "английский"]) +# person +# - + +# Удаление элементов + +# + +# метод .pop() удаляет элемент по ключу и выводит удаляемое значение +# person.pop("dept") + +# + +# мы видим, что пары 'dept' : 'IT' больше нет +# person + +# + +# ключевое слово del также удаляет элемент по ключу +# удаляемое значение не выводится +# del person["born"] + +# + +# метод .popitem() удаляет последний добавленный элемент и выводит его +# person.popitem() + +# + +# метод .clear() удаляет все элементы словаря +# person.clear() +# person +# - + +# Сортировка словарей + +# + +# возьмем несложный словарь +# dict_to_sort = {"k2": 30, "k1": 20, "k3": 10, "k4": 85} + +# отсортируем ключи +# sorted(dict_to_sort) + +# + +# отсортируем значения +# sorted(dict_to_sort.values()) + +# + +# посмотрим на пары ключ : значение +# dict_to_sort.items() + +# + +# для их сортировки по ключу (индекс [0]) +# воспользуемся методом .items() и lambda-функцией +# sorted(dict_to_sort.items(), key=lambda x: x[0]) + +# + +# сортировка по значению выполняется так же, однако +# lambda-функции мы передаем индекс [1] +# sorted(dict_to_sort.items(), key=lambda x: x[1]) +# - + +# Копирование словарей + +# + +# создадим исходный словарь с количеством студентов на +# первом и втором курсах университета +# original = {"Первый курс": 174, "Второй курс": 131} +# - + +# Копирование с помощью метода .copy() + +# + +# создадим копию этого словаря с помощью метода .copy() +# new_1 = original.copy() + +# добавим информацию о третьем курсе в новый словарь +# new_1["Третий курс"] = 117 + +# исходный словарь не изменился +# print(original) +# print(new_1) +# - + +# Копирование через оператор присваивания `=` (так делать не стоит!) + +# + +# передадим исходный словарь в новую переменную +# new_2 = original + +# удалим элементы нового словаря +# new_2.clear() + +# из исходного словаря данные также удалились +# print(original) +# print(new_2) +# - + +# Функция dir() + +# + +# функция dir() возвращает все методы передаваемого ей объекта +# some_dict = {"k": 1} + +# вначале идут специальные методы, +# они начинаются и заканчиваются символом '__' +# выведем первые 11 элементов +# dir(some_dict)[:11] + +# + +# когда мы передаем наш словарь функции print(), +# print(some_dict) + +# + +# на самом деле мы применяем к объекту метод .__str__() +# some_dict.__str__() + +# + +# в большинстве случаев нас будут интересовать методы без '__' +# dir(some_dict)[-11:] +# - + +# Dict comprehension + +# + +# создадим еще один несложный словарь +# source_dict = {"k1": 2, "k2": 4, "k3": 6} + +# + +# с помощью dict comprehension умножим каждое значение на два +# {k: v * 2 for (k, v) in source_dict.items()} + +# + +# сделаем символы всех ключей заглавными +# {k.upper(): v for (k, v) in source_dict.items()} + +# + +# добавим условие, что значение должно быть больше двух И меньше шести +# {k: v for (k, v) in source_dict.items() if v > 2 if v < 6} + +# + +# new_dict = {} + +# при решении этой же задачи в цикле for +# for k, v in source_dict.items(): + +# мы бы использовали логическое И (and) +# if v > 2 and v < 6: + +# если условия верны, записываем ключ и значение в новый словарь +# new_dict[k] = v + +# new_dict + +# + +# условие с if-else ставится в самом начале схемы dict comprehension +# заменим значение на слово even, если оно четное, и odd, если нечетное +# {k: ("even" if v % 2 == 0 else "odd") for (k, v) in source_dict.items()} + +# + +# dict comprehension можно использовать вместо метода .fromkeys() +# keys = ("k1", "k2", "k3") + +# передадим словарю ключи из кортежа keys и зададим значение 0 каждому из них +# {k: 0 for k in keys} +# - + +# Дополнительные примеры + +# lambda-функции, функции map() и zip() + +# Пример со списком + +# + +# возьмем список слов +# words = ["apple", "banana", "fig", "blackberry"] + +# + +# создадим lambda-функцию, которая посчитает длину +# передаваемого ей слова +# с помощью функции map() применим lambda-функцию +# к каждому элементу списка words +# и поместим длины слов в новый список length с помощью +# функции list() +# length = list(map(lambda word: len(word), words)) +# length + +# + +# с помощью функции zip() поэлементно соединим оба +# списка и преобразуем в словарь +# dict(zip(words, length)) + +# + +# то же самое можно сделать с помощью функции zip() +# и list comprehension +# dict(zip(words, [len(word) for word in words])) +# - + +# Пример со словарем + +# + +# возьмем словарь с ростом людей в футах +# height_feet = {"Alex": 6.1, "Jerry": 5.4, "Ben": 5.8} + +# + +# для преобразования футов в метры создадим lambda-функцию +# lambda m: m * 0.3048 +# применим эту функцию к значениям словаря с помощью +# функции map() +# преобразуем в список +# metres = list(map(lambda m: m * 0.3048, height_feet.values())) +# metres + +# + +# с помощью функции zip() соединим ключи исходного +# словаря с элементами списка metres +# dict(zip(height_feet.keys(), np.round(metres, 2))) + +# + +# то же самое можно выполнить с помощью dict +# comprehensions всего в одну строчку +# мы просто преобразуем значения словаря в метры +# {k: np.round(v * 0.3048, 2) for (k, v) in height_feet.items()} +# - + +# Вложенные словари + +# + +# возьмем словарь, ключами которого будут id сотрудников +# employees = { +# "id1": { +# "first name": "Александр", +# "last name": "Иванов", +# "age": 30, +# "job": "программист", +# }, +# "id2": { +# "first name": "Ольга", +# "last name": "Петрова", +# "age": 35, +# "job": "ML-engineer", +# }, +# } + +# + +# а значениями - вложенные словари с информацией о них +# for v in employees.values(): +# print(v) +# - + +# Базовые операции + +# + +# для того чтобы вывести значение элемента вложенного словаря, +# воспользуемся двойным ключом +# employees["id1"]["age"] + +# + +# добавим информацию о новом сотруднике +# employees["id3"] = { +# "first name": "Дарья", +# "last name": "Некрасова", +# "age": 27, +# "job": "веб-дизайнер", +# } + +# и выведем обновленный словарь с помощью функции pprint() +# pprint(employees) + +# + +# изменить значение вложенного словаря можно также с помощью двойного ключа +# employees["id3"]["age"] = 26 +# pprint(employees) +# - + +# Циклы for + +# + +# заменим тип данных в информации о возрасте с int на float + +# для этого вначале пройдемся по вложенным словарям, +# т.е. по значениям info внешнего словаря employees +# for info in employees.values(): + +# затем по ключам и значениям вложенного словаря info +# for k, v in info.items(): + +# # если ключ совпадет со словом 'age' +# if k == "age": + +# преобразуем значение в тип float +# info[k] = float(v) + +# pprint(employees) +# - + +# Вложенные словари и dict comprehension + +# + +# преобразуем обратно из float в int, но уже через +# dict comprehension +# для начала просто выведем словарь employees +# без изменений +# pprint({id: info for id, info in employees.items()}) + +# + +# а затем заменим значение внешнего словаря info +# (т.е. вложенный словарь) +# на еще один dict comprehension с условием if-else +# pprint( +# { +# id: {k: (int(v) if k == "age" else v) for k, v in info.items()} +# for id, info in employees.items() +# } +# ) + +# + +# а затем заменим значение внешнего словаря info +# (т.е. вложенный словарь) +# на еще один dict comprehension с условием if-else +# pprint( +# { +# id: {k: (int(v) if k == "age" else v) for k, v in info.items()} +# for id, info in employees.items() +# } +# ) +# - + +# Частота слов в тексте + +# + +# возьмем знакомый нам текст +# corpus = "When we were in Paris we visited a lot +# of museums. We first went to the Louvre, the largest +# art museum in the world. I have always been +# interested in art so I spent many hours there. +# The museum is enormous, so a week there would +# not be enough." +# - + +# Предварительная обработка текста + +# + +# разделим его на слова +# words = corpus.split() +# print(words) + +# + +# с помощью list comprehension удалим точки, +# запятые и переведем все слова в нижний регистр +# words = [word.strip(".").strip(",").lower() for +# word in words] +# print(words) +# - + +# Способ 1. Условие if-else + +# + +# создадим пустой словарь для мешка слов bow +# bow_1 = {} + +# пройдемся по словам текста +# for word in words: + +# если нам встретилось слово, которое уже есть в +# словаре +# if word in bow_1: + +# увеличим его значение (частоту) на 1 +# bow_1[word] = bow_1[word] + 1 + +# в противном случае, если слово встречается впервые +# else: + +# зададим ему значение 1 +# bow_1[word] = 1 + +# отсортируем словарь по значению в убываюем порядке +# (reverse = True) +# и выведем шесть наиболее частотных слов +# sorted(bow_1.items(), key=lambda x: x[1], reverse=True)[:6] +# - + +# Способ 2. Метод .get() + +# + +# bow_2 = {} + +# # снова пройдемся в цикле по словам +# for word in words: + +# если слова еще нет в словаре, .get() выведет значение 0, к которому мы прибавим единицу +# если слово есть, метод .get() выведет существующее значение, например, 2 или 3, +# и мы также увеличим счетчик на 1 +# bow_2[word] = bow_2.get(word, 0) + 1 + +# выведем наиболее популярные слова +# sorted(bow_2.items(), key=lambda x: x[1], reverse=True)[:6] +# - + +# Способ 3. Модуль collections + +# + +# создадим объект этого класса, передав ему список слов +# bow_3 = Counter(words) + +# выведем шесть наиболее часто встречающихся слов с помощью метода .most_common() +# bow_3.most_common(6) +# - + +# Дополнительные материалы + +# Неизменяемый тип данных + +# + +# создадим строковый объект +# string = "Python" + +# посмотрим на identity, type и value +# функция id() выводит адрес объекта в памяти компьютера +# id(string), type(string), string + +# + +# попробуем изменить этот объект +# string = string + " is cool" + +# посмотрим на identity, type и value +# id(string), type(string), string +# - + +# Изменяемый тип данных + +# + +# создадим список +# lst = [1, 2, 3] + +# посмотрим на identity, type и value +# id(lst), type(lst), lst + +# + +# добавим элемент в список +# lst.append(4) + +# снова выведем identity, type и value +# id(lst), type(lst), lst +# - + +# Копирование объектов + +# + +# вновь создадим строку +# string = "Python" + +# скопируем через присваивание +# string2 = string + +# изменим копию +# string2 = string2 + " is cool" + +# посмотрим на результат +# string, string2 + +# + +# оператор == сравнивает значения (values) +# оператор is сравнивает identities +# string == string2, string is string2 + +# + +# создадим список +# lst = [1, 2, 3] + +# скопируем его в новую переменную через присваивание +# lst2 = lst + +# добавим новый элемент в скопированный список +# lst2.append(4) + +# выведем исходный список и копию +# lst, lst2 + +# + +# убедимся, что речь идет об одном и том же объекте +# lst == lst2, lst is lst2 + +# + +# вновь создадим список +# lst = [1, 2, 3] + +# скопируем с помощью метода .copy() +# lst2 = lst.copy() + +# добавим новый элемент в скопированный список +# lst2.append(4) + +# выведем исходный список и копию +# lst, lst2 + +# + +# теперь сделаем значения списков одинаковыми +# lst.append(4) + +# и убедимся, что это по-прежнему разные объекты +# lst, lst2, lst == lst2, lst is lst2 From c3ad2652ec53dd57db0798dbdc77d4e958e03c53 Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 21:09:25 +0500 Subject: [PATCH 23/24] task 1 decorators --- python/makarov/chapter_16_decorators.ipynb | 1227 ++++++++++++++++++++ python/makarov/chapter_16_decorators.py | 547 +++++++++ 2 files changed, 1774 insertions(+) create mode 100644 python/makarov/chapter_16_decorators.ipynb create mode 100644 python/makarov/chapter_16_decorators.py diff --git a/python/makarov/chapter_16_decorators.ipynb b/python/makarov/chapter_16_decorators.ipynb new file mode 100644 index 00000000..46c7dd9a --- /dev/null +++ b/python/makarov/chapter_16_decorators.ipynb @@ -0,0 +1,1227 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d9ba23ec", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Декораторы.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "9bdbe52a", + "metadata": {}, + "source": [ + "Декораторы в Питон позволяют расширять и изменять поведение вызываемых объектов (функций, методов и классов) без постоянного изменения самого вызываемого объекта." + ] + }, + { + "cell_type": "markdown", + "id": "d7b0251d", + "metadata": {}, + "source": [ + "Присвоение функции переменной " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9d8cb500", + "metadata": {}, + "outputs": [], + "source": [ + "# объявим функцию\n", + "# import functools\n", + "# import time\n", + "\n", + "\n", + "# def say_congratulations(name):\n", + "# print(f\"Congratulations, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "23cb632b", + "metadata": {}, + "outputs": [], + "source": [ + "# присвоим эту функцию переменной\n", + "# say_congratulations_function = say_congratulations\n", + "# вызовем функцию из новой переменной\n", + "# say_congratulations_function(\"Svetlana\")" + ] + }, + { + "cell_type": "markdown", + "id": "d915513a", + "metadata": {}, + "source": [ + "Передача функции в качестве аргумента\n", + "\n", + "Создадим калькулятор, который на входе будет принимать функцию-операцию, а также компоненты математических выражений." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "dceb2b6d", + "metadata": {}, + "outputs": [], + "source": [ + "# def simple_calculator(operation, a, b):\n", + "# return operation(a, b)\n", + "\n", + "\n", + "# def add(a, b):\n", + "# return a + b\n", + "\n", + "\n", + "# def subtract(a, b):\n", + "# return a - b\n", + "\n", + "\n", + "# def multiply(a, b):\n", + "# return a * b\n", + "\n", + "\n", + "# def divide(a, b):\n", + "# return a / b" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2980be81", + "metadata": {}, + "outputs": [], + "source": [ + "# simple_calculator(divide, 5, 8)" + ] + }, + { + "cell_type": "markdown", + "id": "7e38bc23", + "metadata": {}, + "source": [ + "Внутрение функции\n", + "\n", + "Внутренние (inner) или вложенные (nested) функции представляют собой функции, объявленные и вызванные внутри других функций.\n", + "\n", + "Объявим внешнюю и внутреннюю функции." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0c94d596", + "metadata": {}, + "outputs": [], + "source": [ + "# def outer():\n", + "# print(\"Вызов внешней функции.\")\n", + "\n", + "# обратите внимание, мы объявляем, а затем\n", + "# def inner():\n", + "# print(\"Вызов внутренней функции.\")\n", + "\n", + "# вызываем внутреннюю функцию\n", + "# inner()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "fb3bd6c7", + "metadata": {}, + "outputs": [], + "source": [ + "# outer()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50da0496", + "metadata": {}, + "outputs": [], + "source": [ + "# inner()\n", + "# вызвать внутреннюю функцию не получится" + ] + }, + { + "cell_type": "markdown", + "id": "4b9767cf", + "metadata": {}, + "source": [ + "Возвращение функции из функции\n", + "Функция может возвращать другую функцию. В примере ниже функция create_multiplier() создает множитель (factor) для передаваемого во внутреннюю функцию multiplier() числа (number)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7adf8296", + "metadata": {}, + "outputs": [], + "source": [ + "# def create_multiplier(factor):\n", + "# def multiplier(number):\n", + "# return number * factor\n", + "\n", + "# return multiplier" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bc2ea93", + "metadata": {}, + "outputs": [], + "source": [ + "# double = create_multiplier(factor=2)\n", + "# triple = create_multiplier(factor=4)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8581dcca", + "metadata": {}, + "outputs": [], + "source": [ + "# double" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "a15ee271", + "metadata": {}, + "outputs": [], + "source": [ + "# double(number=7), triple(number=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "fea8ccbb", + "metadata": {}, + "outputs": [], + "source": [ + "# Заметим, что код в примере выше можно сократить с помощью lambda-функции\n", + "\n", + "\n", + "# def create_multiplier(factor):\n", + "# return lambda number: factor * number" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7cb319cd", + "metadata": {}, + "outputs": [], + "source": [ + "# triple = create_multiplier(factor=3)\n", + "# triple(number=2)" + ] + }, + { + "cell_type": "markdown", + "id": "eeb80237", + "metadata": {}, + "source": [ + "Замыкание\n", + "В примере выше внутренняя функция multiplier() может получить доступ к переменной factor внешней функции create_multiplier() даже после того, как внешняя функция уже выполнена.\n", + "\n", + "В этом случае говорят о замыкании (closure) внутренней функции внешней или охватываемой (enclosed) функции." + ] + }, + { + "cell_type": "markdown", + "id": "9699bd2d", + "metadata": {}, + "source": [ + "Простой декоратор " + ] + }, + { + "cell_type": "markdown", + "id": "77282888", + "metadata": {}, + "source": [ + "Соберем показанные выше приемы в общую конструкцию. Объявим обычные (внешние) функции simple_decorator() и say_hello(), а также внутреннюю функцию-замыкание wrapper(), которая будет выводить текст до и после вызова функции func(), передаваемой в качестве аргумента." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "15fed84c", + "metadata": {}, + "outputs": [], + "source": [ + "# def simple_decorator(func):\n", + "# def wrapper():\n", + "# print(\"Текст до вызова функции func().\")\n", + "# func()\n", + "# print(\"Текст после вызова функции func().\")\n", + "\n", + "# return wrapper\n", + "\n", + "\n", + "# def say_hello():\n", + "# print(\"Привет!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b1ec23cb", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello = simple_decorator(say_hello)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "46162208", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello()" + ] + }, + { + "cell_type": "markdown", + "id": "9ff2ad53", + "metadata": {}, + "source": [ + "Конструкция @decorator\n", + "Такого же результата можно достичь благодаря использованию так называемого синтаксического сахара (syntactic sugar) или, говоря иначе, шаблона, упрощающего применение декоратора.\n", + "\n", + "В частности, вызовем декоратор с использованием символа @ непосредственно перед объявлением декорируемой функции." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "510ae057", + "metadata": {}, + "outputs": [], + "source": [ + "# @simple_decorator\n", + "# def say_hi():\n", + "# print(\"Снова, привет!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d3d18605", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hi()" + ] + }, + { + "cell_type": "markdown", + "id": "cf299778", + "metadata": {}, + "source": [ + "Функции с аргументами\n", + "Рассмотрим функцию с аргументом и применим к ней simple_decorator()." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d016b320", + "metadata": {}, + "outputs": [], + "source": [ + "# @simple_decorator\n", + "# def say_hello_with_name(name):\n", + "# print(f\"Привет, {name}!\")" + ] + }, + { + "cell_type": "markdown", + "id": "61ae7d27", + "metadata": {}, + "source": [ + "При попытке вызова декорируемой функции произойдет ошибка, поскольку внутренняя функция wrapper() не принимает аргументов." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae825cf4", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello_with_name('Алексей')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "a05be4d8", + "metadata": {}, + "outputs": [], + "source": [ + "# Исправим это.\n", + "\n", + "\n", + "# def decorator_with_name_argument(func):\n", + "# def wrapper(name):\n", + "# print(\"Текст до вызова функции func().\")\n", + "# func(name)\n", + "# print(\"Текст после вызова функции func().\")\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "3d5e1108", + "metadata": {}, + "outputs": [], + "source": [ + "# @decorator_with_name_argument\n", + "# def say_hello_with_name(name):\n", + "# print(f\"Привет, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d8ea74f8", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello_with_name(\"Алексей\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "ed4c5f85", + "metadata": {}, + "outputs": [], + "source": [ + "# def decorator_with_arguments(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# print(\"Текст до вызова функции func().\")\n", + "# func(*args, **kwargs)\n", + "# print(\"Текст после вызова функции func().\")\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "234bcebc", + "metadata": {}, + "outputs": [], + "source": [ + "# @decorator_with_arguments\n", + "# def say_hello_with_argument(name):\n", + "# print(f\"Привет, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "8aa83de0", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello_with_argument(\"Алексей\")" + ] + }, + { + "cell_type": "markdown", + "id": "0531c389", + "metadata": {}, + "source": [ + "Возвращение значения декорируемой функции\n", + "Объявим функцию return_name() и декорируем ее с помощью another_decorator()." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "15f33f7d", + "metadata": {}, + "outputs": [], + "source": [ + "# def another_decorator(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# print(\"Текст внутренней функции.\")\n", + "# func(*args, **kwargs)\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "45c3aaac", + "metadata": {}, + "outputs": [], + "source": [ + "# @another_decorator\n", + "# def return_name(name):\n", + "# return name" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "6474b14a", + "metadata": {}, + "outputs": [], + "source": [ + "# returned_value = return_name(\"Алексей\")" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "ac4aaaa7", + "metadata": {}, + "outputs": [], + "source": [ + "# print(returned_value)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "fd639c0c", + "metadata": {}, + "outputs": [], + "source": [ + "# def another_decorator(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# print(\"Текст внутренней функции.\")\n", + "# return func(*args, **kwargs) # внутренняя функция возвращает func()\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "becbce5d", + "metadata": {}, + "outputs": [], + "source": [ + "# @another_decorator\n", + "# def return_name(name):\n", + "# return name" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "073e5014", + "metadata": {}, + "outputs": [], + "source": [ + "# returned_value = return_name(\"Алексей\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "94340518", + "metadata": {}, + "outputs": [], + "source": [ + "# print(returned_value)" + ] + }, + { + "cell_type": "markdown", + "id": "9820053c", + "metadata": {}, + "source": [ + "Декоратор @functools.wraps\n", + "Питон содержит инструменты для интроспекции (introspection), которые позволяют исследовать уже созданный объект. В частности, функция type() возвращает тип объекта;\n", + "dir() выводит список атрибутов и методов объекта;\n", + "id() возвращает уникальный идентификатор.\n", + "Кроме этого, в частности, для функции мы можем вывести ее имя с помощью атрибута __name__ и, при наличии, документацию через атрибут __doc__." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "60e8bb71", + "metadata": {}, + "outputs": [], + "source": [ + "# def square(x):\n", + "# \"\"\"Squares a number\"\"\"\n", + "# return x * x" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "b0a9acfc", + "metadata": {}, + "outputs": [], + "source": [ + "# square.__name__, square.__doc__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "646b2e66", + "metadata": {}, + "outputs": [], + "source": [ + "# def repeat_twice(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# func(*args, **kwargs)\n", + "# func(*args, **kwargs)\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "917d15f9", + "metadata": {}, + "outputs": [], + "source": [ + "# @repeat_twice\n", + "# def square(x):\n", + "# \"\"\"Squares a number\"\"\"\n", + "# return x * x" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "ac4c2191", + "metadata": {}, + "outputs": [], + "source": [ + "# square(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "89f45436", + "metadata": {}, + "outputs": [], + "source": [ + "# square.__name__, square.__doc__" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "6b22030d", + "metadata": {}, + "outputs": [], + "source": [ + "# def repeat_twice(func):\n", + "# @functools.wraps(func)\n", + "# def wrapper(*args, **kwargs):\n", + "# func(*args, **kwargs)\n", + "# func(*args, **kwargs)\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "61b40b00", + "metadata": {}, + "outputs": [], + "source": [ + "# @repeat_twice\n", + "# def square(x):\n", + "# \"\"\"Squares a number\"\"\"\n", + "# print(x * x)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "9b9057de", + "metadata": {}, + "outputs": [], + "source": [ + "# square.__name__, square.__doc__" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "0117e4a5", + "metadata": {}, + "outputs": [], + "source": [ + "# square.__wrapped__" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "1619792a", + "metadata": {}, + "outputs": [], + "source": [ + "# def repeat_twice(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# func(*args, **kwargs)\n", + "# func(*args, **kwargs)\n", + "\n", + "# functools.update_wrapper(wrapper, func)\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "a18c0bfd", + "metadata": {}, + "outputs": [], + "source": [ + "# @repeat_twice\n", + "# def power(x, n):\n", + "# \"\"\"Raises to a power\"\"\"\n", + "# print(x**n)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "2578545a", + "metadata": {}, + "outputs": [], + "source": [ + "# power(2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "8dc43e8d", + "metadata": {}, + "outputs": [], + "source": [ + "# power.__doc__" + ] + }, + { + "cell_type": "markdown", + "id": "0f653795", + "metadata": {}, + "source": [ + "Примеры декораторов\n", + "Декоратор можно использовать для выведения (и записи) информации о вызове функции (логирования)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "c9063d55", + "metadata": {}, + "outputs": [], + "source": [ + "# def logging(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# print(f\"Calling {func.__name__} with args: {args}, kwargs: {kwargs}\")\n", + "# result = func(*args, **kwargs)\n", + "# print(f\"{func.__name__} returned: {result}\")\n", + "# return result\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "ff215b51", + "metadata": {}, + "outputs": [], + "source": [ + "# @logging\n", + "# def power(x, n):\n", + "# return x**n\n", + "\n", + "\n", + "# power(5, 3)" + ] + }, + { + "cell_type": "markdown", + "id": "153f5b9d", + "metadata": {}, + "source": [ + "Время исполнения функции" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "8f6f5f22", + "metadata": {}, + "outputs": [], + "source": [ + "# def timer(func):\n", + "# def wrapper(*args, **kwargs):\n", + "# start_time = time.time()\n", + "# result = func(*args, **kwargs)\n", + "# end_time = time.time()\n", + "# print(f\"{func.__name__} executed in {end_time - start_time:.4f} #\n", + "# seconds\")\n", + "# return result\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "50b98387", + "metadata": {}, + "outputs": [], + "source": [ + "# @timer\n", + "# def delayed_function(t):\n", + "# time.sleep(t)\n", + "# return \"execution completed\"\n", + "\n", + "\n", + "# delayed_function(2)" + ] + }, + { + "cell_type": "markdown", + "id": "2c4ab570", + "metadata": {}, + "source": [ + "Типы методов \n", + "Методы экземпляра " + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "c5cfef2f", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# self.type_ = \"cat\"\n", + "\n", + "# def info(self):\n", + "# print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "56a1e356", + "metadata": {}, + "outputs": [], + "source": [ + "# cat = CatClass(color=\"black\")\n", + "# cat.info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f61a8ca", + "metadata": {}, + "outputs": [], + "source": [ + "# CatClass.info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4857963", + "metadata": {}, + "outputs": [], + "source": [ + "# CatClass.color" + ] + }, + { + "cell_type": "markdown", + "id": "a6253aa8", + "metadata": {}, + "source": [ + "Методы класса " + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "23f86858", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# species = \"кошка\" # переменная класса доступна\n", + "# всем экземлярам\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "\n", + "# def info(self):\n", + "# print(self.color)\n", + "\n", + "# @classmethod\n", + "# def get_species(cls):\n", + "# print(cls.species)\n", + "# нет доступа к переменным color и type_" + ] + }, + { + "cell_type": "markdown", + "id": "212db27a", + "metadata": {}, + "source": [ + "Статические методы" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "3aca761c", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# species = \"кошка\"\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# self.type_ = \"cat\"\n", + "\n", + "# def info(self):\n", + "# print(self.color, self.type_)\n", + "\n", + "# @classmethod\n", + "# def get_species(cls):\n", + "# print(cls.species)\n", + "# нет доступа к переменным color и type_\n", + "\n", + "# @staticmethod\n", + "# def convert_to_pounds(x):\n", + "# print(f\"{x} kg is approximately {x * 2.205} pounds\")\n", + "# нет доступа к переменным species, color и type_" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "8906dec5", + "metadata": {}, + "outputs": [], + "source": [ + "# CatClass.convert_to_pounds(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "50d920cf", + "metadata": {}, + "outputs": [], + "source": [ + "# cat = CatClass(\"gray\")\n", + "# cat.convert_to_pounds(5)" + ] + }, + { + "cell_type": "markdown", + "id": "859fb106", + "metadata": {}, + "source": [ + "Декорирование класса\n", + "Декорирование методов" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "a370f959", + "metadata": {}, + "outputs": [], + "source": [ + "# class CatClass:\n", + "\n", + "# @logging\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# self.type_ = \"cat\"\n", + "\n", + "# @timer\n", + "# def info(self):\n", + "# time.sleep(2)\n", + "# print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "3c693e0d", + "metadata": {}, + "outputs": [], + "source": [ + "# cat = CatClass(\"black\")" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "e4f3d861", + "metadata": {}, + "outputs": [], + "source": [ + "# cat.info()" + ] + }, + { + "cell_type": "markdown", + "id": "26080aaf", + "metadata": {}, + "source": [ + "Декорирование всего класса" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "76d64c25", + "metadata": {}, + "outputs": [], + "source": [ + "# @timer\n", + "# class CatClass:\n", + "\n", + "# def __init__(self, color):\n", + "# self.color = color\n", + "# self.type_ = \"cat\"\n", + "\n", + "# def info(self):\n", + "# time.sleep(2)\n", + "# print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "96fc63a6", + "metadata": {}, + "outputs": [], + "source": [ + "# cat = CatClass(\"gray\")" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "1f60e693", + "metadata": {}, + "outputs": [], + "source": [ + "# cat.info()" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "0f63801a", + "metadata": {}, + "outputs": [], + "source": [ + "# setattr(cat, \"weight\", 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "5065045a", + "metadata": {}, + "outputs": [], + "source": [ + "# cat.weight, getattr(cat, \"weight\")" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "30232f10", + "metadata": {}, + "outputs": [], + "source": [ + "# def add_attribute(attribute_name, attribute_value):\n", + "# def wrapper(cls):\n", + "# setattr(cls, attribute_name, attribute_value)\n", + "# return cls\n", + "\n", + "# return wrapper" + ] + }, + { + "cell_type": "markdown", + "id": "bab34af9", + "metadata": {}, + "source": [ + "Несколько декораторов" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "f1b5e113", + "metadata": {}, + "outputs": [], + "source": [ + "# @logging\n", + "# @timer\n", + "# def delayed_function(t):\n", + "# time.sleep(t)\n", + "# return \"execution completed\"" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "e9356b00", + "metadata": {}, + "outputs": [], + "source": [ + "# delayed_function(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5cbe6bb", + "metadata": {}, + "outputs": [], + "source": [ + "# не забудем заново объявить функцию без декораторов\n", + "\n", + "\n", + "# def delayed_function(t):\n", + "# time.sleep(t)\n", + "# return \"execution completed\"" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "94bca6f9", + "metadata": {}, + "outputs": [], + "source": [ + "# delayed_function = logging(timer(delayed_function))\n", + "# delayed_function(2)" + ] + }, + { + "cell_type": "markdown", + "id": "9183edf2", + "metadata": {}, + "source": [ + "Декораторы с аргументами" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "a0ac6234", + "metadata": {}, + "outputs": [], + "source": [ + "# def repeat(n_times):\n", + "# def inner_decorator(func):\n", + "# @functools.wraps(func)\n", + "# def wrapper(*args, **kwargs):\n", + "# for _ in range(n_times):\n", + "# func(*args, **kwargs)\n", + "\n", + "# return wrapper\n", + "\n", + "# return inner_decorator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f81eba3a", + "metadata": {}, + "outputs": [], + "source": [ + "# @repeat(n_times=3)\n", + "# def say_hello(name):\n", + "# print(f\"Привет, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "5cad977a", + "metadata": {}, + "outputs": [], + "source": [ + "# say_hello(\"Алексей\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_16_decorators.py b/python/makarov/chapter_16_decorators.py new file mode 100644 index 00000000..8135239b --- /dev/null +++ b/python/makarov/chapter_16_decorators.py @@ -0,0 +1,547 @@ +"""Декораторы.""" + +# Декораторы в Питон позволяют расширять и изменять поведение вызываемых объектов (функций, методов и классов) без постоянного изменения самого вызываемого объекта. + +# Присвоение функции переменной + +# + +# объявим функцию +# import functools +# import time + + +# def say_congratulations(name): +# print(f"Congratulations, {name}!") + +# + +# присвоим эту функцию переменной +# say_congratulations_function = say_congratulations +# вызовем функцию из новой переменной +# say_congratulations_function("Svetlana") +# - + +# Передача функции в качестве аргумента +# +# Создадим калькулятор, который на входе будет принимать функцию-операцию, а также компоненты математических выражений. + +# + +# def simple_calculator(operation, a, b): +# return operation(a, b) + + +# def add(a, b): +# return a + b + + +# def subtract(a, b): +# return a - b + + +# def multiply(a, b): +# return a * b + + +# def divide(a, b): +# return a / b + +# + +# simple_calculator(divide, 5, 8) +# - + +# Внутрение функции +# +# Внутренние (inner) или вложенные (nested) функции представляют собой функции, объявленные и вызванные внутри других функций. +# +# Объявим внешнюю и внутреннюю функции. + +# + +# def outer(): +# print("Вызов внешней функции.") + +# обратите внимание, мы объявляем, а затем +# def inner(): +# print("Вызов внутренней функции.") + +# вызываем внутреннюю функцию +# inner() + +# + +# outer() + +# + +# inner() +# вызвать внутреннюю функцию не получится +# - + +# Возвращение функции из функции +# Функция может возвращать другую функцию. В примере ниже функция create_multiplier() создает множитель (factor) для передаваемого во внутреннюю функцию multiplier() числа (number). + +# + +# def create_multiplier(factor): +# def multiplier(number): +# return number * factor + +# return multiplier + +# + +# double = create_multiplier(factor=2) +# triple = create_multiplier(factor=4) + +# + +# double + +# + +# double(number=7), triple(number=2) + +# + +# Заметим, что код в примере выше можно сократить с помощью lambda-функции + + +# def create_multiplier(factor): +# return lambda number: factor * number + +# + +# triple = create_multiplier(factor=3) +# triple(number=2) +# - + +# Замыкание +# В примере выше внутренняя функция multiplier() может получить доступ к переменной factor внешней функции create_multiplier() даже после того, как внешняя функция уже выполнена. +# +# В этом случае говорят о замыкании (closure) внутренней функции внешней или охватываемой (enclosed) функции. + +# Простой декоратор + +# Соберем показанные выше приемы в общую конструкцию. Объявим обычные (внешние) функции simple_decorator() и say_hello(), а также внутреннюю функцию-замыкание wrapper(), которая будет выводить текст до и после вызова функции func(), передаваемой в качестве аргумента. + +# + +# def simple_decorator(func): +# def wrapper(): +# print("Текст до вызова функции func().") +# func() +# print("Текст после вызова функции func().") + +# return wrapper + + +# def say_hello(): +# print("Привет!") + +# + +# say_hello = simple_decorator(say_hello) + +# + +# say_hello() +# - + +# Конструкция @decorator +# Такого же результата можно достичь благодаря использованию так называемого синтаксического сахара (syntactic sugar) или, говоря иначе, шаблона, упрощающего применение декоратора. +# +# В частности, вызовем декоратор с использованием символа @ непосредственно перед объявлением декорируемой функции. + +# + +# @simple_decorator +# def say_hi(): +# print("Снова, привет!") + +# + +# say_hi() +# - + +# Функции с аргументами +# Рассмотрим функцию с аргументом и применим к ней simple_decorator(). + +# + +# @simple_decorator +# def say_hello_with_name(name): +# print(f"Привет, {name}!") +# - + +# При попытке вызова декорируемой функции произойдет ошибка, поскольку внутренняя функция wrapper() не принимает аргументов. + +# + +# say_hello_with_name('Алексей') + +# + +# Исправим это. + + +# def decorator_with_name_argument(func): +# def wrapper(name): +# print("Текст до вызова функции func().") +# func(name) +# print("Текст после вызова функции func().") + +# return wrapper + +# + +# @decorator_with_name_argument +# def say_hello_with_name(name): +# print(f"Привет, {name}!") + +# + +# say_hello_with_name("Алексей") + +# + +# def decorator_with_arguments(func): +# def wrapper(*args, **kwargs): +# print("Текст до вызова функции func().") +# func(*args, **kwargs) +# print("Текст после вызова функции func().") + +# return wrapper + +# + +# @decorator_with_arguments +# def say_hello_with_argument(name): +# print(f"Привет, {name}!") + +# + +# say_hello_with_argument("Алексей") +# - + +# Возвращение значения декорируемой функции +# Объявим функцию return_name() и декорируем ее с помощью another_decorator(). + +# + +# def another_decorator(func): +# def wrapper(*args, **kwargs): +# print("Текст внутренней функции.") +# func(*args, **kwargs) + +# return wrapper + +# + +# @another_decorator +# def return_name(name): +# return name + +# + +# returned_value = return_name("Алексей") + +# + +# print(returned_value) + +# + +# def another_decorator(func): +# def wrapper(*args, **kwargs): +# print("Текст внутренней функции.") +# return func(*args, **kwargs) # внутренняя функция возвращает func() + +# return wrapper + +# + +# @another_decorator +# def return_name(name): +# return name + +# + +# returned_value = return_name("Алексей") + +# + +# print(returned_value) +# - + +# Декоратор @functools.wraps +# Питон содержит инструменты для интроспекции (introspection), которые позволяют исследовать уже созданный объект. В частности, функция type() возвращает тип объекта; +# dir() выводит список атрибутов и методов объекта; +# id() возвращает уникальный идентификатор. +# Кроме этого, в частности, для функции мы можем вывести ее имя с помощью атрибута __name__ и, при наличии, документацию через атрибут __doc__. + +# + +# def square(x): +# """Squares a number""" +# return x * x + +# + +# square.__name__, square.__doc__ + +# + +# def repeat_twice(func): +# def wrapper(*args, **kwargs): +# func(*args, **kwargs) +# func(*args, **kwargs) + +# return wrapper + +# + +# @repeat_twice +# def square(x): +# """Squares a number""" +# return x * x + +# + +# square(3) + +# + +# square.__name__, square.__doc__ + +# + +# def repeat_twice(func): +# @functools.wraps(func) +# def wrapper(*args, **kwargs): +# func(*args, **kwargs) +# func(*args, **kwargs) + +# return wrapper + +# + +# @repeat_twice +# def square(x): +# """Squares a number""" +# print(x * x) + +# + +# square.__name__, square.__doc__ + +# + +# square.__wrapped__ + +# + +# def repeat_twice(func): +# def wrapper(*args, **kwargs): +# func(*args, **kwargs) +# func(*args, **kwargs) + +# functools.update_wrapper(wrapper, func) +# return wrapper + +# + +# @repeat_twice +# def power(x, n): +# """Raises to a power""" +# print(x**n) + +# + +# power(2, 3) + +# + +# power.__doc__ +# - + +# Примеры декораторов +# Декоратор можно использовать для выведения (и записи) информации о вызове функции (логирования) + +# + +# def logging(func): +# def wrapper(*args, **kwargs): +# print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}") +# result = func(*args, **kwargs) +# print(f"{func.__name__} returned: {result}") +# return result + +# return wrapper + +# + +# @logging +# def power(x, n): +# return x**n + + +# power(5, 3) +# - + +# Время исполнения функции + +# + +# def timer(func): +# def wrapper(*args, **kwargs): +# start_time = time.time() +# result = func(*args, **kwargs) +# end_time = time.time() +# print(f"{func.__name__} executed in {end_time - start_time:.4f} # +# seconds") +# return result + +# return wrapper + +# + +# @timer +# def delayed_function(t): +# time.sleep(t) +# return "execution completed" + + +# delayed_function(2) +# - + +# Типы методов +# Методы экземпляра + +# + +# class CatClass: + +# def __init__(self, color): +# self.color = color +# self.type_ = "cat" + +# def info(self): +# print(self.color, self.type_, sep=", ") + +# + +# cat = CatClass(color="black") +# cat.info() + +# + +# CatClass.info() + +# + +# CatClass.color +# - + +# Методы класса + +# + +# class CatClass: + +# species = "кошка" # переменная класса доступна +# всем экземлярам + +# def __init__(self, color): +# self.color = color + +# def info(self): +# print(self.color) + +# @classmethod +# def get_species(cls): +# print(cls.species) +# нет доступа к переменным color и type_ +# - + +# Статические методы + +# + +# class CatClass: + +# species = "кошка" + +# def __init__(self, color): +# self.color = color +# self.type_ = "cat" + +# def info(self): +# print(self.color, self.type_) + +# @classmethod +# def get_species(cls): +# print(cls.species) +# нет доступа к переменным color и type_ + +# @staticmethod +# def convert_to_pounds(x): +# print(f"{x} kg is approximately {x * 2.205} pounds") +# нет доступа к переменным species, color и type_ + +# + +# CatClass.convert_to_pounds(4) + +# + +# cat = CatClass("gray") +# cat.convert_to_pounds(5) +# - + +# Декорирование класса +# Декорирование методов + +# + +# class CatClass: + +# @logging +# def __init__(self, color): +# self.color = color +# self.type_ = "cat" + +# @timer +# def info(self): +# time.sleep(2) +# print(self.color, self.type_, sep=", ") + +# + +# cat = CatClass("black") + +# + +# cat.info() +# - + +# Декорирование всего класса + +# + +# @timer +# class CatClass: + +# def __init__(self, color): +# self.color = color +# self.type_ = "cat" + +# def info(self): +# time.sleep(2) +# print(self.color, self.type_, sep=", ") + +# + +# cat = CatClass("gray") + +# + +# cat.info() + +# + +# setattr(cat, "weight", 5) + +# + +# cat.weight, getattr(cat, "weight") + +# + +# def add_attribute(attribute_name, attribute_value): +# def wrapper(cls): +# setattr(cls, attribute_name, attribute_value) +# return cls + +# return wrapper +# - + +# Несколько декораторов + +# + +# @logging +# @timer +# def delayed_function(t): +# time.sleep(t) +# return "execution completed" + +# + +# delayed_function(2) + +# + +# не забудем заново объявить функцию без декораторов + + +# def delayed_function(t): +# time.sleep(t) +# return "execution completed" + +# + +# delayed_function = logging(timer(delayed_function)) +# delayed_function(2) +# - + +# Декораторы с аргументами + +# + +# def repeat(n_times): +# def inner_decorator(func): +# @functools.wraps(func) +# def wrapper(*args, **kwargs): +# for _ in range(n_times): +# func(*args, **kwargs) + +# return wrapper + +# return inner_decorator + +# + +# @repeat(n_times=3) +# def say_hello(name): +# print(f"Привет, {name}!") + +# + +# say_hello("Алексей") From 6fcaed12df3da9552b03c68bb17630e13ea0d3cf Mon Sep 17 00:00:00 2001 From: Svetlana Sabitova Date: Mon, 13 Apr 2026 21:29:36 +0500 Subject: [PATCH 24/24] task 1 oop --- python/oop.ipynb | 827 +++++++++++++++++++++++++++++++++++++++++++++++ python/oop.py | 287 ++++++++++++++++ 2 files changed, 1114 insertions(+) create mode 100644 python/oop.ipynb create mode 100644 python/oop.py diff --git a/python/oop.ipynb b/python/oop.ipynb new file mode 100644 index 00000000..93c7b9cf --- /dev/null +++ b/python/oop.ipynb @@ -0,0 +1,827 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cba6231b", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Объектно-ориентированное программирование.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "eced2943", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим класс Person\n", + "\n", + "\n", + "# class Person:\n", + "# name = \"Svetlana\"\n", + "\n", + "\n", + "# Person.name" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "834e3405", + "metadata": {}, + "outputs": [], + "source": [ + "# Person.__name__ # возвращает название класса" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "882c22e8", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим доступные атрибуты\n", + "# dir(Person)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7bccbd4c", + "metadata": {}, + "outputs": [], + "source": [ + "# определим принадлежность класса\n", + "# Person.__class__" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ef36a067", + "metadata": {}, + "outputs": [], + "source": [ + "# создадим экземпляр класса Person\n", + "# p = Person()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0744f2a4", + "metadata": {}, + "outputs": [], + "source": [ + "# s = Person()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "011c3429", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на класс, к которому относится этот экземпляр\n", + "# p.__class__" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1c00eac4", + "metadata": {}, + "outputs": [], + "source": [ + "# или\n", + "# p.__class__.__name__" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "92012231", + "metadata": {}, + "outputs": [], + "source": [ + "# так же можно использовать функцию type()\n", + "# type(p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eafa7b3a", + "metadata": {}, + "outputs": [], + "source": [ + "# создание нового экземпляра через функцию type()\n", + "# new_person = type(p)() # новый экземпляр того же типа, что и объект р" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "73d16047", + "metadata": {}, + "outputs": [], + "source": [ + "# new_person" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "fa8e03e6", + "metadata": {}, + "outputs": [], + "source": [ + "# сравним id\n", + "# id(p)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8b15d501", + "metadata": {}, + "outputs": [], + "source": [ + "# id(new_person)" + ] + }, + { + "cell_type": "markdown", + "id": "8f3d797c", + "metadata": {}, + "source": [ + "Свойства и атрибуты классов" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "4dc6c0f5", + "metadata": {}, + "outputs": [], + "source": [ + "# class People:\n", + "# name = \"Ivanka\"\n", + "\n", + "\n", + "# dir(People)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "0505d0f3", + "metadata": {}, + "outputs": [], + "source": [ + "# пространство имен класса и экземпляров класса\n", + "# People.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3bf4195f", + "metadata": {}, + "outputs": [], + "source": [ + "# добавление свойств класса\n", + "# People.age = 35" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c66da07d", + "metadata": {}, + "outputs": [], + "source": [ + "# теперь посмотрим на словарь\n", + "# People.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "ad43df10", + "metadata": {}, + "outputs": [], + "source": [ + "# свойства класса можно добавлять через специальные функции\n", + "# getattr(People, \"name\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "7272590b", + "metadata": {}, + "outputs": [], + "source": [ + "# установка нового атрибута\n", + "# setattr(People, \"job\", 123)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "328b03c3", + "metadata": {}, + "outputs": [], + "source": [ + "# People.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d0b11003", + "metadata": {}, + "outputs": [], + "source": [ + "# объявление функций\n", + "\n", + "\n", + "# class Human:\n", + "# name = \"Ivan\"\n", + "\n", + "\n", + "# def hello():\n", + "# print(\"Hello\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "7a619597", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на словарь\n", + "# print(Human.__dict__)" + ] + }, + { + "cell_type": "markdown", + "id": "dba20e73", + "metadata": {}, + "source": [ + "Если вызвать класс, то он возвращает свой экземпляр" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "434046fb", + "metadata": {}, + "outputs": [], + "source": [ + "# h1 = Human()\n", + "# h1" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e5b454f5", + "metadata": {}, + "outputs": [], + "source": [ + "# h2 = Human()\n", + "# h2" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "83694d4f", + "metadata": {}, + "outputs": [], + "source": [ + "# id(h1)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "36b120df", + "metadata": {}, + "outputs": [], + "source": [ + "# id(h2)" + ] + }, + { + "cell_type": "markdown", + "id": "1d885ec2", + "metadata": {}, + "source": [ + "Мы создали экземпляры класса, чтобы хранить разные значения одних и тех же свойств." + ] + }, + { + "cell_type": "markdown", + "id": "96425903", + "metadata": {}, + "source": [ + "Свойства класса глобальны для всех объектов" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "5e4d412a", + "metadata": {}, + "outputs": [], + "source": [ + "# h1.name" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "f8b8b867", + "metadata": {}, + "outputs": [], + "source": [ + "# h2.name" + ] + }, + { + "cell_type": "markdown", + "id": "d13faa8a", + "metadata": {}, + "source": [ + "Мы можем посмотреть id свойства name. Они совпадают." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "e89fa06c", + "metadata": {}, + "outputs": [], + "source": [ + "# id(h1.name)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "0fffb6a1", + "metadata": {}, + "outputs": [], + "source": [ + "# id(h2.name)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "8830c17e", + "metadata": {}, + "outputs": [], + "source": [ + "# id(Human.name)" + ] + }, + { + "cell_type": "markdown", + "id": "a2b7a1d6", + "metadata": {}, + "source": [ + "При этом пространства имен пусты." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "e36e1d3d", + "metadata": {}, + "outputs": [], + "source": [ + "# h1.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "47b0b15e", + "metadata": {}, + "outputs": [], + "source": [ + "# h2.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "90fe0a95", + "metadata": {}, + "outputs": [], + "source": [ + "# ищем в родительском классе\n", + "# Human.__dict__" + ] + }, + { + "cell_type": "markdown", + "id": "ef312d8b", + "metadata": {}, + "source": [ + "Такой подход позволяет экономить память и ресурсы на создание атрибутов и хранение их значений. На этом механизме основано наследование и полиморфизм." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "9dc89652", + "metadata": {}, + "outputs": [], + "source": [ + "# h1.name = \"Oleg\"\n", + "# h2.name = \"Dmitry\"" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "8692194f", + "metadata": {}, + "outputs": [], + "source": [ + "# h1.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "adbdd726", + "metadata": {}, + "outputs": [], + "source": [ + "# h2.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "43326104", + "metadata": {}, + "outputs": [], + "source": [ + "# h2.age = 48" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "f65f6cd6", + "metadata": {}, + "outputs": [], + "source": [ + "# h2.__dict__" + ] + }, + { + "cell_type": "markdown", + "id": "747308bb", + "metadata": {}, + "source": [ + "Классы являются callable-объектами, при вызове классов мы получаем его экземпляр, и у каждого экземпляра да и у класса свои изолированные друг от друга пространства имен. " + ] + }, + { + "cell_type": "markdown", + "id": "82a3426f", + "metadata": {}, + "source": [ + "Функции классов и методы экземпляров. Параметр self." + ] + }, + { + "cell_type": "markdown", + "id": "0b671758", + "metadata": {}, + "source": [ + "Поведение функции отличается от поведения свойств. " + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "1d55d05a", + "metadata": {}, + "outputs": [], + "source": [ + "# class Population:\n", + "# def hallo():\n", + "# print(\"Hello!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "d815b1ab", + "metadata": {}, + "outputs": [], + "source": [ + "# посмотрим на объект\n", + "# Population.hallo" + ] + }, + { + "cell_type": "markdown", + "id": "af2f9375", + "metadata": {}, + "source": [ + "Мы видим, что это объект функции" + ] + }, + { + "cell_type": "markdown", + "id": "a7498142", + "metadata": {}, + "source": [ + "Создадим экземпляр класса и посмотрим на объект hallo с его точки зрения" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "8b630549", + "metadata": {}, + "outputs": [], + "source": [ + "# p = Population()" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "657d60ad", + "metadata": {}, + "outputs": [], + "source": [ + "# p.hallo" + ] + }, + { + "cell_type": "markdown", + "id": "2862852a", + "metadata": {}, + "source": [ + "мы увидим, что речь идет о bound method.\n", + "Переведем id в шестнадцатиричный формат" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "606f4426", + "metadata": {}, + "outputs": [], + "source": [ + "# hex(id(p))" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "8dfaad0b", + "metadata": {}, + "outputs": [], + "source": [ + "# type(p.hallo)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "32676f5a", + "metadata": {}, + "outputs": [], + "source": [ + "# type(Population.hallo)" + ] + }, + { + "cell_type": "markdown", + "id": "def9dbac", + "metadata": {}, + "source": [ + "Функции и методы - это разные классы." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "49a08065", + "metadata": {}, + "outputs": [], + "source": [ + "# id(Population.hallo) # объект функции" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "0fc15cbb", + "metadata": {}, + "outputs": [], + "source": [ + "# id(p.hallo) # объект экземпляра" + ] + }, + { + "cell_type": "markdown", + "id": "5d094fb5", + "metadata": {}, + "source": [ + "Также у них разные атрибуты" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "70d875eb", + "metadata": {}, + "outputs": [], + "source": [ + "# dir(Population.hallo)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "b9eb2539", + "metadata": {}, + "outputs": [], + "source": [ + "# dir(p.hallo)" + ] + }, + { + "cell_type": "markdown", + "id": "3e32d5d4", + "metadata": {}, + "source": [ + "При вызове у экземпляра какого-либо метода, первым аргументом метод получает тот экземпляр класса, с которым он и был связан. Зачем это нужно? Это все тот же самый принцип поиска и определения имен. " + ] + }, + { + "cell_type": "markdown", + "id": "e98cbad4", + "metadata": {}, + "source": [ + "Методы - это специальные классы, которые объединяют в себе функции класса, с одной стороны, и конкретный экземпляр этого класса, с другой стороны. " + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "721ca229", + "metadata": {}, + "outputs": [], + "source": [ + "# p.hallo.__self__\n", + "# hex(id(p))\n", + "# p.hallo.__func__" + ] + }, + { + "cell_type": "markdown", + "id": "f018a91a", + "metadata": {}, + "source": [ + "Первичная инициализация и метод __init__()" + ] + }, + { + "cell_type": "markdown", + "id": "36cd5dc2", + "metadata": {}, + "source": [ + "В ООП конструктор класса - это метод, который автоматически вызывается при создании объектов. \n", + "В Python роль конструктора играет метод __init__(). \n", + "Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. \n", + "\n", + "Пусть имеется класс Students, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан следующим образом:" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "ed357575", + "metadata": {}, + "outputs": [], + "source": [ + "# class Student:\n", + "# def set_name(self, n, s):\n", + "# self.name = n\n", + "# self.surname = s" + ] + }, + { + "cell_type": "markdown", + "id": "f436a3af", + "metadata": {}, + "source": [ + "то создание объекта возможно без полей. Для установки имени и фамилии метод set_name нужно вызывать отдельно: " + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "cce38274", + "metadata": {}, + "outputs": [], + "source": [ + "# t = Student()\n", + "# t.set_name(\"Bill\", \"Ross\")\n", + "# t.name, t.surname" + ] + }, + { + "cell_type": "markdown", + "id": "b7c6c68e", + "metadata": {}, + "source": [ + "В свою очередь, конструктор класса не позволяет создать объект без обязательных полей. " + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "00408cd5", + "metadata": {}, + "outputs": [], + "source": [ + "# class Stud:\n", + "# def __init__(self, n, s):\n", + "# self_name = n\n", + "# self_surname = s\n", + "\n", + "\n", + "# p = Stud(\"Sam\", \"Baker\")\n", + "# print(p.name, p.surname)" + ] + }, + { + "cell_type": "markdown", + "id": "b2507ed4", + "metadata": {}, + "source": [ + "Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__(). Первый его параметр self - ссылка на сам только что созданный объект." + ] + }, + { + "cell_type": "markdown", + "id": "c6bd72f6", + "metadata": {}, + "source": [ + "Статические методы" + ] + }, + { + "cell_type": "markdown", + "id": "7784a064", + "metadata": {}, + "source": [ + "Статический метод - это такой метод, который может выполнять свою работу, не имея доступа к информации, хранящейся в атрибутах экземпляра класса. \n", + "Чтобы не передавать в статический метод лишнюю ссылку на объект self, необходимо перед методом вставить декоратор @staticmethod." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.13.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/oop.py b/python/oop.py new file mode 100644 index 00000000..1b71fdbd --- /dev/null +++ b/python/oop.py @@ -0,0 +1,287 @@ +"""Объектно-ориентированное программирование.""" + +# + +# создадим класс Person + + +# class Person: +# name = "Svetlana" + + +# Person.name + +# + +# Person.__name__ # возвращает название класса + +# + +# посмотрим доступные атрибуты +# dir(Person) + +# + +# определим принадлежность класса +# Person.__class__ + +# + +# создадим экземпляр класса Person +# p = Person() + +# + +# s = Person() + +# + +# посмотрим на класс, к которому относится этот экземпляр +# p.__class__ + +# + +# или +# p.__class__.__name__ + +# + +# так же можно использовать функцию type() +# type(p) + +# + +# создание нового экземпляра через функцию type() +# new_person = type(p)() # новый экземпляр того же типа, что и объект р + +# + +# new_person + +# + +# сравним id +# id(p) + +# + +# id(new_person) +# - + +# Свойства и атрибуты классов + +# + +# class People: +# name = "Ivanka" + + +# dir(People) + +# + +# пространство имен класса и экземпляров класса +# People.__dict__ + +# + +# добавление свойств класса +# People.age = 35 + +# + +# теперь посмотрим на словарь +# People.__dict__ + +# + +# свойства класса можно добавлять через специальные функции +# getattr(People, "name") + +# + +# установка нового атрибута +# setattr(People, "job", 123) + +# + +# People.__dict__ + +# + +# объявление функций + + +# class Human: +# name = "Ivan" + + +# def hello(): +# print("Hello") + +# + +# посмотрим на словарь +# print(Human.__dict__) +# - + +# Если вызвать класс, то он возвращает свой экземпляр + +# + +# h1 = Human() +# h1 + +# + +# h2 = Human() +# h2 + +# + +# id(h1) + +# + +# id(h2) +# - + +# Мы создали экземпляры класса, чтобы хранить разные значения одних и тех же свойств. + +# Свойства класса глобальны для всех объектов + +# + +# h1.name + +# + +# h2.name +# - + +# Мы можем посмотреть id свойства name. Они совпадают. + +# + +# id(h1.name) + +# + +# id(h2.name) + +# + +# id(Human.name) +# - + +# При этом пространства имен пусты. + +# + +# h1.__dict__ + +# + +# h2.__dict__ + +# + +# ищем в родительском классе +# Human.__dict__ +# - + +# Такой подход позволяет экономить память и ресурсы на создание атрибутов и хранение их значений. На этом механизме основано наследование и полиморфизм. + +# + +# h1.name = "Oleg" +# h2.name = "Dmitry" + +# + +# h1.__dict__ + +# + +# h2.__dict__ + +# + +# h2.age = 48 + +# + +# h2.__dict__ +# - + +# Классы являются callable-объектами, при вызове классов мы получаем его экземпляр, и у каждого экземпляра да и у класса свои изолированные друг от друга пространства имен. + +# Функции классов и методы экземпляров. Параметр self. + +# Поведение функции отличается от поведения свойств. + +# + +# class Population: +# def hallo(): +# print("Hello!") + +# + +# посмотрим на объект +# Population.hallo +# - + +# Мы видим, что это объект функции + +# Создадим экземпляр класса и посмотрим на объект hallo с его точки зрения + +# + +# p = Population() + +# + +# p.hallo +# - + +# мы увидим, что речь идет о bound method. +# Переведем id в шестнадцатиричный формат + +# + +# hex(id(p)) + +# + +# type(p.hallo) + +# + +# type(Population.hallo) +# - + +# Функции и методы - это разные классы. + +# + +# id(Population.hallo) # объект функции + +# + +# id(p.hallo) # объект экземпляра +# - + +# Также у них разные атрибуты + +# + +# dir(Population.hallo) + +# + +# dir(p.hallo) +# - + +# При вызове у экземпляра какого-либо метода, первым аргументом метод получает тот экземпляр класса, с которым он и был связан. Зачем это нужно? Это все тот же самый принцип поиска и определения имен. + +# Методы - это специальные классы, которые объединяют в себе функции класса, с одной стороны, и конкретный экземпляр этого класса, с другой стороны. + +# + +# p.hallo.__self__ +# hex(id(p)) +# p.hallo.__func__ +# - + +# Первичная инициализация и метод __init__() + +# В ООП конструктор класса - это метод, который автоматически вызывается при создании объектов. +# В Python роль конструктора играет метод __init__(). +# Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. +# +# Пусть имеется класс Students, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан следующим образом: + +# + +# class Student: +# def set_name(self, n, s): +# self.name = n +# self.surname = s +# - + +# то создание объекта возможно без полей. Для установки имени и фамилии метод set_name нужно вызывать отдельно: + +# + +# t = Student() +# t.set_name("Bill", "Ross") +# t.name, t.surname +# - + +# В свою очередь, конструктор класса не позволяет создать объект без обязательных полей. + +# + +# class Stud: +# def __init__(self, n, s): +# self_name = n +# self_surname = s + + +# p = Stud("Sam", "Baker") +# print(p.name, p.surname) +# - + +# Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__(). Первый его параметр self - ссылка на сам только что созданный объект. + +# Статические методы + +# Статический метод - это такой метод, который может выполнять свою работу, не имея доступа к информации, хранящейся в атрибутах экземпляра класса. +# Чтобы не передавать в статический метод лишнюю ссылку на объект self, необходимо перед методом вставить декоратор @staticmethod.