diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6341a1aa..fc9071a5 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] @@ -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 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 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-ключей и папок сборки, обеспечивая чистоту проекта. +# +# 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/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. +# Таким образом, хотя выбор имён не имеет никакого отношения к компьютерным алгоритмам, это остаётся важным фактором удобочитаемости кода. +# 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” +# 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 +} 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 раза больше. +# 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 или коммиты. 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_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("Алексей") 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 =’так делать нельзя’ +# 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("Значение переменной ложно") 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} - день тяжелый") 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) 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 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) 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) 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 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 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. 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 +# Ответ: удалила +# 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. Что значит отвалился интерпретатор? +# +# Это означает, что интерпритатор перестал работать или быть доступным, из-за чего программный код, который от него зависел, не может запуститься, выполнить команды или выдать ошибку. +# +# 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