diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e4f007c7..92970301 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,31 +1,31 @@ repos: - repo: https://github.com/mwouts/jupytext - rev: "v1.16.4b" + rev: "v1.17.3" hooks: - - id: jupytext - entry: jupytext - language: python - types: [jupyter] - args: - - --from=ipynb - - --to=py:light - - --set-formats=ipynb,py:light - - --quiet - - --sync - - --warn-only - exclude: '.*\.md$' + - id: jupytext + entry: jupytext + language: python + types: [jupyter] + args: + - --from=ipynb + - --to=py:light + - --set-formats=ipynb,py:light + - --quiet + - --sync + - --warn-only + exclude: '.*\.md$' # excludes md files - repo: https://github.com/PyCQA/docformatter - rev: "eb1df347edd128b30cd3368dddc3aa65edcfac38" + rev: "v1.7.7" hooks: - id: docformatter args: [--in-place, --wrap-descriptions=90, --style=google] - repo: https://github.com/psf/black.git - rev: "24.10.0" + rev: "25.1.0" hooks: - id: black - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-black name: nbqa-black @@ -36,12 +36,12 @@ repos: types_or: [jupyter, markdown] additional_dependencies: [black] - repo: https://github.com/asottile/pyupgrade - rev: "v3.19.0" + rev: "v3.20.0" hooks: - id: pyupgrade args: [--py39-plus] - repo: https://github.com/pycqa/isort - rev: "5.13.2" + rev: "6.0.1" hooks: - id: isort entry: isort @@ -50,7 +50,7 @@ repos: - --float-to-top - repo: https://github.com/nbQA-dev/nbQA - rev: "1.9.0" + rev: "1.9.1" hooks: - id: nbqa entry: nbqa blacken-docs @@ -60,7 +60,7 @@ repos: args: - --nbqa-md - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-pyupgrade name: nbqa-pyupgrade @@ -83,7 +83,7 @@ repos: - --float-to-top - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: @@ -93,7 +93,7 @@ repos: - --ignore-regex=[A-Za-z0-9+/]{100,} - --skip=*.js,*.html,*.css,*.svg",*.json,*.png,*.jpg,*.yml,*.yaml - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-flake8 args: @@ -111,7 +111,7 @@ repos: - flake8-functions-names - repo: https://github.com/PyCQA/flake8 - rev: 7.1.1 + rev: 7.3.0 hooks: - id: flake8 args: @@ -123,7 +123,7 @@ repos: - flake8-functions-names - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-mypy name: nbqa-mypy @@ -168,7 +168,7 @@ repos: - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v1.18.1 hooks: - id: mypy args: @@ -206,7 +206,7 @@ repos: - types-setuptools - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-pylint name: nbqa-pylint @@ -224,7 +224,7 @@ repos: - repo: https://github.com/pylint-dev/pylint - rev: "v3.3.1" + rev: "v3.3.8" hooks: - id: pylint name: pylint @@ -241,7 +241,7 @@ repos: additional_dependencies: [pylint] - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.0 + rev: 1.9.1 hooks: - id: nbqa-pydocstyle name: nbqa-pydocstyle @@ -251,6 +251,7 @@ repos: require_serial: true types_or: [jupyter, markdown] additional_dependencies: [pydocstyle] + # - repo: https://github.com/christophmeissner/pytest-pre-commit # rev: 1.0.0 # hooks: @@ -266,7 +267,7 @@ repos: # additional_dependencies: [pytest-html] - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: diff --git a/README.md b/README.md index edcf18ea..8756ed9b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # Data-Science-For-Beginners-from-scratch-SENATOROV Командный репозиторий. +https://t.me/SENATOROVAI diff --git a/git/stash.ipynb b/git/stash.ipynb new file mode 100644 index 00000000..e4be98f8 --- /dev/null +++ b/git/stash.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d36425c2", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Stash Conspect.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "f5fd5001", + "metadata": {}, + "source": [ + "Что делает команда git stash?\n", + "\n", + "#Сохраняет изменения в буфер обмена\n", + "\n", + "Как просмотреть список всех сохранённых изменений (стэшей)?\n", + "\n", + "#через команду git stash list\n", + "\n", + "Какая команда применяется для использования верхнего стэша?\n", + "\n", + "#команда git stash apply автоматический применяет самые верхние изменения из списка\n", + "\n", + "Как применить конкретный стэш по его номеру?\n", + "\n", + "#git stash apply stash@{номер}\n", + "\n", + "Чем отличается команда git stash apply от git stash pop?\n", + "\n", + "#git stash apply(применяет изменения из буфера обмена но не удаляет его) git stash pop(применяет и удаляет)\n", + "\n", + "Что делает команда git stash drop?\n", + "\n", + "#git stash drop stash@{номер} удалит конкретный stash.\n", + "\n", + "Как полностью очистить все сохранённые стэши?\n", + "\n", + "#git stash clear\n", + "\n", + "В каких случаях удобно использовать git stash?\n", + "\n", + "#Для чистого рабочего директория для pull и для переключение ветки без коммита \n", + "\n", + "Что произойдёт, если выполнить git stash pop, но в проекте есть конфликтующие изменения?\n", + "\n", + "#stash применится частично, а в конфликтных местах Git создаст merge-конфликты. Их нужно будет вручную разрешить и потом сделать git add для фиксации. Stash при этом удалится, даже если были конфликты.\n", + "\n", + "Можно ли восстановить удалённый стэш после выполнения git stash drop?\n", + "\n", + "#да через хэш, git stash apply \n", + "\n", + "\n", + "Что делает команда git stash save \"NAME_STASH\"\n", + "\n", + "#Добавляет изменения в буфер обмена с именем\n", + "\n", + "Что делает команда git stash apply \"NUMBER_STASH\"\n", + "\n", + "#применяет определённые изменения из буфера обмена \n", + "\n", + "Что делает команда git stash pop \"NUMBER_STASH\"\n", + "\n", + "#применяет определённые изменения из буфера обмена и удаляет его из буфера обмена\n", + "\n" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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NYFV5gl47mjV3l1BookuQAAEQAAEQAAEQAAETiQB5AnYu4MACIAACIAACIAACIAACGgC68oT/t3bfvG3L/7eE3/49KfP35Nebv7EJ+966D8/lj5uv+yVeI9ZO+xEZqswCgRAAARAAARAAARAYNMIrCVPOPuBD33l6tff9/985Cd3rr/+tT/3lpveefn3n3jvuQ//4rve/4dPfePNN/5SShWQJyBPAAEQAAEQAAEQAAEQAIE1EFhLnvC7X3j09jv/Q0oGfuGd7/360bc/8mu/sf2yVz786Jc++x/uS0XIE9YQE5uWy0IfEAABEAABEAABEACB1RNYS57wpT/46q2//umUDOz8zGt//ub3/Oyr37D9sld++GOfeOIPn/6ZV73OlyJPQJ4AAiAAAiAAAiAAAiAAAmsgsJY84bcv/t7nfvtSyhPeeebcf/3O/+szh9e87s1Xv3r04Y99AnnCGqJh9XkqegQBEAABEAABEAABENhMAmvJE17/797xxB8+/QdPfu3B3334rv/4uZQw+IP77t+7/PtPIE9AngACIAACIAACIAACIAACayOwljzB5wBvuemdb//Ff/+TO9erPOFnX/2GG3/+l/15PHe0tsjYzLwWWoEACIAACIAACIAACKyGwBrzBJUemB+RJyBPAAEQAAEQAAEQAAEQAIE1EFhlnvDNb81/877fGfTvm9+a/94XD8wUon3yx378RY1/37eaJAy9gAAIgAAIgAAIgAAIgMAxJbCyPOGOO+/+o/nz/+2//89B//5o/vwdd97dTgnM0kaS8GM//iLkCWtISY/pCIHaIAACIAACIAACIHA6CawsTzB388s7iTxh58yl2Xx+ZXd7oZRgsJDzV+bpb7Z/JvXuz/Mz2ztbvPLhhdM5AmE1CIAACIAACIAACGwmAeQJ47bRFw7m84PzvC2dObp0rtvNZ/ePdFsuZ7LjwVv8tKdnB8OENEwz84TQ0bm92XyOPIFh744iVAYBEAABEAABEACBJRNAnjBuX448weBGSYW6Y9ArfJEnGDCRKoAACIAACIAACIDAegkgTxi3RUOeYHDbPZwjT1jveEbvIAACIAACIAACIDAVAeQJxn63B9xWnkDb5cML7OH72d5Z6sU9w5Me3k8H8RUCejLnyu62u7juC/mjOPxR/uKtA+ox/IW+YndR+DYpPOdPRrlnhGIj9iLB9s4W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" + } + }, + "cell_type": "markdown", + "id": "efe78a91", + "metadata": {}, + "source": [ + "Сохраните текущие изменения в стэш под названием \"SENATOROV ver1\", вставьте скриншот из терминала\n", + "\n", + "![image.png](attachment:image.png)" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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AhC4/tAN8yvu//hPvoK+5+0LCEAAAhCAAAQgAAEIRATQ9xEO1nxzTODGu2+5lWhCAAIQgAAEIACBRSeAvh97Bqzcfnz1zHufr29d3bh0dWPz8vm11R/eszIB3fzwqYtXz7/y8PgtH77tyMm331y/fPEz1YWLm5+++drLd393El0YI/xTZz67urH5ydMPzbifY+zycKZu/MfV1z/6YuOzL86vvXzksKt7/+qbv3k1/MoHWiAAAQhAAAIQmH8CQ+n7v/zGoZ+e/n8u/O7zj/+///nB73dW3/nd393z0Jf/9LqhjIxQ+M/+9vjxNzff/3hHqc2PN39x9M4bjr7zzsc7s3c+53svv755dX39V08//qObjxw5dPi2m4/86IevrF/47OqFfzl1sxdV48ibG5/9ZGPj8vqlT46OddP60EO/fHPz6sUP1k8988TtR+6++cjdNz/41NP/8un6pavnXzt24zg8H/+CRHl1+qxainyxcemL15+9dzJNOE08uxDqHt716tpnn7/wkwdvPvKjo+e/uPjGUwrR/b88/xm46tDmMdD4DAEIQAACEBjm/P3f3nn3u7/7w6/e+/1Djx5d/quVv77ljqee/cUHm1d+8U/nrvva10dQ7V2r3PnaO5eublzaef+DzTNvfPjO7/W2+KWrG7+/NGP6/v7V859dfunYXQVxeeuxFz64enHt9Nj08eEnXvjoi5ceX3ngjS8u/PMThRZHS27VhYrgu0N1Yf2t8XVhNA9lrRsffOBF9T7D+sbl9Y0vNi5dPXt85a4XP7l46eqFN8a8mhobYen/FF/f/PynG++8aHtx/+qFi6tHDul3PC59oeldvvDerx793k3z3k38hwAEIAABCECg++dr//qWO9793R9+/sJrf3bd16Quv+GmlbV3P3n2uVcntov/rYfWrm78fv2+f+++5+ebP39Dyf0PH/nmTH2+9vBTL21+cfb4kWpWqQJX154fz9byLc9/uvGbl9Vq4daX3/zs0yfvGsce5OAuPHz64tU3n633cXqCdeX2n3+4funqxtbltXfefvqZF3+s/7v7u4rDjf/49vnPrm6sv/0PY31noxrZ6fV6H1E+tr7x0a/u1u8gqXd+3nv15kMrd73y+cZnnzx5/903H3nwgVc+ubi5/sPv7KOJueCAkxCAAAQgAIEFICDFeuP1cy/9y+tvv2/26f/8L69/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" + } + }, + "cell_type": "markdown", + "id": "187e76a1", + "metadata": {}, + "source": [ + "Восстановите ваш стэш \"SENATOROV ver1\", вставьте скриншот из терминала\n", + "\n", + "![image.png](attachment:image.png)" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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AAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAQiIAAAAAAAQAIREAAAAAAAIIEICAAAAAAAkEAEBAAAAAAASCACAgAAAAAAJBABAQAAAAAAEoiAAAAAAAAACURAAAAAAACABCIgAAAAAABAAhEQAAAAAAAggQgIAAAAAACQQAQEAAAAAABIIAICAAAAAAAkEAEBAAAAAAASiIAAAAAAAAAJREAAAAAAAIAEIiAAAAAAAEACERAAAAAAACCBCAgAAAAAAJBABAQAAAAAAEggAgIAAAAAACQQAQEAAAAAABKIgAAAAAAAAAlEQAAAAAAAgAT6/wFI0B/UauxkMgAAAABJRU5ErkJggg==" + } + }, + "cell_type": "markdown", + "id": "baee70df", + "metadata": {}, + "source": [ + "Удалите все стеши из истории, вставьте скриншот из терминала\n", + "\n", + "![image.png](attachment:image.png)" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/git/stash.py b/git/stash.py new file mode 100644 index 00000000..d07addf0 --- /dev/null +++ b/git/stash.py @@ -0,0 +1,68 @@ +"""Stash Conspect.""" + +# Что делает команда git stash? +# +# #Сохраняет изменения в буфер обмена +# +# Как просмотреть список всех сохранённых изменений (стэшей)? +# +# #через команду git stash list +# +# Какая команда применяется для использования верхнего стэша? +# +# #команда git stash apply автоматический применяет самые верхние изменения из списка +# +# Как применить конкретный стэш по его номеру? +# +# #git stash apply stash@{номер} +# +# Чем отличается команда git stash apply от git stash pop? +# +# #git stash apply(применяет изменения из буфера обмена но не удаляет его) git stash pop(применяет и удаляет) +# +# Что делает команда git stash drop? +# +# #git stash drop stash@{номер} удалит конкретный stash. +# +# Как полностью очистить все сохранённые стэши? +# +# #git stash clear +# +# В каких случаях удобно использовать git stash? +# +# #Для чистого рабочего директория для pull и для переключение ветки без коммита +# +# Что произойдёт, если выполнить git stash pop, но в проекте есть конфликтующие изменения? +# +# #stash применится частично, а в конфликтных местах Git создаст merge-конфликты. Их нужно будет вручную разрешить и потом сделать git add для фиксации. Stash при этом удалится, даже если были конфликты. +# +# Можно ли восстановить удалённый стэш после выполнения git stash drop? +# +# #да через хэш, git stash apply +# +# +# Что делает команда git stash save "NAME_STASH" +# +# #Добавляет изменения в буфер обмена с именем +# +# Что делает команда git stash apply "NUMBER_STASH" +# +# #применяет определённые изменения из буфера обмена +# +# Что делает команда git stash pop "NUMBER_STASH" +# +# #применяет определённые изменения из буфера обмена и удаляет его из буфера обмена +# +# + +# Сохраните текущие изменения в стэш под названием "SENATOROV ver1", вставьте скриншот из терминала +# +# ![image.png](attachment:image.png) + +# Восстановите ваш стэш "SENATOROV ver1", вставьте скриншот из терминала +# +# ![image.png](attachment:image.png) + +# Удалите все стеши из истории, вставьте скриншот из терминала +# +# ![image.png](attachment:image.png) diff --git a/github/opensource.ipynb b/github/opensource.ipynb new file mode 100644 index 00000000..03d04988 --- /dev/null +++ b/github/opensource.ipynb @@ -0,0 +1,66 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cfc6b049", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Opensource Contributing Quiz.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "f653f0ae", + "metadata": {}, + "source": [ + "#Проект в который вы отправили пул реквест, попадает под определение опенсорса:\n", + "да\n", + "Есть ли у него лицензия? Обычно в корне репозитория находится файл LICENSE.\n", + "#да\n", + "Напишите название понравившейся компании и ссылку на репозиторий\n", + "#first-contributions(https://github.com/firstcontributions)\n", + "Проект активно принимает стороннюю помощь?\n", + "да\n", + "Напишите второе улучшение которое вы сделали\n", + "#исправил ридми файл внём не отображились иконки и сделал ревью в документе на синтаксические ошибки\n", + "Посмотрите на коммиты в основной ветке, напишите общее количество\n", + "#10,932\n", + "Когда был последний коммит?\n", + "#22:20\n", + "Сколько контрибьюторов у проекта?\n", + "#5,000\n", + "Как часто люди коммитят в репозиторий? (На GitHub выяснить это можно, кликнув по ссылке «Commits» в верхней панели.)\n", + "#очень активно\n", + "Сколько сейчас открытых ишью?\n", + "#26\n", + "Быстро ли мейнтейнеры реагируют на ишью после того, когда они открываются?\n", + "#да\n", + "Ведётся ли активное обсуждение ишью?\n", + "#да\n", + "Есть ли недавно созданные ишью?\n", + "#много\n", + "Есть ли закрытые ишью? (На странице Issues GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые ишью.)\n", + "916 closed\n", + "Сколько сейчас открытых пул-реквестов?\n", + "#82\n", + "Быстро ли мейнтейнеры реагируют на пул-реквесты после их открытия?\n", + "#да\n", + "Ведётся ли активное обсуждение пул-реквестов?\n", + "#да\n", + "Есть ли недавно отправленные пул-реквесты?\n", + "#да\n", + "Как давно были объединены пул-реквесты? (На странице Pull Request GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые пул-реквесты.)\n", + "#24 минут назад(22:10)" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/github/opensource.py b/github/opensource.py new file mode 100644 index 00000000..33f9e56f --- /dev/null +++ b/github/opensource.py @@ -0,0 +1,40 @@ +"""Opensource Contributing Quiz.""" + +# #Проект в который вы отправили пул реквест, попадает под определение опенсорса: +# да +# Есть ли у него лицензия? Обычно в корне репозитория находится файл LICENSE. +# #да +# Напишите название понравившейся компании и ссылку на репозиторий +# #first-contributions(https://github.com/firstcontributions) +# Проект активно принимает стороннюю помощь? +# да +# Напишите второе улучшение которое вы сделали +# #исправил ридми файл внём не отображились иконки и сделал ревью в документе на синтаксические ошибки +# Посмотрите на коммиты в основной ветке, напишите общее количество +# #10,932 +# Когда был последний коммит? +# #22:20 +# Сколько контрибьюторов у проекта? +# #5,000 +# Как часто люди коммитят в репозиторий? (На GitHub выяснить это можно, кликнув по ссылке «Commits» в верхней панели.) +# #очень активно +# Сколько сейчас открытых ишью? +# #26 +# Быстро ли мейнтейнеры реагируют на ишью после того, когда они открываются? +# #да +# Ведётся ли активное обсуждение ишью? +# #да +# Есть ли недавно созданные ишью? +# #много +# Есть ли закрытые ишью? (На странице Issues GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые ишью.) +# 916 closed +# Сколько сейчас открытых пул-реквестов? +# #82 +# Быстро ли мейнтейнеры реагируют на пул-реквесты после их открытия? +# #да +# Ведётся ли активное обсуждение пул-реквестов? +# #да +# Есть ли недавно отправленные пул-реквесты? +# #да +# Как давно были объединены пул-реквесты? (На странице Pull Request GitHub-репозитория щелкните на вкладку «Closed», чтобы увидеть закрытые пул-реквесты.) +# #24 минут назад(22:10) diff --git a/github/quiz.ipynb b/github/quiz.ipynb new file mode 100644 index 00000000..82e6400c --- /dev/null +++ b/github/quiz.ipynb @@ -0,0 +1,157 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "bc037d97", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Contributing to the open-source note.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "e3f2de2a", + "metadata": {}, + "source": [ + "## GitHub\n", + "1.1. Что такое GitHub?\n", + "#бесплатный веб сервис для хостинга\n", + "1.2. Как GitHub связан с Git?\n", + "#гит отслеживает версию проекта а гитхаб это веб сервис где можно хранить версии своего проекта на удалённом сервере\n", + "1.3. Чем отличается fork репозитория от его клонирования (clone)?\n", + "#форк копирует рабочую копию проекта на ваш аккаунт гитхаб а клонироние это скачивания на вашу локальную машину для далнейшей работы с ним\n", + "1.4. Зачем нужны и как работают pull requests?\n", + "#нужен для запроса на слияние, как это работает: форкаем проект вносим свои какие то изменения, обновления, новые фичи, и отправляем запрос на слияние ветки \n", + "1.5. GitHub использует ваш почтовый адрес для\n", + "привязки ваших Git коммитов к вашей учётной записи?\n", + "#да\n", + "1.6 Какая команда генерирует SSH ключ для Доступа по SSH к репозиторию (Рисунок 83)\n", + "#Account settings>SSH keys>Add SSH key" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e233a65", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "82ac8d22", + "metadata": {}, + "source": [ + "## Рабочий процесс с использованием GitHub\n", + "3 Напишите 8 пунктов, которые нужно сделать, чтобы внести вклад в чужой проект.\n", + "#1. Создайте форк проекта.\n", + "#2. Создайте тематическую ветку на основании ветки master.\n", + "#3. Создайте один или несколько коммитов с изменениями, улучшающих проект.\n", + "#4. Отправьте эту ветку в ваш проект на GitHub\n", + "#5. Откройте запрос на слияние на GitHub.\n", + "#6. Обсуждайте его, вносите изменения, если нужно.\n", + "#7. Владелец проекта принимает решение о принятии изменений, либо об их отклонении.\n", + "#8. Получите обновлённую ветку master и отправьте её в свой форк.\n", + "3.1.\n", + "Какие практики принято соблюдать при создании Pull Request чтобы закрыть автоматический issues?\n", + "#В описании PR использовать ключевые слова GitHub:\n", + "Closes #номер_ишью\n", + "Fixes #номер_ишью\n", + "Resolves #номер_ишью\n", + "Тогда при мерже PR issue закроется автоматически.\n", + "Какие практики принято соблюдать при создании commit чтобы закрыть автоматический issues?\n", + "#В сообщении коммита можно тоже указывать\n", + "3.2 Как отклонить/закрыть пул реквест?\n", + "#Перейти на вкладку Pull requests в репозитории.\n", + "Выбрать нужный PR.\n", + "Внизу страницы будет кнопка Close pull request.\n", + "3.3 Перед отправкой пул реквеста нужно ли создавать ишьюс?\n", + "#Не обязательно\n", + "3.4 В какой вкладке можно посмотреть список изменений который был в пул реквесте? (Рисунок 92)\n", + "#Files changed\n", + "3.5 В какой вкладке находится страница обсуждений пул реквеста? (Рисунок 94)\n", + "#Conversation" + ] + }, + { + "cell_type": "markdown", + "id": "894c5f6a", + "metadata": {}, + "source": [ + "## Создание запроса на слияние\n", + "4 Можно ли открыть пул реквест, если вы ничего не вносили в FORK?\n", + "#Нет. PR сравнивает изменения между твоей веткой/форком и оригинальным репозиторием\n", + "4.1 Что нужно сделать чтобы открыть пул реквест? (Рисунок 90)\n", + "#Внести изменения в код в своём форке.\n", + "#Закоммитить и запушить изменения в ветку.\n", + "#Нажать кнопку Compare & pull request в GitHub.\n", + "#Добавить описание и отправить PR.\n", + "4.2 Что нужно сделать Если ваш Форк устарел?\n", + "#нажать кнопку Sync fork\n", + "4.3 Что нужно сделать если в пул реквесте имеются конфликты слияния (Рисунок 96)\n", + "#①Добавляем исходный репозиторий как удалённый с именем «upstream»\n", + "#Получаем последние изменения из него\n", + "#Сливаем основную ветку в нашу тематическую\n", + "#Исправляем указанный конфликт\n", + "#Отправляем изменения в ту же тематическую ветку\n", + "\n", + "## Отрывки кода\n", + "5 Что нужно сделать Для добавления отрывка кода в комментарии к ишьюсу? (Рисунок 104)\n", + "#Для добавления отрывка кода следует обрамить его обратными кавычками.\n", + "5.1 На какую клавишу нажать клавишу чтобы выделенный текст был включён как цитата в ваш комментарий?(Рисунок 105)\n", + "#клавишу r\n", + "5.2 Как вставить картинку в ишьюс? (Рисунок 108)\n", + "#Copy/Pass, Перетащить файл в окно комментария.\n", + "\n", + "## Поддержание GitHub репозитория в актуальном состоянии\n", + "6 Как понять что ваш форк устарел?\n", + "#В GitHub показывается сообщение: “This branch is behind main by X commits”\n", + "6.1 Как обновить форк?\n", + "#В интерфейсе GitHub: кнопка Sync fork.\n", + "\n", + "## Добавление участников\n", + "7 Как добавить участников в ваш репозиторий, чтобы команда могла работать над одним репозиторием? (Рисунок 112)\n", + "#В меню Collaborators → Add people\n", + "\n", + "## Упоминания и уведомления\n", + "8 Какой символ нужен для упоминания кого-либо? (Рисунок 118)\n", + "#\"@\"\n", + "8.1 Где находится Центр уведомлений, напишите ссылку (Рисунок 121)\n", + "#https://github.com/notifications\n", + "\n", + "## Особенные файлы\n", + "9 Что такое и зачем нужен файл README\n", + "#README.md — это файл документации в корне проекта.\n", + "В нём описывается:\n", + "назначение проекта\n", + "установка\n", + "использование\n", + "примеры\n", + "\n", + "9.1 Что такое и зачем нужен файл CONTRIBUTING (Рисунок 122)\n", + "#CONTRIBUTING.md — инструкция для участников проекта:\n", + "правила внесения изменений\n", + "оформление PR\n", + "стиль кода\n", + "ссылки на обсуждения\n", + "\n", + "## Управление проектом\n", + "10 Как измененить основную ветку (Рисунок 123)\n", + "#Settings → Branches → Default branch → выбрать нужную ветку.\n", + "10. 1 Как передать проект? какая кнопка? (рисунок 124)\n", + "#Settings → Danger Zone → Transfer ownership\n", + "10.2 Что такое файл .gitignore?\n", + "#Это файл, в котором перечислены файлы и папки, которые Git должен игнорировать" + ] + } + ], + "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..a4bc4bf3 --- /dev/null +++ b/github/quiz.py @@ -0,0 +1,112 @@ +"""Contributing to the open-source note.""" + +# ## GitHub +# 1.1. Что такое GitHub? +# #бесплатный веб сервис для хостинга +# 1.2. Как GitHub связан с Git? +# #гит отслеживает версию проекта а гитхаб это веб сервис где можно хранить версии своего проекта на удалённом сервере +# 1.3. Чем отличается fork репозитория от его клонирования (clone)? +# #форк копирует рабочую копию проекта на ваш аккаунт гитхаб а клонироние это скачивания на вашу локальную машину для далнейшей работы с ним +# 1.4. Зачем нужны и как работают pull requests? +# #нужен для запроса на слияние, как это работает: форкаем проект вносим свои какие то изменения, обновления, новые фичи, и отправляем запрос на слияние ветки +# 1.5. GitHub использует ваш почтовый адрес для +# привязки ваших Git коммитов к вашей учётной записи? +# #да +# 1.6 Какая команда генерирует SSH ключ для Доступа по SSH к репозиторию (Рисунок 83) +# #Account settings>SSH keys>Add SSH key + + +# ## Рабочий процесс с использованием GitHub +# 3 Напишите 8 пунктов, которые нужно сделать, чтобы внести вклад в чужой проект. +# #1. Создайте форк проекта. +# #2. Создайте тематическую ветку на основании ветки master. +# #3. Создайте один или несколько коммитов с изменениями, улучшающих проект. +# #4. Отправьте эту ветку в ваш проект на GitHub +# #5. Откройте запрос на слияние на GitHub. +# #6. Обсуждайте его, вносите изменения, если нужно. +# #7. Владелец проекта принимает решение о принятии изменений, либо об их отклонении. +# #8. Получите обновлённую ветку master и отправьте её в свой форк. +# 3.1. +# Какие практики принято соблюдать при создании Pull Request чтобы закрыть автоматический issues? +# #В описании PR использовать ключевые слова GitHub: +# Closes #номер_ишью +# Fixes #номер_ишью +# Resolves #номер_ишью +# Тогда при мерже PR issue закроется автоматически. +# Какие практики принято соблюдать при создании commit чтобы закрыть автоматический issues? +# #В сообщении коммита можно тоже указывать +# 3.2 Как отклонить/закрыть пул реквест? +# #Перейти на вкладку Pull requests в репозитории. +# Выбрать нужный PR. +# Внизу страницы будет кнопка Close pull request. +# 3.3 Перед отправкой пул реквеста нужно ли создавать ишьюс? +# #Не обязательно +# 3.4 В какой вкладке можно посмотреть список изменений который был в пул реквесте? (Рисунок 92) +# #Files changed +# 3.5 В какой вкладке находится страница обсуждений пул реквеста? (Рисунок 94) +# #Conversation + +# ## Создание запроса на слияние +# 4 Можно ли открыть пул реквест, если вы ничего не вносили в FORK? +# #Нет. PR сравнивает изменения между твоей веткой/форком и оригинальным репозиторием +# 4.1 Что нужно сделать чтобы открыть пул реквест? (Рисунок 90) +# #Внести изменения в код в своём форке. +# #Закоммитить и запушить изменения в ветку. +# #Нажать кнопку Compare & pull request в GitHub. +# #Добавить описание и отправить PR. +# 4.2 Что нужно сделать Если ваш Форк устарел? +# #нажать кнопку Sync fork +# 4.3 Что нужно сделать если в пул реквесте имеются конфликты слияния (Рисунок 96) +# #①Добавляем исходный репозиторий как удалённый с именем «upstream» +# #Получаем последние изменения из него +# #Сливаем основную ветку в нашу тематическую +# #Исправляем указанный конфликт +# #Отправляем изменения в ту же тематическую ветку +# +# ## Отрывки кода +# 5 Что нужно сделать Для добавления отрывка кода в комментарии к ишьюсу? (Рисунок 104) +# #Для добавления отрывка кода следует обрамить его обратными кавычками. +# 5.1 На какую клавишу нажать клавишу чтобы выделенный текст был включён как цитата в ваш комментарий?(Рисунок 105) +# #клавишу r +# 5.2 Как вставить картинку в ишьюс? (Рисунок 108) +# #Copy/Pass, Перетащить файл в окно комментария. +# +# ## Поддержание GitHub репозитория в актуальном состоянии +# 6 Как понять что ваш форк устарел? +# #В GitHub показывается сообщение: “This branch is behind main by X commits” +# 6.1 Как обновить форк? +# #В интерфейсе GitHub: кнопка Sync fork. +# +# ## Добавление участников +# 7 Как добавить участников в ваш репозиторий, чтобы команда могла работать над одним репозиторием? (Рисунок 112) +# #В меню Collaborators → Add people +# +# ## Упоминания и уведомления +# 8 Какой символ нужен для упоминания кого-либо? (Рисунок 118) +# #"@" +# 8.1 Где находится Центр уведомлений, напишите ссылку (Рисунок 121) +# #https://github.com/notifications +# +# ## Особенные файлы +# 9 Что такое и зачем нужен файл README +# #README.md — это файл документации в корне проекта. +# В нём описывается: +# назначение проекта +# установка +# использование +# примеры +# +# 9.1 Что такое и зачем нужен файл CONTRIBUTING (Рисунок 122) +# #CONTRIBUTING.md — инструкция для участников проекта: +# правила внесения изменений +# оформление PR +# стиль кода +# ссылки на обсуждения +# +# ## Управление проектом +# 10 Как измененить основную ветку (Рисунок 123) +# #Settings → Branches → Default branch → выбрать нужную ветку. +# 10. 1 Как передать проект? какая кнопка? (рисунок 124) +# #Settings → Danger Zone → Transfer ownership +# 10.2 Что такое файл .gitignore? +# #Это файл, в котором перечислены файлы и папки, которые Git должен игнорировать diff --git a/intro_log.py b/intro_log.py new file mode 100644 index 00000000..ceaabf98 --- /dev/null +++ b/intro_log.py @@ -0,0 +1,8 @@ +"""Интро отчёт.""" + +# 11/08/2025 +# +# 1.скачал и установил все фреймворки и организовал базовую рабочую среду +# 2.вспомнил и изучил о Git, Github +# 3.сделал форк репозитории и установил пакеты и зависимости +# 4.здал отчёт diff --git a/python/clean-code/chapter_4_choosing_clear_names.ipynb b/python/clean-code/chapter_4_choosing_clear_names.ipynb new file mode 100644 index 00000000..edf3bf8e --- /dev/null +++ b/python/clean-code/chapter_4_choosing_clear_names.ipynb @@ -0,0 +1,92 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "4d573c12", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Choosing clear names for variables, functions, and classes.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "f7c8e8b0", + "metadata": {}, + "source": [ + "## Компактные, содержательные имена важны для удобочитаемости вашей программы\n", + "\n", + "Если вы пишете не «одноразовый» код, который вы не собираетесь сопровождать\n", + "после однократного запуска программы, вам стоит подумать над выбором хороших\n", + "имен в вашей программе. Выбор имен — субъективный выбор, который делаете именно вы.\n", + "Автоматизированные средства форматирования (такие как Black) не способны\n", + "решить, как должны называться ваши переменные.\n", + "\n", + "#### Схемы регистра имен\n", + "\n", + "- Змеиный регистр `snake_case` разделяет слова символом подчеркивания.\n", + "\n", + "- Верблюжий регистр `camelCase` — слова записываются в нижнем регистре,\n", + "но второе и следующие слова начинаются с заглавной.\n", + "\n", + "- Схема Pascal `PascalCase` — названа так, потому что применяется в языке\n", + "программирования Pascal; аналогична схеме верблюжьего регистра, но первое\n", + "слово в ней тоже начинается с заглавной.\n", + "\n", + "\n", + "#### Соглашения об именах PEP 8\n", + "\n", + "**•** Все буквы должны быть буквами ASCII — то есть латинскими буквами\n", + "верхнего и нижнего регистров без диакритических знаков.\n", + "**•** Имена модулей должны быть короткими состоять только из букв нижнего регистра.\n", + "**•** В схеме должны записываться \n", + "**•** Имена классов необходимо записывать в схеме Pascal\n", + "**•** Имена констант следует записывать в верхнем змеином регистре\n", + "**•** Имена функций, методов и переменных записывают в нижнем змеином\n", + "регистре\n", + "**•** Приватные атрибуты классов всегда начинают с символа подчеркивания ( _ )\n", + "\n", + "\n", + "#### Длина имен\n", + "\n", + "Имена не должны быть слишком короткими или слишком длинными. Так как код читают чаще, чем пишут, лучше все-таки задавать более длинные имена переменных. Не пропускайте буквы в своем коде. устаревшей считается венгерская запись — практика включения сокращения типа данных в имена. Например, имя `strName` указывает, что\n", + "переменная содержит строковое значение. Современные языки и IDE могут предоставить программисту информацию о типе данных без этих префиксов\n", + "\n", + "\n", + "\n", + "#### Выбирайте имена, пригодные для поиска\n", + "\n", + "Чтобы имя было найдено немедленно, создавайте уникальные имена с более длинными именами переменных, которые содержат конкретную информацию. Лучше всего писать код, понятный тем, для кого английский язык не является родным, то есть прямолинейно, традиционно и без юмора.\n", + "\n", + "\n", + "\n", + "#### Не заменяйте встроенные имена\n", + "\n", + "Никогда не используйте встроенные имена Python для своих переменных. Наиболее часто заменяемые имена Python — all, any, date, email, file, format, hash,\n", + "id, input, list, min, max, object, open, random, set, str, sum, test и type. Не берите их для своих идентификаторов. Другая распространенная проблема — присваивание файлам .py имен, совпадающих с именами сторонних модулей.\n", + "\n", + "\n", + "#### Итоги\n", + "\n", + "Выбор имен не имеет никакого отношения к алгоритмам или компьютерной теории, и все же это важнейший фактор написания удобочитаемого кода. В конечном счете выбор имен, используемых в вашем коде, остается на ваше усмотрение, но вы\n", + "должны учитывать существующие рекомендации. В PEP 8 вы найдете несколько\n", + "соглашений о выборе имен — например, имена в нижнем регистре для модулей\n", + "и имена в схеме Pascal для классов. Имена не должны быть слишком короткими\n", + "или слишком длинными. Однако часто лучше сделать имя избыточным, чем недостаточно содержательным\n", + "\n", + "Имена упрощают чтение кода людьми, а не выполнение его компьютерами. Если\n", + "ваш код хорошо читается, он будет понятным. Если он понятен, его легко изменить.\n", + "А если его легко изменить, вам будет проще исправить ошибки или добавить новые\n", + "возможности. Использование понятных имен — основополагающий фактор разработки качественного программного обеспечения." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/clean-code/chapter_4_choosing_clear_names.py b/python/clean-code/chapter_4_choosing_clear_names.py new file mode 100644 index 00000000..51fd7664 --- /dev/null +++ b/python/clean-code/chapter_4_choosing_clear_names.py @@ -0,0 +1,66 @@ +"""Choosing clear names for variables, functions, and classes.""" + +# ## Компактные, содержательные имена важны для удобочитаемости вашей программы +# +# Если вы пишете не «одноразовый» код, который вы не собираетесь сопровождать +# после однократного запуска программы, вам стоит подумать над выбором хороших +# имен в вашей программе. Выбор имен — субъективный выбор, который делаете именно вы. +# Автоматизированные средства форматирования (такие как Black) не способны +# решить, как должны называться ваши переменные. +# +# #### Схемы регистра имен +# +# - Змеиный регистр `snake_case` разделяет слова символом подчеркивания. +# +# - Верблюжий регистр `camelCase` — слова записываются в нижнем регистре, +# но второе и следующие слова начинаются с заглавной. +# +# - Схема Pascal `PascalCase` — названа так, потому что применяется в языке +# программирования Pascal; аналогична схеме верблюжьего регистра, но первое +# слово в ней тоже начинается с заглавной. +# +# +# #### Соглашения об именах PEP 8 +# +# **•** Все буквы должны быть буквами ASCII — то есть латинскими буквами +# верхнего и нижнего регистров без диакритических знаков. +# **•** Имена модулей должны быть короткими состоять только из букв нижнего регистра. +# **•** В схеме должны записываться +# **•** Имена классов необходимо записывать в схеме Pascal +# **•** Имена констант следует записывать в верхнем змеином регистре +# **•** Имена функций, методов и переменных записывают в нижнем змеином +# регистре +# **•** Приватные атрибуты классов всегда начинают с символа подчеркивания ( _ ) +# +# +# #### Длина имен +# +# Имена не должны быть слишком короткими или слишком длинными. Так как код читают чаще, чем пишут, лучше все-таки задавать более длинные имена переменных. Не пропускайте буквы в своем коде. устаревшей считается венгерская запись — практика включения сокращения типа данных в имена. Например, имя `strName` указывает, что +# переменная содержит строковое значение. Современные языки и IDE могут предоставить программисту информацию о типе данных без этих префиксов +# +# +# +# #### Выбирайте имена, пригодные для поиска +# +# Чтобы имя было найдено немедленно, создавайте уникальные имена с более длинными именами переменных, которые содержат конкретную информацию. Лучше всего писать код, понятный тем, для кого английский язык не является родным, то есть прямолинейно, традиционно и без юмора. +# +# +# +# #### Не заменяйте встроенные имена +# +# Никогда не используйте встроенные имена Python для своих переменных. Наиболее часто заменяемые имена Python — all, any, date, email, file, format, hash, +# id, input, list, min, max, object, open, random, set, str, sum, test и type. Не берите их для своих идентификаторов. Другая распространенная проблема — присваивание файлам .py имен, совпадающих с именами сторонних модулей. +# +# +# #### Итоги +# +# Выбор имен не имеет никакого отношения к алгоритмам или компьютерной теории, и все же это важнейший фактор написания удобочитаемого кода. В конечном счете выбор имен, используемых в вашем коде, остается на ваше усмотрение, но вы +# должны учитывать существующие рекомендации. В PEP 8 вы найдете несколько +# соглашений о выборе имен — например, имена в нижнем регистре для модулей +# и имена в схеме Pascal для классов. Имена не должны быть слишком короткими +# или слишком длинными. Однако часто лучше сделать имя избыточным, чем недостаточно содержательным +# +# Имена упрощают чтение кода людьми, а не выполнение его компьютерами. Если +# ваш код хорошо читается, он будет понятным. Если он понятен, его легко изменить. +# А если его легко изменить, вам будет проще исправить ошибки или добавить новые +# возможности. Использование понятных имен — основополагающий фактор разработки качественного программного обеспечения. diff --git a/python/commits.ipynb b/python/commits.ipynb new file mode 100644 index 00000000..3cd77bf4 --- /dev/null +++ b/python/commits.ipynb @@ -0,0 +1,83 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "4af67dd7", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Конспект по Conventional Commits.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "056a45cf", + "metadata": {}, + "source": [ + "# Конспект по Conventional Commits\n", + "\n", + "## Назначение типов коммитов\n", + "\n", + "- **feat**: Добавление новой функции (MINOR в SemVer).\n", + "- **fix**: Исправление бага (PATCH в SemVer).\n", + "- **docs**: Изменения в документации (README, комментарии).\n", + "- **style**: Форматирование кода без изменения логики (отступы, линтинг).\n", + "- **refactor**: Улучшение кода без изменения поведения.\n", + "- **test**: Добавление или изменение тестов.\n", + "- **build**: Изменения в системе сборки или зависимостях.\n", + "- **ci**: Настройка CI/CD (GitHub Actions, пайплайны).\n", + "- **perf**: Улучшение производительности.\n", + "- **chore**: Рутинные задачи (обновление инструментов, .gitignore).\n", + "\n", + "\n", + "\n", + "### Исправление бага (fix)\n", + "\n", + "**fix**: исправлен баг в функции округления числа\n", + "\n", + "### Добавления новой функциональности\n", + "\n", + "**feat**: Добавлена новая функция для генерации отчёта\n", + "\n", + "Реализована новая функция generateReport которая автоматически создаёт отчёты\n", + "\n", + "\n", + "### Форматирование кода (style)\n", + "\n", + "**style**: поправлено все отступы и форматирования\n", + "\n", + "Базовая логика кода не поменялась!\n", + "\n", + "\n", + "### Документация (docs)\n", + "\n", + "**docs**: задокументировано функция generateReport\n", + "\n", + "Добавлен пример использования и описания функции в README.md\n", + "\n", + "\n", + "### Тестирование (test)\n", + "\n", + "**test**: добавлены тесты для улучшения функции generateReport\n", + "\n", + "добавлен тест для автоматического создания PDF отчёта\n", + "\n", + "\n", + "\n", + "\n", + "## Заключение\n", + "\n", + "Conventional Commits структурирует историю коммитов, упрощая автоматизацию и понимание изменений. Типы и шаблон (тип: описание, тело, сноски) обеспечивают ясность.\n", + "\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/commits.py b/python/commits.py new file mode 100644 index 00000000..92e031d5 --- /dev/null +++ b/python/commits.py @@ -0,0 +1,58 @@ +"""Конспект по Conventional Commits.""" + +# # Конспект по Conventional Commits +# +# ## Назначение типов коммитов +# +# - **feat**: Добавление новой функции (MINOR в SemVer). +# - **fix**: Исправление бага (PATCH в SemVer). +# - **docs**: Изменения в документации (README, комментарии). +# - **style**: Форматирование кода без изменения логики (отступы, линтинг). +# - **refactor**: Улучшение кода без изменения поведения. +# - **test**: Добавление или изменение тестов. +# - **build**: Изменения в системе сборки или зависимостях. +# - **ci**: Настройка CI/CD (GitHub Actions, пайплайны). +# - **perf**: Улучшение производительности. +# - **chore**: Рутинные задачи (обновление инструментов, .gitignore). +# +# +# +# ### Исправление бага (fix) +# +# **fix**: исправлен баг в функции округления числа +# +# ### Добавления новой функциональности +# +# **feat**: Добавлена новая функция для генерации отчёта +# +# Реализована новая функция generateReport которая автоматически создаёт отчёты +# +# +# ### Форматирование кода (style) +# +# **style**: поправлено все отступы и форматирования +# +# Базовая логика кода не поменялась! +# +# +# ### Документация (docs) +# +# **docs**: задокументировано функция generateReport +# +# Добавлен пример использования и описания функции в README.md +# +# +# ### Тестирование (test) +# +# **test**: добавлены тесты для улучшения функции generateReport +# +# добавлен тест для автоматического создания PDF отчёта +# +# +# +# +# ## Заключение +# +# Conventional Commits структурирует историю коммитов, упрощая автоматизацию и понимание изменений. Типы и шаблон (тип: описание, тело, сноски) обеспечивают ясность. +# +# diff --git a/python/cpython.ipynb b/python/cpython.ipynb new file mode 100644 index 00000000..526cb8cf --- /dev/null +++ b/python/cpython.ipynb @@ -0,0 +1,97 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "9fd89528", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Quiz Cpython.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "c38ceb13", + "metadata": {}, + "source": [ + "### 1. Что такое CPython и чем он отличается от Python?\n", + "#Python — это язык, а CPython — это интерпретатор" + ] + }, + { + "cell_type": "markdown", + "id": "f004ff7b", + "metadata": {}, + "source": [ + "3. Сколько существует реализаций Python, и какая из них самая популярная?\n", + "#самые популярные CPython, которая является стандартной реализацией. Другие заметные реализации включают Jython (написан на Java), IronPython (для .NET) и PyPy (быстрая реализация с JIT-компиляцией)\n", + "4. На каком языке написан CPython?\n", + "#на яп С\n", + "Поиск и установка CPython\n", + "5. (опционально) Кто создал CPython?\n", + "#Гвидо ван Россум\n", + "6. Почему Python считается быстрым, несмотря на то, что это интерпретируемый язык?\n", + "#он считается \"быстрым\" с точки зрения скорости разработки — написание кода на Python занимает меньше времени, чем на других языках\n", + "7. Напишите путь к Интерпретатору CPython на вашем компьютере\n", + "Структура CPython\n", + "#C:\\Users\\Maksat\\AppData\\Local\\Programs\\Python\\Python39\\python.exe\n", + "\n", + "Что содержится в папке include в CPython?\n", + "#содержит файл необходимые для создания расширений на яп С\n", + "Где можно найти исходный код CPython дайте ссылку на репозиторий гитхаб\n", + "#https://github.com/python/cpython\n", + "Запуск файла с помощью CPython\n", + "11. Какая команда используется для запуска файла с помощью CPython?\n", + "#если он установлен правильно(добавлен в переменные среды то ) python \n", + "12. Можно ли запускать текстовые файлы через интерпретатор Python? Почему?\n", + "#да если этот текстовый файл содержит валидный синтаксис Python\n", + "13. Как указать путь к интерпретатору и файлу для выполнения кода? Сначала путь к интерпретатору а потом к файлу\n", + "Введение в PyPy\n", + "#\n", + "\n", + "14. Чем PyPy отличается от CPython?\n", + "#PyPy компилирует часть кода \"на лету\" в машинный код главное отличие — наличие JIT-компилятора (Just-In-Time)\n", + "Почему PyPy не может использоваться для всех проектов на Python?\n", + "из-за проблем совместимости\n", + "Где можно скачать PyPy?\n", + "#https://www.pypy.org/download.html\n", + "Установка и запуск PyPy\n", + "\n", + "17. Как установить PyPy после скачивания?\n", + "##его достаточно распаковать в удобную папку затем можно добавить путь к исполняемому файлу PyPy в системную переменную PATH\n", + "18. Как запустить файл с помощью PyPy?\n", + "#pypy \n", + "19. Почему PyPy выполняет код быстрее, чем CPython?\n", + "#Он анализирует часто используемые участки кода и компилирует их в машинный код во время выполнения это позволяет избежать накладных расходов на интерпретацию байт-кода\n", + "Задание 5: Сравнение производительности CPython и PyPy\n", + "\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", + "Result: 49999995000000\n", + "Execution time: 0.008118867874145508 seconds\n", + "Result: 49999995000000\n", + "Execution time: 0.5473790168762207 seconds\n", + "0.5473790168762207/0.008118867874145508 = 67.42" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/cpython.py b/python/cpython.py new file mode 100644 index 00000000..f823b6a7 --- /dev/null +++ b/python/cpython.py @@ -0,0 +1,65 @@ +"""Quiz Cpython.""" + +# ### 1. Что такое CPython и чем он отличается от Python? +# #Python — это язык, а CPython — это интерпретатор + +# 3. Сколько существует реализаций Python, и какая из них самая популярная? +# #самые популярные CPython, которая является стандартной реализацией. Другие заметные реализации включают Jython (написан на Java), IronPython (для .NET) и PyPy (быстрая реализация с JIT-компиляцией) +# 4. На каком языке написан CPython? +# #на яп С +# Поиск и установка CPython +# 5. (опционально) Кто создал CPython? +# #Гвидо ван Россум +# 6. Почему Python считается быстрым, несмотря на то, что это интерпретируемый язык? +# #он считается "быстрым" с точки зрения скорости разработки — написание кода на Python занимает меньше времени, чем на других языках +# 7. Напишите путь к Интерпретатору CPython на вашем компьютере +# Структура CPython +# #C:\Users\Maksat\AppData\Local\Programs\Python\Python39\python.exe +# +# Что содержится в папке include в CPython? +# #содержит файл необходимые для создания расширений на яп С +# Где можно найти исходный код CPython дайте ссылку на репозиторий гитхаб +# #https://github.com/python/cpython +# Запуск файла с помощью CPython +# 11. Какая команда используется для запуска файла с помощью CPython? +# #если он установлен правильно(добавлен в переменные среды то ) python +# 12. Можно ли запускать текстовые файлы через интерпретатор Python? Почему? +# #да если этот текстовый файл содержит валидный синтаксис Python +# 13. Как указать путь к интерпретатору и файлу для выполнения кода? Сначала путь к интерпретатору а потом к файлу +# Введение в PyPy +# # +# +# 14. Чем PyPy отличается от CPython? +# #PyPy компилирует часть кода "на лету" в машинный код главное отличие — наличие JIT-компилятора (Just-In-Time) +# Почему PyPy не может использоваться для всех проектов на Python? +# из-за проблем совместимости +# Где можно скачать PyPy? +# #https://www.pypy.org/download.html +# Установка и запуск PyPy +# +# 17. Как установить PyPy после скачивания? +# ##его достаточно распаковать в удобную папку затем можно добавить путь к исполняемому файлу PyPy в системную переменную PATH +# 18. Как запустить файл с помощью PyPy? +# #pypy +# 19. Почему PyPy выполняет код быстрее, чем CPython? +# #Он анализирует часто используемые участки кода и компилирует их в машинный код во время выполнения это позволяет избежать накладных расходов на интерпретацию байт-кода +# Задание 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. Запишите результаты времени выполнения для обоих интерпретаторов. +# Сделайте вывод о разнице в производительности. +# +# Result: 49999995000000 +# Execution time: 0.008118867874145508 seconds +# Result: 49999995000000 +# Execution time: 0.5473790168762207 seconds +# 0.5473790168762207/0.008118867874145508 = 67.42 diff --git a/python/issues.ipynb b/python/issues.ipynb new file mode 100644 index 00000000..b5fb84ac --- /dev/null +++ b/python/issues.ipynb @@ -0,0 +1,147 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "562c42f2", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Конспект по GitHub Issues.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "a30b6b81", + "metadata": {}, + "source": [ + "### Общие вопросы:\n", + "\n", + "1.Что такое Issues на GitHub и для чего они используются?\n", + "#Система для отслеживания задач основные функции управлять, обсуждать, отслеживать рабочие вопросы\n", + "2.Чем Issues отличаются от других инструментов управления задачами?\n", + "#Автоматический связывает коммиты и пулл реквесты, отслеживает изменения в коде связанная с конкретной задачей, удобно использовать для обсуждения кода\n", + "3.Какие основные компоненты (поля) есть у каждого Issue?\n", + "#заголовок, описание, метки (labels), исполнители (assignees), вехи (milestones) и комментарии.\n" + ] + }, + { + "cell_type": "markdown", + "id": "10aad8ec", + "metadata": {}, + "source": [ + "### Создание Issues:\n", + "\n", + "1.Как создать новое Issue в репозитории?\n", + "#Repository>Issues>New Issues\n", + "2.Какие данные рекомендуется указывать в описании Issue для лучшего понимания задачи?\n", + "#цель, инструкции, майлстон, прикрепить отвественого\n", + "3.Какие теги (labels) можно добавить к Issue? Какие из них стандартные?\n", + "#ошибка(bug), улучшение(enhancement), документация(documentation), нужна помошь(help wanted)\n", + "4.Как прикрепить Assignees (ответственных) к Issue?\n", + "#на боковой панели Issue в разделе Assignees выберите одного или нескольких пользователей\n" + ] + }, + { + "cell_type": "markdown", + "id": "4f6844c2", + "metadata": {}, + "source": [ + "### Работа с Issues:\n", + "\n", + "1.Как использовать Labels для классификации задач?\n", + "#Метки используются для фильтрации и организации Issues\n", + "2.Для чего нужен Milestone, и как связать его с Issue?\n", + "#Чтобы связать Issue с вехой, выберите её на боковой панели в разделе Milestone, это группа Issues, объединённая общей целью, например, сроком или версией релиза\n", + "3.Как привязать Issue к пул-реквесту (Pull Request)?\n", + "#(#<номер ишьюса>) \n", + "4.Как добавить комментарий к существующему Issue?\n", + "#внизу страницы Issue в поле комент" + ] + }, + { + "cell_type": "markdown", + "id": "f5cca504", + "metadata": {}, + "source": [ + "### Закрытие и завершение Issues:\n", + "\n", + "1.Как закрыть Issue вручную?\n", + "#Closes: #<номер ишью>\n", + "2.Можно ли автоматически закрыть Issue с помощью сообщения в коммите или пул-реквесте? Как это сделать?\n", + "#Closes/Fixes/Resolves: <номе ишью> \n", + "3.Как повторно открыть закрытое Issue, если работа ещё не завершена?\n", + "#нажимаем на Reopen issue" + ] + }, + { + "cell_type": "markdown", + "id": "889ad6d9", + "metadata": {}, + "source": [ + "### Фильтрация и поиск:\n", + "\n", + "1.Как найти все открытые или закрытые Issues в репозитории?\n", + "#в строке поиска используйте is:open, is:closed.\n", + "2.Как использовать фильтры для поиска Issues по меткам, исполнителям или другим критериям?\n", + "#В строке поиска используйте синтаксис: label:bug, assignee:username, milestone:version-1.0\n", + "3.Как сортировать Issues по приоритету, дате создания или другим параметрам?\n", + "#выпадающее меню Sort в правой части страницы Issues, чтобы отсортировать по Newest (новые), Oldest (старые), Most commented (самые комментируемые) и другим критериям" + ] + }, + { + "cell_type": "markdown", + "id": "87a2b9d3", + "metadata": {}, + "source": [ + "### Интеграции и автоматизация:\n", + "\n", + "1.Как настроить автоматические уведомления о новых или изменённых Issues?\n", + "#в разделе Notifications можно выбрать, о каких событиях вы хотите получать уведомления\n", + "2.Что такое Projects в контексте GitHub, и как связать их с Issues?\n", + "#помогают визуально отслеживать прогресс задач вы можете добавлять Issue на доску Project и перемещать его между колонками (To do, In progress, Done).\n", + "3.Какие сторонние инструменты можно использовать для автоматизации работы с Issues (например, боты, Webhooks)?\n", + "#GitHub Actions, Webhooks позволяют автоматизировать рутинные задачи, такие как назначение меток, закрытие неактивных Issues или создание новых" + ] + }, + { + "cell_type": "markdown", + "id": "e51019d0", + "metadata": {}, + "source": [ + "### Коллаборация:\n", + "\n", + "1.Как упомянуть другого пользователя в комментарии к Issue?\n", + "#@username и GitHub отправит этому пользователю уведомление\n", + "2.Как запросить дополнительные данные или уточнения у автора Issue?\n", + "#комментарий в Issue, используя @username автора или отметить нужные строки кода и коментировать\n", + "3.Что делать, если Issue неактуально или его нужно объединить с другим?\n", + "#если Issue неактуально, его можно просто закрыть. Если оно дублирует другое, его можно закрыть, сославшись на оригинальный Issue" + ] + }, + { + "cell_type": "markdown", + "id": "b459709c", + "metadata": {}, + "source": [ + "### Практические аспекты:\n", + "\n", + "1.Как использовать шаблоны для создания Issues?\n", + "#В репозитории можно создать папку .github и в ней файл ISSUE_TEMPLATE.md, который будет содержать определённую структуру для новых Issues\n", + "2.Что такое Linked Issues, и как создать связь между задачами?\n", + "#способ указать на связь между двумя или более Issues используя символ # и номер Issue.\n", + "3.Какие метрики (например, время выполнения) можно отслеживать с помощью Issues?\n", + "#Lead Time Это помогает измерить, насколько быстро команда способна решать задачи, Cycle Time Время, которое Issue находится в работе (с момента, когда его назначили исполнителю, до закрытия)\n", + "4.Какие best practices рекомендуются при работе с Issues в команде?\n", + "#однозначные заголовки, назначайте ответственных, используйте метки, обновляйте статус, закрывайте неактуальные Issues." + ] + } + ], + "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..45e06bfa --- /dev/null +++ b/python/issues.py @@ -0,0 +1,81 @@ +"""Конспект по GitHub Issues.""" + +# ### Общие вопросы: +# +# 1.Что такое Issues на GitHub и для чего они используются? +# #Система для отслеживания задач основные функции управлять, обсуждать, отслеживать рабочие вопросы +# 2.Чем Issues отличаются от других инструментов управления задачами? +# #Автоматический связывает коммиты и пулл реквесты, отслеживает изменения в коде связанная с конкретной задачей, удобно использовать для обсуждения кода +# 3.Какие основные компоненты (поля) есть у каждого Issue? +# #заголовок, описание, метки (labels), исполнители (assignees), вехи (milestones) и комментарии. +# + +# ### Создание Issues: +# +# 1.Как создать новое Issue в репозитории? +# #Repository>Issues>New Issues +# 2.Какие данные рекомендуется указывать в описании Issue для лучшего понимания задачи? +# #цель, инструкции, майлстон, прикрепить отвественого +# 3.Какие теги (labels) можно добавить к Issue? Какие из них стандартные? +# #ошибка(bug), улучшение(enhancement), документация(documentation), нужна помошь(help wanted) +# 4.Как прикрепить Assignees (ответственных) к Issue? +# #на боковой панели Issue в разделе Assignees выберите одного или нескольких пользователей +# + +# ### Работа с Issues: +# +# 1.Как использовать Labels для классификации задач? +# #Метки используются для фильтрации и организации Issues +# 2.Для чего нужен Milestone, и как связать его с Issue? +# #Чтобы связать Issue с вехой, выберите её на боковой панели в разделе Milestone, это группа Issues, объединённая общей целью, например, сроком или версией релиза +# 3.Как привязать Issue к пул-реквесту (Pull Request)? +# #(#<номер ишьюса>) +# 4.Как добавить комментарий к существующему Issue? +# #внизу страницы Issue в поле комент + +# ### Закрытие и завершение Issues: +# +# 1.Как закрыть Issue вручную? +# #Closes: #<номер ишью> +# 2.Можно ли автоматически закрыть Issue с помощью сообщения в коммите или пул-реквесте? Как это сделать? +# #Closes/Fixes/Resolves: <номе ишью> +# 3.Как повторно открыть закрытое Issue, если работа ещё не завершена? +# #нажимаем на Reopen issue + +# ### Фильтрация и поиск: +# +# 1.Как найти все открытые или закрытые Issues в репозитории? +# #в строке поиска используйте is:open, is:closed. +# 2.Как использовать фильтры для поиска Issues по меткам, исполнителям или другим критериям? +# #В строке поиска используйте синтаксис: label:bug, assignee:username, milestone:version-1.0 +# 3.Как сортировать Issues по приоритету, дате создания или другим параметрам? +# #выпадающее меню Sort в правой части страницы Issues, чтобы отсортировать по Newest (новые), Oldest (старые), Most commented (самые комментируемые) и другим критериям + +# ### Интеграции и автоматизация: +# +# 1.Как настроить автоматические уведомления о новых или изменённых Issues? +# #в разделе Notifications можно выбрать, о каких событиях вы хотите получать уведомления +# 2.Что такое Projects в контексте GitHub, и как связать их с Issues? +# #помогают визуально отслеживать прогресс задач вы можете добавлять Issue на доску Project и перемещать его между колонками (To do, In progress, Done). +# 3.Какие сторонние инструменты можно использовать для автоматизации работы с Issues (например, боты, Webhooks)? +# #GitHub Actions, Webhooks позволяют автоматизировать рутинные задачи, такие как назначение меток, закрытие неактивных Issues или создание новых + +# ### Коллаборация: +# +# 1.Как упомянуть другого пользователя в комментарии к Issue? +# #@username и GitHub отправит этому пользователю уведомление +# 2.Как запросить дополнительные данные или уточнения у автора Issue? +# #комментарий в Issue, используя @username автора или отметить нужные строки кода и коментировать +# 3.Что делать, если Issue неактуально или его нужно объединить с другим? +# #если Issue неактуально, его можно просто закрыть. Если оно дублирует другое, его можно закрыть, сославшись на оригинальный Issue + +# ### Практические аспекты: +# +# 1.Как использовать шаблоны для создания Issues? +# #В репозитории можно создать папку .github и в ней файл ISSUE_TEMPLATE.md, который будет содержать определённую структуру для новых Issues +# 2.Что такое Linked Issues, и как создать связь между задачами? +# #способ указать на связь между двумя или более Issues используя символ # и номер Issue. +# 3.Какие метрики (например, время выполнения) можно отслеживать с помощью Issues? +# #Lead Time Это помогает измерить, насколько быстро команда способна решать задачи, Cycle Time Время, которое Issue находится в работе (с момента, когда его назначили исполнителю, до закрытия) +# 4.Какие best practices рекомендуются при работе с Issues в команде? +# #однозначные заголовки, назначайте ответственных, используйте метки, обновляйте статус, закрывайте неактуальные Issues. diff --git a/python/made-easy/fundamentals_of_programming_and_intro_to_ds.ipynb b/python/made-easy/fundamentals_of_programming_and_intro_to_ds.ipynb new file mode 100644 index 00000000..340b0f1d --- /dev/null +++ b/python/made-easy/fundamentals_of_programming_and_intro_to_ds.ipynb @@ -0,0 +1,309 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "5fd5eac2", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Basics of programming and introducing DS note page 26-47.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "aea71c22", + "metadata": {}, + "source": [ + "#### Что такое Data Science?\n", + "\n", + "Data Science - это научная дисциплина, которая включает в себя извлечение ин формации из огромных объемов данных с использованием различных научных методов, алгоритмов и процессов." + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "a1f6cb90", + "metadata": {}, + "source": [ + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "id": "d197e997", + "metadata": {}, + "source": [ + "#### Зачем нам Data Science? \n", + "\n", + "Data Science как наука, занимающаяся изучением данных, помогает лучше прини мать решения, обнаруживать закономерности, составлять прогнозы, выполнять анализ и создавать визуальное представление из необработанных данных. Эта наука помогает нам:\n", + "\n", + "- задавать правильные вопросы; \n", + "- находить основную причину проблемы; \n", + "- находить закономерности среди, на первый взгляд, хаотичных необработанных \n", + "данных; \n", + "- создавать модели для предиктивного анализа;\n", + "- визуализировать и отображать результаты с помощью графиков, информационных панелей и т. д.; \n", + "- наделять машины интеллектом; \n", + "- определять лояльность клиентов с помощью анализа настроений; \n", + "- принимать более качественные и быстрые решения; \n", + "- рекомендовать правильный продукт нужному клиенту для развития нашего бизнеса.\n", + "\n", + "#### Чем занимается специалист по Data Science? \n", + "\n", + "специалист по анализу данных решает бизнес задачи с помощью следующих шагов:\n", + "\n", + "♦ задает правильные вопросы, чтобы понять проблему; \n", + "♦ собирает данные из нескольких источников - корпоративные данные, общедоступные данные и т. д.; \n", + "♦ обрабатывает сырые данные и преобразует их в формат, подходящий для анализа; \n", + "♦ загружает данные в аналитическую систему - алгоритм машинного обучения или статистическая модель; \n", + "♦ подготавливает результаты и идеи, которые можно изложить заинтересованным сторонам. \n", + "Всё это позволяет решить немало проблем, некоторые из них приведены далее: \n", + "♦ обнаружение мошенничества и выявление аномалий, например изменений схемы снятия или расходования средств с кредитной карты клиента; \n", + "♦ целевой и персонализированный маркетинг - персональные рассылки по электронной почте, системы рекомендаций на сайтах магазинов; \n", + "♦ метрические прогнозы - показатели эффективности, качества рекламных кампаний и других мероприятий; \n", + "♦ оценка принятия решений - обработка больших объемов данных и помощь в принятии решения, например о выдаче кредита на основе кредитных оценок; \n", + "♦ прогнозирующее моделирование - прогнозирование столкновения метеорита с землей на основе астрономических данных.\n", + "\n", + "\n", + "#### Профессии в области Data Science:\n", + "\n", + "- специалист по данным; \n", + "- дата-инженер; \n", + "- аналитик данных; \n", + "- статистик; \n", + "- архитектор данных; \n", + "- администратор данных;\n", + "- бизнес-аналитик; \n", + "- менеджер данных/аналитики.\n", + "\n", + "\n", + "#### Основы компьютерного программирования\n", + "\n", + "Что такое программирование? \n", + "программирование - это то, как мы общаемся с компьютером. Программу определяют инструкции, которые являются конкретными и последовательными. \n", + "И точно так же, как рецепт, когда программа составлена правильно, нас порадует конечный результат.\n", + "Чтобы заставить компьютер сделать что-либо, инструкции должны быть записаны в виде компьютерной программы. В компьютерной программе вы должны последовательно указать, что именно вы от него хотите. Затем компьютер запускает программу и выполняет ее шаг за шагом, чтобы сделать требуемую задачу.\n", + "\n", + "\n", + "#### Компьютерный алгоритм\n", + "\n", + "алгоритм - это конечная последовательность четко определенных, реализуемых компьютером инструкций для решения какой-то проблемы или для выполнения вычислений. Алгоритмы всегда однозначны и используются для вычислений, обработки данных, автоматизированных решений и других задач.\n", + "\n", + "Алгоритмы можно изображать в графической форме с использованием определенных обозначений. Полученное изображение называется блок-схемой. " + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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RYtpbWtjxowZ8ewJlm2xZftWFi1cxLBhwyg7ZYbU19PY2MgzzzxHTU0N8+fPj/t+Shl6UZO9ZVlkMhmam5t59NFHAXjzm9/MhAkTEldGo9EcLg7aLKRavQ43bW2tdHd3U1tbR1NTU+x/+eWXA7Bp0yba2toAuOOO21mzZjX3338/H/nIP1MqlXjooYf48Y9/xLp163Ach3vuuYd/+7fP4routbU1vPWtV3LBBRfS2trKE088QVdXF4sXL+b555/HMAzWr1/PunXrWL9+Pc8//zzLli2lsbGR5uZmHnvsUdraWikUCqxevZoVK5YD8NBDD3LvvfcA8L3vfZd7772HhoYhrF69mi9/+Ut0d3ezcOFCVq1axebNmwBYtGghzz//PCtXruTBBx9g8+YtLFq0iHvuuZsXXnieTZs2cccdt/O///s/gEFrayvXXvtDli5dEpfJ4eBwCs0D4XkeL7zwPOl0mi9/+atccMGFAHzgAx/kHe94JwDLly+jra2Nm2++iSeffBKAF198kUWLFrJ161YWL17EX//6HESjbdete5X169dxzz338Pjjj/HYY49y6623UC6XWbJkCUuXLuHpp58CYOXKlWzfvg3btnn66ae4447bAPjLX25m4cJXuOuu8IPhy1/+EosXL6KpqQnTNFm1aiVLlhze63a0IPXIgeqTo+k+O1SsXbuW7du3M3PmTKZOndrrI47oo873fcqOE378eWGTt+u67Nixg7vvvpvf//733HPPPXR1dVFfX4/jOARBwDnnnsvFF19MV3c3S5YsYeHChbS2tvLGN76R97znPQwdOpSlS5fS0tJCS0sL48aN42/+5m+YOXMmxWIxjke6SJRKJRzHwTRNuru7KRSKOI5LuVzGdcssWbKYFSuW4zhltm7dwosvvsBJJ53Iu9/9d8ybNxfHKVEodFN2Spxx5hm8973vZe7ceZRKJTo6OqipqeGtb3krV199NbNnz2Hbtm10dHRgGEbYhcDzaG9rxzAMZsyYQWNDI6tWrWbr1m2Uy2XGjBlDLpfD389gVdd1WbduHZs2beLkk09mypQpvcpbo9EcXg5ajB5J+qo3hg0LhemECRPiyuXyyy/nttvu4J/+6cNs2rSJm266kUcffRiAT33q0/zxj9dz0UUXsXr1al566SW+//0f8slPfoqGhgYAcrls/BJcvnwZTz/9FLfffisAvh9wySWXcNNNN/Mv//IxiMTQwoULGTp0KACLFi2iUCjgeR7FYhHf93nyySfIZrN885vf4oILLqC9vT0WqgA33XQTjzzyMBs2bCAIfMLOWOESeH/4w+/icG1tbTzxxOMAfPjDH+Yf//H9APz5zzfEYV5rdHd34/s+NTU15PP5uJuFTMtCVI4nnXQSF198CQ899CAAL730Iul0OraSLF++jKeeepLbbpNr7dPV1QXA17/+VU466SS++tWv4TgOAIVCAaKXnbyg5T7du3cvt9xyM0TXDGD37t0AfOUrX+Pqq98D0YA8zfGNavHdu3cvCxYswPM8JkyYQDqdji14gTJRfBAEmFEd5EVLbjqOQzqdZvr06Zx66qnMmTOHcrnM0qVLcRwHy7LYvHkzS5YsYe/evZRKJbZs2cLw4cM5+eSTmTVrFtOnT6erq4u2tja6u7sZNWoUM2bMYNiwYbEIlTwMGTIE0zSjj6+l7Nixg3K5TKlUwjRNdu7cwZIli8hm0+TzWfa0NAM+s2fPYszY0Zxzzlmcf8HryNdkyWbTjB0zmhMnTKBxaCMGBvX1Q5gzZw5tbW089tijbN68ORTh5XLcf9ZxXVpaWujq6uLEE09k+vTpbNiwgRdffJFCocCIESPiulqsolKeVjQl044dO3jppZewbZvp06fHfUw1Gs2R4ZgWo/l8HsMw8LxwtKnw/PN/BWDlyhVxU83JJ89m2LBhnHbafABefvllmpubAZgxY2avykgskuVymXvvvQfTNJk8eUrcLNjR0cGXv/wlFi1aFB+zdu0aPve5z/GJT3w89vP9gPPOex1nnHEmjz/+GB/96D/H+9rb2/F9n2KxyNvediUPPPAAAMViMc7zI488zH/+5zfjY0RY//CH32fhwoW9/FtbQ3HzhS98nh/84PsAFArFOMxrjbq6OjKZDG1tbeze3cyWLZsBaG3dy5o1q0H5aDn33PNYunQJ3/3ut1m0aCGzZ88hl8tDfK2/yKJFPeWtcuaZZ8fxAIwfPy7eDgIf13Xij4gPf/iDdHZ2xvsB5s8P78ePfeyj/O53vwVgxIgRvcJoji9EYAobNmxg48aNTJo0iXHjxuF5HqVSCU+ZnUSefdO0MK2e/o++79PU1MTFF1/M2666ine/+91Mnz6dVatW0dnZied5bN68mU2bNgFhulLHmKZJsVjEjVYjkpWJGhsbsSyL7u7uKM3QKhsEAUOHDmXixImsWLGCO++8k1dffTUWe+VymWXLlxLgM3XaFDzfpVwukc6kyGTTQEA6k6LslHBdBztlAaF114oGqO3Zs4dnn32WZ599lu3bd+C4PVZZ3/fxfB/Xcdi+YzuO49DU1MTUqVNxXZeXXnoJCGhoaMCtsFSqEc1BGgQBr776Khs2bGDChAmcdNJJoK2iGs0R5ZgWo9lsltGjR9Pe3s5zzz0LUeV8//33ATB37jwaGxtjfyBuLs/nc9TX10MkGgzDwHXDwUKZTIaVK1eQyWR473vfh+/7/PnPN2CaJradYtiwJt71rnfHosEw4LrrrmPDhvX8/d9fzfDhw2N/wzD4whf+nX/4h2tobW1FsKMl7UzT5J3v/BuuvvpqrrnmvVxyySWxGL3wwgu56KKLoyN6miZ37drFiBEjOOOMM2I/OeaCCy7k7//+aq6++mre+973xvtfi5xzzrn4vs+nP/2puG/Y+9////jtb/8XgLPPPhuA006bj22nuP/++/B9n/nzT8cwjIrXOslNN/2ZrVu3xr/T6fCjpru7GzMadCMvuV27djF//nxGjRoF0cvv4x//BDU1NbS0tJBKhdewuzu0vGqOT0RIEt0nS5cuxfM8pk+fTl1dXSyiZEonM+orKqIvFLM9glb8MIxeVkrHcchms1x44YW8+93vZvz4CbS0tGDbNnv27KG1tZX29na2bNmCYRh0d3dTKpWoqamhs7MzttCLBdfzPOrr67nkkkt429vexumnn87o0aNjkdfW1sbWLVs4+eSTGT9+PMVCgbq6OlzXZePGjXR1dbFgwQJuv/12tm3fFrUUhSLXi2YN2bxpEzt27ODyyy/nH//xH5k1a1ZsEU2lUliWRbFUYm/LXoYNG0ZjYyNjx45lwoTxbNmyGcMwqa8PrbciYknUt7t37+bll1+mXC4zffp0amtre30caDSaw88xLUYBrrrqbQB84xtf58c//hHXXPMelixZwrBhw3j3u98dzzf6pz/9kZ///Dp+9rOfAnDmmWcxb96pAPzgB9/nllv+wtNPP4VhGMybN4+PfvQjfPKTH+exxx6D6KWRyWSoq6tlypTJfPjD/8w//MM1EFXWe/e2kM/nmTBhQvyykUq8oaGBD3zgg9x88y3xMnO1tbWcccaZAEyaNJlt27Zz5513MGxYE8OGDQPg3e/+e774xS/16g8r8X72s59jypSpsd/FF4eidfTo0QSBz+2334FtHx8DPAbKv/zLx5kzZw5btmyJujmE1NTUcPXV72H+/NMByOVyzJkzJ95/xhlnkE6nqaurZfLkyfzTP/Vca6KPjHQ6zUc+8lF83+e2226Jr/n//d8fuPXWW1i/PuyH/NRTT8VitL6+ns9//j/i6xsEAb/+9a/o6urife/7f3zpS18B6CVuNccfgTJ10IoVK1i4cCHDhw9nwoQJ5HK5eNJ5dQaPnu4lAX5ggJUiMGx8w2Lzth3cfe8D/N/1f+ZPf76Bzdu3MePkWTQMG0rZc3l143oWLVtGc0srjU0jmDPvNLqKZe578GHuf+gRNm/bwbARo1i7biObt+1g6YpV3HP/g6xavZqdO3fQ3Nwc59cyLZpGDOf0s8/kvAvOZ+yJ4/GMACfwad7bQiqXY+qMGaSyWbBtThg7lqaRI/nriy9y01/+wsMPPUzL7haWLF3Grta9ZOprsUwbu2yRN7PYlkFndztr1q5l8bKl7NzdTNEtU/IcAssA26RQLNHe1sWQIUOxrQx1tUOYNGka6XSOTCZDPp/DVGZ2EaFpmiau67JixQrWr1/PnDlzmD17Nhyn/ZA1mmOJY16Mvv3t7+DUU0+js7OTW275C5s2bWL48BF87Wtfp75+CLNnz+aKK65g165d3HDD9ZTLZd70pjfxpje9mXe+853MnDmLZcuW8dOf/gSA973v/3HiiSdx1VVvY9myZbz66lqamobHojfsfxiOGB8/PuxXmM/nmT17Drt37+bb3/5W3A8wnDi6p6KTF0pdXR0Af/d37yKfz/Pd736bxx57lJqacAqpfD5sIrbt0BIwbtw48vk8I0aMBGD69OmcfvoZsdW3rq6O17/+Ik466SRuuOF6brjhBiAgm31t94MaNmwYP/7xT7nnnvtiC/N3vvM97rrrHj7wgQ/1Cjt7dihGw2bISRBdV5kdQL3WdXV1ZLNZ3vrWqxgxYiTPPvtsbGXfvn0bP/nJj2Or1q5dOxk5Mrxub3zjmxk2bBgNDY3U1NSwbds27rrrTlKpFBdeeBE1NWG3kxNOGI3m+MYwDAqFAkuXLsWyLM4555z4PpF+jYKIVyOyTvq+jx8YBIbByFGjOWniZHa37GX1mjV0dHVx9jlnc87rzmPU6BMYN2E8u5qbWbFiFU3DRzL/9DM4bf7pvO78C2nZ28q69RuYfcpcJk6azNr16/EC2NW8hzVrX8W2bbq6uli3bh2BTBlnhU32PpDOZjjxpJOYOn06Q4cNZdr0aVxw4YWMPOEERo8Zw7xTT2Xc+PFc8cY3MnbcODZs2MCoUSdw0UUXkclmmTn7ZE6ceBIEMGLYCKZNmsrJs2Yye84stm7dyuYtWzhp0kROP+MMampr8SLrbwCcdNJEZs44GdtOEwQGs0+ew5vf9BZOP/30eKYUwzCwbRsjWrTFj/p7L1++nGw2y7nnnht/GGo0miNLVSswoTQFWZZFuVxm165dWJZFY2NjryYQaRpRfw825XKZe+65mw0b1jN9+gxe//qLyGazvcJs3bqV3bubGTdufDyoiGig0fr16+nu7mLChAnU1w+J9xWLRdasWRN/PQNs27YV3w8YO3YsQRDw6qtrY/GyZMkSuru7mTBhPJs3b+bkk2f3WiXGMAzWrl2LYRhMmhQes2XLFl59dS2maXHmmWeSTqdxXZelS5cye/ZsTNOkpaUF3/doahrOkiWLGTZsGKNHj6FUKrFu3TqmT5+OYRh0dHTwyisvg9JHdrAJgoDOzk4cx+m1ApP0MZM+WvJyOFz3BGrzZXSP7Nmzu0+h9+c/38Avf/lzLr/8Cj7/+X+HPq71pEmT6Orqpqurk5EjR/Hss8/gui7nn38B69a9Snd3dzS6fjG/+91vueyyy/nsZz/HK6+8wvTpM6irq2PPnt0UCgXy+Rquv/5PXHrppcyYMROArVu3UFdXH4vb1wpyreT+kOsmIswwDLq6uli9ejWGYTBt2jRyudxhu5cONYZhsGrVKq6//npGjRrF3/7t31JXV9erDKQvJ0pTvfSFNKM+lp2dnezZsyf2S2cshgypJ5vNUi6XaWlpoVQqYVtp8vlaampqYotrW1sbHR0dNDU1sXPnTu644w6mT5/OtGnTACh2tfPYo48wYcKJXHnllRhRV4GS62ClbNLpNG1tbXheuMpSS0sLQ4YMob6+vleTfyqVYvfu3XR2dtLY2EhDQwN79uwhiAZEpdMpSqUSxWKRXC5HZ2cnnZ2dNDQ0kM3mYn+pW7q7ihSL5djPjLokdHV1xR/zajmqwn758uX88Y9/ZPz48bzvfe+LB2lpNJojy3EhRg+WZIV1qDnY+Ks9vtpwh5LgGBGj++Pmm2/k+uv/RGtrKz/+8U97NdkfDH/3d+/kvPPO52Mf6xnUpiIiS/PaEqOGYdDZ2clf/vIXFi9ezOWXX865554bD5AU0SdWUBLz9ar09Cu1sG0Tw/RjK6AIVs9zscw0BhZlpxwOGLKs+IPd8zx27tzJggULmDp1KieeeCKGYVAudPL0U08xdOjQeKCd7/n4Jhi2Fa7QpMxMIXU+0fMvM0xkMhn8qE9oLpeL73nf93HKDhgmhhEO+LSURShMq/cSnhK35wbYdti/WvrXSt0ndYyUnaQlVt677rqLl19+mXe+852cf/75UKFMNRrN4eeYb6Y/FAy2IDjY+Ks9vtpwmt4sWLAAMPj4xz95yIQowHXX/YIPfOCDSW+Nhu3bt7N69WomTJjAKaecEos0+XBLCiQRWuq2Gy1rGQ7wCQWo5/YsC+z7IkyjOUK90NJqRM395WixCt/3GTp0KGeffTajRo0KR6y7LqZpMX/+fKZNmxYLvoBoeqlILKuiT823CGHJsxfNUepEa9iXy6EoxjAwMDCxsEwLCAeSlsvhfKoiNuWc1fzL6H9JU/apwtWIBlcBbN68OZqIf3xs/dVoNEcHgyJG1YrzcFMp3SPll6RSmAP5yXY1fuKOVo7WvH3nO9/jttvu4G1ve3ty10ExbFiTXl5Q0wsjEpEvv/wyra2tTJ06laFDh8aWQ1V87Q9DGV0fCq+oCd/vEaISzjRNfGVkufihDPAxDCNu2bBk2VG7p8nf971wCr1E3kQIGmaPRTIUwGHrmG3bGKaBbYf95YOg5zxFQPs+YJiYpo3vg++Hll7DMDGjeE1TmU2AfVs85JykXNQ8mqZJe3s7Tz/9NHv27GHevHlx83wyHo1Gc2Tolxjt68FNVk5SwcUV1QEq1kr0lVZfSMUi6aruSPklXaUwB/KT7Wr8xB2tBAdxPwwEEedHq1PzqXntsHnzZhYvXszo0aOZPXs2qVSKIOojqj7TJIRjoFgIiQY6ieALxZ6NYYR/bTsdzkkaOYKeOjJZj6giTuK1LQvLToFpExgmng+eD4FpgRHGadtpLCuFYVgYWJimjWWlMA0LsDANK9yPGe83sACTIADPI7SJRuch09eF+ZHfJoZhEfgGgQ+mYWFGA0PFAmpE1k85B6kH1bLavHkzmzdvZuLEicyePTsemKjRaI4OqhajgbK2r1opqi9SCeNES9ZJfyb6KQzUyrI/rueL+7XrpCzUa3IgJ+GS5XkgVymevkjuT17zwXLywjpanaFYuQfTyTXoj0uS3K869b7Q7EsQ1Zm+77NkyRJKpRLnnHMOw4cPj5uuLWV1MAlv23av5m4S94pMAWVGzeK2lca2MlEfURsjsCEIrYzJ+8BUrKNJAiAwrFCMmja+YWPYaUw7jWmlsMw0lpnCNOzYWWYK28pg2xksMxWmj0XgmxiGjW2lMSP/+HgzHO1uGEZs/ZRzMY0wLIGJ7xtAKHKDoLdwlvKR4+Q85Rnr7u5m8eLFFAoFTj755MMysFOj0fSPfolRlIpQ3VZfrGb0pa5+qSZfVgdyatza9c/JtUqK0/05L9Evq1qH0synXjs1D34FK25/74cj6Srl9UB+6vnuz+9od9XeE8nnVdM3r776Ki+99BKNjY1MnDgR27bjvo99faSIaFS3g2hwoBEJ3H2vV/SBGYT75HiJQxW9cpyI2iCy0oqlliDAssx40nlDsaLK8T3xKx+2gY/r9tQBahjLsuJVoFQkf2Eee8oB5YPZi1amkvxKntV3kJxjJpNh+/btrFy5kpEjRzJ9+nSsaFClRqM5eqhajKoVoVDpgbYsq9ekzYEiSqp1aoWiXf+dXJv+uIGUubyUxMlLpy8n+5PX+2h2le7dA/nJ9oH8DrdLXo9qnEqP0OntkveFZl/MqD/lypUr6erq4rTTTqOpqYkgCLBtm1QqhalMRaQ+Y+JUsSjXE6UeFv/k9Uapv9X4xF8VdUYkbuU+lTASXtKQ3+LnRQOiZLWkHnruIYlHZl+RdNTzUcVusgyS5y1xyl91vxxbKpVYsWIFruty8cUXx0t/ajSao4t+Te3k+z62bVMqldi5cyemadLY2BhXpFIhqJWBWnEciECpiDUDR30JVctAy9zzvF5TO8l0MfJCFAuMp0z3JS85zdGPPJOC+vLvi/7eeyj3rNQZEocIEeMYn9rJMAy2bt3KjTfeSKlU4pprrmHkyJG4rhufH9Fzov4WpExUISh/HcfpVW960byf6rESPvlcoghliS+ILKOGYZBKpeJtMS6YUeuXF7W+iFXXiEa5oyy/qSL3kmVZvYSopJt8X0g5qGUj+yUf6v0iQtZxnHj71Vdf5c9//jNDhw7lfe97H42NjcfMPaPRvJaoWoGolV2ygpApO+RvqVSKv5D78+BLnOpXfbVOKlntBtbNIVme1bpkPMnrmXSaI0PyOhzIyUdDuVyOLV7i3GjidbnfkveEZl9c1+WFF15g48aNTJkyhSFDhsTPqgi45PMRKM3S4uSZEyEmx8j1kOtHVI8mr1OlY+V6yvUzpc9mor43DAOCcD5QNU7Jmxwn8cox6n0heVLTET+VgN5dBSQty7JiSzKREJcpoAAMZNWlsK/oggULaG5uZs6cOQwZMkTfnxrNUUrVllG1onRdl5aWFojW+ZavUyP6MvaiL3P5Ok5WsgdCKp7+oF+EPZYHsVT3B3lp9Qe5tl1dXZTLZWpra+P5EiU+27bjF5aEl5dLf+8LzcCJxUSVGIZBqVSiVCqBcq3FJX9L3Oq+/qAKIfVZVuM/li2jmzZt5MabbqK7q5v3ve+9jB07Ds9zcd3wucAwMA0D0wonk/cDn0CpmoMgIACs6CNBylkVcqp/oFhRpV4QoZh89vxognpVgIq/aZqYplzbcG13EYUSrxtPvN9jHZX6H2VifrHGSp7k2vm+jxkNsPKD3nWQXHt5J6TT6fi3vGskn+l0iiAIj7Ftm7Vr1/K73/2O2toa/vEf388JJ5ywz7lrNJqjg6rFqAgKy7Lo7u6mubkZ3/epqamJKwcUS6kV9R0dyItJvpz7g+SPChaG1wryckin07EIrBap2PtD+KIy6erqwnEcampqyOfzmGb40vI8r9e0NfKyE2vHa/U6HQnkpT4Q5FhxSSFKdO+VSqW4jqirq4vvJxElRiRcitHyjiJOyuUyQRDEq3eVSqX43pVBM2Y0KvpYFaO//8P/sHz5cubNncfb3/F2LMsm8H28ADxfmrdDsSVVsmkaeJ5YO2XUu0HgeVhxEzUEQe++2KqoFH8j0TwOcu3CDwBVZMYYPqFODkVvKCB9wMQ0eqZGCp9tG9M08P0AxynH9b+kbyqDpgA8zw/jMsN6JOWn8QKPslnECAxsPw0mGBYQGDhOGTPqHiB5QanzTNOM5h8Nuwy4rsODDz7IAw88yOWXX86b3/xWUnb6mLlfNJrXGlWJUXmJlMthJdPZ2cm2bdvwPI/a2loM5eu7LzHan0pArWyqwVCsba91jMgyKpaLapDrdjBiVCyj+XweFHGrWkdUMVpt3jSHBlU4VoOIw2w2Gx8nccjLX7a3bdsWW1DlWbRtGzfRH/KEE06gra2NcrkcryleX19Pa2srxWKRpqamuNXFMIxwAvZIwDQ2NuL7PmvXrsU4BsXoxz7+YUaNOoG3v/1tTJ8+A8/3orE9RihGfQ/f88MJ4i0bwwAvqtNUYWka4YpF6pXsEYphWYRlbvYa2W6aFtAjTD3PRwYXGb266YBhgGGamGYQbRv4kXgM5/80MbEgEsgigA3C85B8hHUQuG64VGjYfN4z0AgMvCCsC7JmHgyfslGESIyatklgBAR+KILlPgrz2FMCUj6+7xHgkkqn2LhhI//7v/9LKmXzoQ/9E2NGTzhm7hWN5rVIVWIU5Qvbsiy6urrYvn07QRBQX18fVzLyIhLryP7EaCU/lf3t64uBHHM8IiKxP+WhvsyqRV4IMoCprq4uWq2lp4+XXH95CaovviSV7olq/QaLSmkdyE+2D8ZPpVq//WH0Q4gKhiIkZbsvlzyuvwTHeTP9h/7pH3nrW9/K5ZdfTjqVDsUoEPZyNOMpmIIgfH4ty4ynRSLuVxpgWTaplI1BT9N1kBhlHh4fWkFlnxF9QHiJgYTy21OauwXDDK2zcj3jsg4MLDNs8lc/YIMgwIvikGsmdUGPYAzzJPkJBSSkrQwYAY5fhiBaINQyI8HcM3gKiCy1AD3xhP4Q4OF5Lg888AB33HEHF154IVdffTUGNsfIraLRvCapWowKRjRacdeuXZimSUNDwz6iU0TrQF5KmmMPaaavra2NLaGa4wOxbqKITBEafTEQgXi8i9HPfu5TXHnllZx88smxWATCfqHKR0lYrgEE4EYC1DTDZTRdxyUAMtH8nCL0HMcBw4jn5QyCANMIBW7gB7jKgCEAz3VJpVLYqRSOU47TCoKAdCoFUUuYafaIQLWcA8/HImwW9z0PU+p6wyAwwkFFAZDJpAn8AD8IsKLr6jgOfhCQyaRDS6rnY1om6UwK3w9wyw6+H2BaYXjP8yAIsFOpaFL8UAz7fk8fVCBaaQoM02fHjh388Y9/jGctmDF9ViRE+75nNRrNkaVqMSoVXyqVolwu09zcjG3b8dROfb2c1C/hA6FWyNWET3KsvJgGm4GUuXxM9BfXdeno6IjFqNpM7ycGMBnK9DCaw0t/y1zEi2opq5b+psVrQIx+7t8+zbhx46ipqcF1XTKZTPxc+NHUSNlcLup3GVpIS8UiQSTEAFIpG8eJJse3wmvjeR6lUgkj6taQyWQoRsehDGqyLItCoRD7pVIpstksnudRdhxIDA4iamY3jHCuziCaDzUAcF0Mz8eLwqXTaQzA9X1IWaHg9P24/3h3dzee55HP5/GiblyZTAbXdXEdj5Rtk6mNxGkxFNdmxsQpOT1lFFtcwXWBIKyvpFXOdd2wO4AV0N3dxbZt27n44ou57LLLSNkpfN/ACDugyiXRaDRHEQMSo47jsHv3bmzbZujQob2+UNUXyUAZyAtQ0xt5CSWvRfK3MFAx6inzjNbU1JDL5UC5X+TeEDEqYkNz+OlvuVe6J/obR7WIADpexei3vvN1zGg0uvSZDiKLIdFzkslk8KOmcxFa6lRa6XQ4ACeI+nGCQblcolwO5xlNp9OkUjadnV3Ydrh+vOM6pOxU3IfXNE3S6TTlcgnX7Zlb1LIsamtr6erqxHFcautq8Twfp1yOB1HFH5KeRyqe+svpWUnJgIIbvhtEIAPU1dWRy+fIpMM+wGFcZtgn1vExDKgZmoPAxOv08IMAMwelQhnPDdN2XYdy2SGXy+H74HvSjB/eI+FgKR/PL2OnbKZNm8aFF1zI8KYRQEAQmNoyqtEcxVQtRuPK0wq/fHfv3k0qlaKxsbGXGJUvX6m8Kr3QBoMg7hQ/8BemUUG8VfI7mjEOwso5UNTR9KnIiqOKCc2xi3rv7+85UPcN5GNS6pfjVYxu2rwhag538dywn6RhgGVaBL6HaVrh1ER+gOu5gEE6lcJxnfi4qPskhhn2Jw0IIGr6Rtaxj1YdwjDCaaCU1ibLsjAi4el6Hr4X5sP3PIxYpJYxDINMOoPjunieGw6YUqadch2HdCqFaZiUyj1Tf6XSKVpaW3jkkUfYsGED5XKJYcOauPzyyxgzZlzPtEuWjWVHTfvR68fKRO8QJ+oDage4Ts/UVwbgRN0LwtmfwvMV4W4YoTh1nBKGaTB8+Ahqa2qU+yMU7xqN5uhkQGI02UyfHMAkX+AiUvsjSCSdoFcfqn3jCJuyel5abjRlTHt7O21tbRSLxdiSK90IxFonLz3LsuIvdYkn+fdAfoOF5EktC0lTtpN+ruuSTqcZOXJkPKm2GTW1ikuWo0p/z0nS7+jooFwuU19fH01N0zNYSd3WHFtUuh/kvkv6qST3V4PEq973KGIUoFAosHr1agCmTZtGNpvdJ+2jlYGUybFIa9tubr75Zl5++RUKhW6mT5/O+973PkaNHJsMelg4Vu4Pjea1zoDFqAxgGjp0KHY0ub1YNbxoNL0qlvqDCEZ5ESXFjIjK5cuX88QTj7FixQpOOeUUzjnnPHbs2MHOnTvp6OjA932y2SzZbBbTNOMmryDq/yT5Rjm/araT+RlM+lN+pVKJuro65s2bx7Zt2zAMg4kTJzJy5MhYeKtWbJX+pCPI9W1tbaVUKtHY2Bj3BZP7QW2eFwaSlua1gTxXco+oz1mxWGTVqlUYkWVU+l0eC6j5VOsPtX4hYVWWuqY/qHWVUCkOdX+ldKQu7wv1+qjH7m1t5pZbbmHx4sUUi0WmTp3KP/zDPzByxJhoENG+17Uv9pd+X6jxDuR4jUZzZDgoMWpZVmwZTYpR9Xd/keZ2KvRbC4KABQte4o47bmf9+nUA5PN5rrzybRiGSXNzM3v37qWrqwuATCYTd8x3oiVKiSbiFj+x3qkvBvVv0k8VsYNFoAwgkbwdiGKxSENDA+eeey5/+ctfwuY74JRTTuGyyy6jsbFxn/LkICptyVdbWxulUomGhgYtRjUHhSrS1N8ollHjGBSjSfp6ppPnL37JsJXCqVTar/oFiZaVZBi13CWsbFfGwDBg954d3H77baxbt55iscgJJ5zAu9/9bsaOOTF5wAHpO639o+ZXo9EcGxyVYjRZgUrFUigU+MUvrmPBgpcwTYtTTz2VM888i1mzZtHdXWDXrl10dnbS2dkZT8KdyWSwo+mGZA1jI+rwLn4iRtW05XyTfiirwgwmUqH2R/Q6TtjBf9KkSXR2dvLQQw+xY8cOAHK5HO94xzuYNWvWPi+cgVwjqhSj8mGhxaimGirdk+rzf7yI0SNJsswORrhJPSVx7Grexq233sL69Rvo7u5m5MiRXHPNNYwfN3GfdDUajUY4KsVoJQqFAt/97rd59dW1TJ8+g/e85xpGjBgRN9nLtCZeNNWJ44Srfohw9KP5+FQxKpa7ZB6T4jP5YrSigVnJ4waDgaQhXRFM02T79u28/PLLLF68GN/3ueKKKzj//PPhIF9CaDGqGQS0GD08VCrng0Hia94dWkbXvvoqra17GTN6DB/44AcYPWr8IUtLo9Ecf1RvdjvMqF/bpVKJa6/9Aa++upa3vOVKPvOZz/YSokE0kl5G8vvKWshmhWZp+W1GI0ilX6kIWtkW/1wuRy6Xi/1F4Eq/08Fy0u9WLY/+OIAxY8Zw5ZVX8i//8i9MmTKF++67j6effppAGRyl0WhemyTrxoPFtixMwwjnTsUgnUoTjoUHPZpdo9H0xVEpRtUKMggC/vu/f8TKlSv427/9O6688qpYfIoQDaLpTbq6uuju7qZUKsVz87mui+M4lMtlyuUyjuP0cm4075+6LccmnQjecrlMqVQ6LE7yKfmvxpHoaxsEAY2Njfz93/89M2bM4N5772XVqlW9yk+LUo3mtcNgPfeB61HuLlLuLhI4HmnTwgqOjAhNfphrNJqjl6NSjApBEHD33XeyePEiLr30Mi677IpYhIqQUsMSzaGXTqdjJ1M7pdPp2PIp+6xoEudkXH1xuCs20zSxbTs+h2qdoQxMSL503vGOd9DQ0MCNN95IW1tbHEaj0Wj6S7LuMKJ+7nbUqlMsFuOVmvTqRxqNpi+OSjEq4mnz5k3ceustzJ07j7/923f1KUTlGPFPikYJKxWl9F/0ozlR92cxVS2l8lcVd4OFpKF+3ffHqX001fhs2+aKK66gWCxy9913H5ZzOR7p7g5naxA8z6O1dW8vP43meEetZwEs2yadTiOT8BuGQRCL0cP3Ia/RaI4tjlox6nke999/P67r8qY3vTkWm5WEqFSIsk/CJQWkhJUwySb55O++nJrmYKGeU3+dKkpRhKgflc/UqVMZPnw4y5cvZ9u2bYmUjwxbtmzh29/6z15+hUKBz//bZ9mzZ08v/yPN7bfdyuOPP97Lb/GiRfzov64FoFgo8Itf/Jz/+PcvaIGqgQp9vo8nep1PVP/YkSiVOZ7DcINfb6pIvZd8X2g0mqOPo1aMFotFXnzxeSzLYty48bHQSlYsUrlLk7YMWkpaBqWClDCCDERKDkiS39L03df2YDqxLBysQ7EOy9+zzz4bgEWLFh0VFfbmTZtYsWJ5r3zs3dvCpk2b2LVrZ6+wR5qXX15AXW1dL7+u7i46O0Nr6fU3XM+TTzzOiJEjaGho7BVOozkekedWPvzNaFlS+XgnaqQ/0vWMRqM5Ojkqxajv+yxfvoxCocCIESNiv2RFpgqu5Oh5EVhynBFNyaROyyT+Il77cnKcODX+wXIq8lvdtz8/+ujfKmF932fatGkYhsHy5b0F4KGm2rgDAlzXZfv2fS21QRDG89STT/K73/2Wu+68I17UYPmyZXE413XZumVLdEzl8ABbt27ltltv4U9//D+uv/5PvPzyAohmbbj7rjv59a9+yYsvvBCHV3Ech40bNzJ9xozkLvyoOXLhKy8zfvx4Pvzhj0CUl2eeeZpf/eqX3HffvfELesWK5XFzv+u6vc7l6aef4je/+TV//etzsd8rr7wcl2d7e3u8NKbm2KLaZ+JYIaxX1O2wzvU8j0KhgOM4EPlpNBpNJQYsRgejYlHF06ZNmwAYNeqEXmJLnIoqvOSvn2iGV48VK2uy+d1TRsxXCiO/y+UyxWJxn5Hvh9IVi0XK0ST9UrGreaqUT9nuC7Xs8vk8o0aNoqWlhY6OjmTQw47k6+mnn2bnjh3s3LGD9evWx/v//Ocb+PnPf8bSJUu47bZb+cH3v0dr616++c2vs3btWgAefvghvva1r+J5XsXwwv/85lfcfPNN3HPP3dx915387Kc/IQgCfvD973HjjX9m7dq1/OhH13LPPXfHxwi7doZW2mHDhiV3sWfPbh5/7FHa29v51Kf/lUwmA8Btt97Cz376E1avWsXNN93If137QwB+/atfsXjxYgBWr17ND374fQBu+cvN/OLn17Fs2VL++8c/4rZbb6G9vZ3vf++7tLS0APDIww/xne98K3zRa456+qq7jgeCICBQBic5ZSc+T6m/MEzMRNcjCaMaFY5GjtZ8aTTHE1WL0WRlIU3IntKHUioZCdffilcN39HRDsDw4SPitMXqqf4Wp6aZTFfEnIhTEWzJ+JLHiJOKM1mJDibqefQnPcmnKqDVfKtu5MiREFkKB0pQYaUo2ZZ9sl0Nt992K5/61Cf41Kc+wc9+9pPYv7Ghgc985rP84IfXcs1738eqVStxXReA9vZwVoD29nY6Ozvo7OysGF5mD2hrb+d1rzuf//3t7/m7d70b3/dZt24dy5Yt5eOf+CTf/d73efNb3spfbr6J7u7uOA8ALy14iUmTJ/c6X8FxHH71q1/yutedH5et7/vcc8/dXHHFG/jBD6/lE5/8FC+/vIClS5cSBOFCDEQrgQW+T3t7O3feeQdve/s7+K//+jFvvfIqbr/9tviDoRytLOa4LsVCQUldc7Qhz2G19/6xhhG1ELW2trJ+3To2bthAc3MzXV1d8XugWCzS3NzMrh3bWbVqNVu2bNlvvXs0Ui6X47pMzvl4vq4azZFg3zdqH6iCw1BGSibF6EAESBLDMHDdMN76+vp9ms1VAdqXEDWUZnnJmypG1f3JOCtVkoEiSk2lf+pgOYlfzU+1zvO8eEYAEaRq2Uj51NbWAtDa2qqcafWoZV1JjPrR4gOG8qHSJ1HWLrroYr74pa/wxS99hWuueW+8+9LLLscPfK6//k/cdOONADiOi2VZLF26lGKhEDfRG0bl8KqwbGhoIJvNcsIJJwCwY/t2ampqmD//dADmz59PqVRi+/bt8TFEfVvPOvOsXn5CLpfjoosu5rnnnmXtmjUQlW2hUOCCC18PwOzZc8hkMmxYvw4i8f2HP/yeP9/wJwDWrFmN4zi8+MLz/PQn/81fn3sOx3HifrNlJ5xHlqicU9GytpqjDxGjxytSFxaLRZ566inuuusuFi9eTCabpb6+nrq6OnK5HMuWLeOee+/hrrvvYuPGjXF9YRwDQpSoC41ad4kYlfeIRqM5eKoWo4eDSg928mUrgksYqOB9LZAsT1WwoojGxsbBHWSTzMf+uOTSy5g5cyYzZ85kzimnxP4/+q9r+a9rf8iCBS8h0TmOwyWXXMr9993LP/7j+3jxRennafQZXjCjQWylYmhpDAjI5XJxXrPZLABeZH0VVq5cyegxY3v5CQ0NDbz/Ax8km83xox9dS6FQiFV2PpcDRUCKVXfXrl0sWvhKPKtBsVgEoLOzi917dtPY2Mjrzj+f0aPHQGSlESSPxzP9uXeONtQP3ANRTZijlYaGBkzTZMPGDWzZupVUKkVNTQ11dXXU1NSwc+dOli1dhud6TJw4MT7uWKm7s9kstm338ku+hzQazcFxVIlRtXKyrDBrntdbDKiItS9p9dP0vNzUv2rlaRgG7e1hV4jRo0fH/oNBNddG+pxVanru7u5iwYKX+Ju//Tt++MP/4u3veCdE4vKa976PT33qM/zj+z/AtGnTITq3vsITCdCamppwuxSKv3w+z+7du+NppDZs2IBhGIweE4pAgM7ODtraWmlq2re/KIQmWcMwOP+CC2hpaeHRRx8hmw0F7spVKwHYs2cPnZ2djBs3HoBr3vs+fnjtj/jIR/8FgGHDmgB499//PV/96tf5zL9+lhEjRpJKhS9DQ5mrUbVGH69Uc+8crRhR68uBSD6rxxr5fJ558+bR2NDI1i1bePXVV9mxYwd79+5l165dbNu2jWKxyJQpkxk6dGiv+vpou75STyavhbQuJankp9Fo+s9R+TYzDIO6unDqnHLZ6dO6UMlPs2+5yO9kxdnS0kI+n2fIkCH7HHO4yWVDy6Fcd6J+yQA1NTVks1lWrVzBc88+y5133A6A6zoYhsHpZ5zBJZdcytnnnAOhJuwz/P333UtLyx6GDx8epwMwffoM8vkavvfdb3PDDdfzpz/+kVNPPS3uygCwePFiamtrGTlyVK9jiYShFYnDN77xTdTW1vLyggXk83lmzJzJ73/3W2644Xqu/eH3aWho4OTZswGorQnjl7/Tpk1jzNix3HbrrTz33LN84+tf46EHH0QmDH/8icdZu2YNW7duobu7m5aWo2sOVk0PRoXFJyohXViSz+exxPTp05k+fTqe51EqlWhvb2fPnj20trbS1dXFSRMnMm/ePFKpdHSEEd/TR+r8K9V4geRFaZaXwaTJpvpA6ZKm0WgODusrX/nKV5OelVAfOt/3KRaLBEEQz4lpmmb8sKphB/qw7tmzh5dfXkBTUxNz586LK6pkfJW+YjUhUi7qX3lB+r7Pgw8+yNixY5k3b95BlaNU1Ol0OhaQcr3kZSwVd19p1NXVEfg+Z519TnxMPl+D53mcccYZjB03jgULXuLVV9dy5lln09DQwOvOvyAesU4kWju7OjnvvNcxctSoiuGffvopampquOqqq0il0gTRvXbBhRcyY+YMli1fxqqVK5g5ayYf+OAHSad74nddj9FjxvRqahRSqRS5XI7JU6aQTqeZNHkKtmUxfcYMTjllLps3beKVV16mafhwPvihDzN8+HBWrljBKXPnMmzYMMqOw6aNG7jggguZM2cOixcv4pGHHyaXy/GhD/0TY8eN46knn2TZsqU89tijbNu6lSAIqKmpYcaMmcnsHLNUuj/Ez3Vd9uzZg2EYNDU17dN0erQh+Za+hZXOLUk1YfaHPGf9EUpq3iodV8nPUMVcZAEudnfz6tpwujFD6bueSae56JJLmD1nNqZlRscFgB+1iPSup5LbKpLXvvaHDSwGYd8cI55yyjANgshP8IOAwIAgDg+BEZ5PYETxRKvWyTsOJW/7zYdGo+kXhu/7VX2Oqg+d4zi0trbi+z65XI58Po9t23E/ONUaMNCHtauri4997CM0NDTwne98P/5yFidIhZD0fy0j5VCpPMTKvG7dOv74xz9y4YUXctlllw24Yg2CgM7OThzHoba2NhaHcr0syyKIBn8ZkRCulC9N/yiXy3zj619l7tx5vOOdf5Pcfcwi92DyGSdakWv16tUYhsG0adPIZDJH9b0k9ZLjOPHAxOOZ7o4ObvnLjSxevJhUKkVXVxd79+5l0qRJvOe91zBp8lTAjwSh1DW9BeLhRO4cI9qulItK91ele1Sj0RwcR6UYlUr8l7/8OU8//RSf+tRnOPnk2XFzThItRvelr7IQMXrDDTewevVqPvrRjzJ27NgBXSf6KUYl7b7ypukfP/j+95g4cWLcJ/Z4IPmiV+/LY1WMFgoFDMPAdcPZH2Sf2pKkfmzbth3/VuOROIzow9H3fazEQh9E9bNqyZNpiIJo9LsRWS2TH4bqc5p8Xn3fj2dQwfdBeW14vg9BgGVbLF+2mDvuuIOOjg5c16VUKnHFFVdw7vmvI53LYNAzJZ9hGFimjeeFcZmmQbkcdr0xjdBaaZkmnu8TBCJihR4jhJxneI4GhiH3j4FphuFc38U0wTR7yp8gwA8CDCPMj+d5YfO8YWAaYsGFjRs3EgQB2WyWIUOGUFdXF9dzR/P9p9EcSxy1YhRg69YtfP7zn2P8+Al86UtfjlfiSVYAUikl/V/rJMtDXmJr167l+uuvZ9KkSbz//e+P/QdC0A8xamjL6CFl/fp15HN5Ro7atw/rsYrch+o9In7Hohj1o7ljN2zYwJIlS2hvb8eyrLh7U7FYxHFCARZEglP81eWAgyBcoaxQKJDL5chmswRRNynbtgmiJZRN06RcLpPJZDCj1ePCWR3CMvU8j3Q67LepftgbUVN7oVAgm81SiuazTafTuK4bC0jLtrENk1KhEPobBq7n4Xs+2VyGYrGLlStX0traGq9NP2H8BDI1OQIjXH5Z6oQgCMhkstGMFgbpTJqO9nYsyyaVsgkgjN/1cF0H07KwLQvDtHDKHr4fTq+UTqexLKuXuJcptcIZJwyKxS4M0yAVCX3DNHHKZcAgk8mRyWQoFAr4vk8qnSIIAsqlMoZhMGzYMDzPo6amhjFRNx1ZGfBovv80mmOJo1qMAvzud7/l4Ycf5I1vfDNvf/s7elkMkvTl/1qj0gtd6Ojo4Fe/+hXFYpGPfOQjjB49utf16i+BFqOaQ0ile/dYF6N79uxh/fr1PPTQQ+zevRvf98lms+RyuXhCdRGK6vnkcrl4bmSxVjpOuLpROp0mnU6TSqXwolXhyuVy3HdZrJJqvWxEllUikRkEQXyMCFTHCQeMyvMqx7iuSyqVIp/P43sehc4ugsgqGU5V5oV9QAMP27Yol0MhV1NTg+u4+CZ40SIP6XQax3HwfZ9MJg0YpFI2hmHS1tYWi0s5V89zMc1wzmXbtsjlaikWwlXwAqVPJ9HsGOF2KEgtK7R4+r6DZYWCmshaHGKSSYfvr1K5hOuEZQ3gRWJ3zJgx8UfA2LFjOe2005g+PZy542i+/zSaY4mjXoyWSkW+8pUvsXXrVt7//g9yxhln9lkB9OX/WkMtP7VMOjs7+cMf/sCePXu44oorOO+882KLx0AJtBjVHEKONzFaLpfZtWsXO3fupFQqkcvl4j6k0hwvos/3/VicAmQymViA2rYdhy+VSnFzv1hFnWjaMrG6utFE7SL8RDiakeVU0vM8DztaYMNUmvD9qJk+nU7jeV5sqbVtG7dcxnPC7gIirIlmq/D9sItA+NvtiTtlU3bDhThM04z/plI2pmnG17JQKMTnKXWIG3VvCIKAIPDJZGog6IlDyjBs0ndJp9OYUbO7Ey3+QRAKU/X8MpkMlmljWVl8PxT0nufF+Q8I8Hyf7du3s337djo6Oqirq+PUU09l/vz5ui7TaA4hR70YDYKAPXv28I1vfJU9e/Zw1VVv5w1veGOv8IKuGEKS5Qewbds2br31Vvbu3ctFF13ERRddFIvDgVwjQYtRzaFE7sXjQYwSrfq1a9cudu/ezUknnURTU1MvEei6LkFk3VNFJVE9qj47qkgzDCO2YorwspWZLKRc1Ofb87xYQAaJZXzFUijHSryq2IvD+QF2tE+EYhjOw3VDoWwo3Q4sy8LxvbiZXtIIt8Pz6clnQBD0XHMvWtZYysfzPNKpLIaRwnHKmFFXBMm/aQVRP1GTIPCj0fQB+D5mdH5SDqZlQmBikIoXxgii+80APCOsxwqFAsuXL2fNmjWUSiVmzJjB6aefHluTj/Z7UKM5FjgoMep5Hvl8vpcYlUpGPUY9dn9I5ZXEj75Ov//977J7dzOnnnoaf/u376KhoaFXGlK5SsUmFS0VKgypLCvtGywqnduhQj0HsYoAbN++naeffprly5djGAZvetObOP300+NKXH1Z9bccjOjF1tXVRblc7iVG1Zca0UtF0upvOprXDsl7UX1misUiq1atwjjKxajk2fM8Ojs72blzJ62trUycODEWo040yEisdKlU1E8xWmFL6jMRn1bU11KEJNGMCvIMi2BT0yYSoyIok4LTiASuhA+UJY8lPcmDqQhjgoCUGe53owFVqhhV0zQNA8M0KXsuWAYpOzxPSSM8/0gcRnWFnG8QWUWlfCSf6XQOA5tyOUxL4gmnifIwzZ64pDwM38dQPpJ77jODwA+Xd5ZzlP2+EU7/ZNs2CxcuZMmSJXR2djJnzhzOPfdcXZdpNIeQqsWoYERf5G1tbXie18syqlaA6kN9sEhce/e28Otf/4rly5dhWRannHIKZ511DrNnz4FIhKlOKlip2HsqoB7LgVS4KsnfElb+JvdXg5pmf0hWeMk41PMiKvt8Pk9HRwf33nsv69evh6iP2FVXXcWsWbPiil/cweD7fi/LqDTZqS9RFDEq94ZGk0S9j9V7RPyPJcuoETUHd3Z2sn37dorFInV1dQwfPpy6urq4fjIUQVgul+Om5/4ilkMxCJjRh5/UHyJ6pT6Uek+t06opywPVfQeKQ/JUKR6pIyUOtW5O7hMOFJ/6FyW8lLEV9U2Vvqr19fWUSiXcqItBPp/HcRyWLFnCsmXLaG9vZ+7cuZx77rn7xK3RaAZO1WJUxIV8zbe3t+N5HplMhlwuF1eoglrZVqoo9oeISBEvyQpn8eJF3HrrLaxb9yoA9fVDeM97rmH48OG0traye/du9u7dS3t7e9yMJJ39jahDvhONYM3lcnGlVymtILIGiCPR9FUtIpCTGBVeAuIneVLzoFbKZmQVEOf7PjU1NUydOpXbbrstXu7zpJNO4sorr2To0KG9zpOEwO7vOUm+Ojs7Y8toLlrfXV5+cl+IBcWKLDmHg0ovr2oYSP4GktZAynygDCR/VCE+KjGQdJJlrt7nUk7d3d2sXbsW0zSZNm1aPAjnaMUwDLq6utiyZQvFYpHGxkYaGxvJ5XK9PtzVukWO6y/J51ndVv+q+wdy/0n9wX7SSqY7UCoZCgYLtfzlnpP6tVAosGbNGtauXUtbWxsnn3wy50SrvR3sOWo0mpABiVHXdfcRo6lUqtcD7USjJVPRfHf9eWgrVZhqpST7V6xYzlNPPcnKlSuYPHkqp5wyl7a2tth1d3fjeR5W1KlfmrFEjPrK4AGpfNTfUrEGihhkgGJ0IBiReAuUkbYiSGW/aYZNTPKF39DQwNy5c7njjjuYOHEip556KpMnT97n3CT/ybKuFimfSmIU5YNCtYzK+RxO+nPfCf0pB5X+pjXQdAZKf/PHfo6R65/kUJyT+typ96uIUcMwmD59uhajCsnnudLfZFmp9UC1GBXEaKU0kmkNBC1GNZrXDgMWo9JMn8lkyOfzscVUHk6xPMrIxsFm8+bNLFmyhK6uLorFIoVCIZ4rz4pGrko+xGpbKpUoR0tZSsWnOqlcxYkQNAfQ3Gwr049Ug1ohStqSvjjJh1hGy+UyDQ0NnHfeeUyePDm+BoNZqSfFqNpML3mU3+qLTHP0I/dZfxnINZb7RX3uSHyMiigwtBg9IGoZVrqO8mz2Ny25FkKlNNS0ZHsg98RA8jdQtBjVaI4sVYlRI2p29aIJk1XLqMyXJ32WBHm4B1KhSMWWrPj2R1dXF+3t7TjRVB5qNwERa0Rxy7m4ykAfyWcyTclLIJ33+3lOUiYiiPuLmrYqSFGsFHJ+QTT/YENDAzU1NQQVujok497f7/1hKBNxq31G8/k8RJZQP9FML3mhn2kNlOT5VstA8yb3bDX0J+yhoto05fzl3lL9BLn+lfzko7TatCRcX8+V+JXLZdasWQPA1KlT40E/RyOSZxGjpVKJhoaGQy5GK5WzlMmB/hr9/DgMEgJWLXs17qS/UaFerYaBHDMQ+sqz3P/FYpE1a9awZs0a2tvbmTVrlhajGs0hpioxSiQuDyRG+6K/D6xaWR6oMhJxdribf49m/GguQnlxqC8QtTyT10X9bVQQG4L6MvKiQRqqGBV/EaNG1DVCxGhf8Q4W+zsXlWrDVWKgxx3o/j5U9Dd/8kz197kKlEE0/Tk3uU/3J45c12X16tUATJ48+bi1jA4E9ZkUZDvow2pZTf2qEuynVSiZhrptVBgwVQ39ydvBkiw3uR+1ZVSjOTz0S4z6FZrpRYz2pwl6MBBrJ1EFf6AXm1Qih6vCCxTLajWoFX/SX6VS/uVaHehlk3wxSVpSGSfTUlFffqoYVefek3gqxXWo/QaLSmlV8jsY1PgqxV2t36Fmf/fO/hhIvuTZUD+ckpTLZVatWgWRZfRoHk1PVH4DEaMDOSf1eVQJ+hCJRMf0VdZ9YVToM6puJ9OTYwbaVSh5PoeDQItRjeaw07daS6BWQkQPoe/7cXO4bItzHCceJCQV1EBdMo7k72Q++6pk1bD7C1PJHSzJ+A7k5Ji+4pAXWLIs5Bj1pa4eox6bPEaQ49SyTLq+wif9Vb/k8ZXiHKjfYLlKaVXyOxinxlcp7mr9DrWrdM+o907ST/yT8VTj1PikC43UK+LK0ZKX0tdb0xv1OU4+28ntgVApftX/QH79ZaDHaTSaY48BiVGpYJIvIrWvZlKMJsPuz0n8qkvuV8P5ygolqVRqn6/wZHiVZBrJdA+VM5S+q9U6aQ4LEgIyWV7qSzuo8MKQY5LHqvsHiqSvWqZVf4lf8ij7Docb6Hkl46nGqWXZH5eMZ7BcMt3+uErHV/Lbn/+BHBXqFfW+UusUqWeCfnYFOJ5JlmG1fv1xybgqxVcp7kp+1TiNRvPaoWoxqiLCVJoxrGhwjszlKduZTCYWhmrT+YFc0mqS9E/+Vv1Ugj5ebH5isEAyjgP5HSmXLKdK+ZJzUsMkBW5S9Eq/zuTL4EAuKXbUcpXfybDBQbycDpc72vN3uJzcR3LfJO+pvvyS8VTjTNOMPyRlqrJK969at8g9ezQiz2Jfvw/EQM4rWabip+5Xw/Xln3RdXV1s376tV7hSqcTu3bt7HU/0Ibd586Z94l2/fh2PPfoIS5cs2cfi3ZdT4x0sqkkjWbdqNJpDz4DEqKCKJJTRt+oLJSmWDsbJyynpb/RRQaj+6rFUWQkdTSTLISkoVVEg55g8JnlcsjwHiry0ZDtJ0i957QbLHQzJuKpxUpbJv5X8+rqPB9MNNM1K5bE/v0rnrbqkX1/3oXpfGVHLQjqdjj96j2aS93zyd1/IOQ/EJam0Xw3Xl3+Se+6+i2t/+AP27t0bh7v7rjt55eUF+6Sx8JVXuOH6P/WK7+GHHuQH3/8eN998E9dd91NuuunGfYRnJZeMezAcBzh3+lFOGo1m4PRLjKovChKV3dFKUoCJCKNCxRIkmrPVv0n6qtQO5KqtZP1+DHY6VCRFQ7WukphI7u/rmMF2yXSrcck4qnFGwnKi/q3kJ3+T8QyWS+anGscAuiwE0bOgxlEp3uRvNS3pc672QZfnQc7neEbKMFknVOPUOCrFk0yjGlasWE6xWOT+++6F6Do9//xfcZV5peXv4iWLmDp1WnxsEAQ8++wznHnWWXzik59i7rx5PPvM0xSLhX3yfiSdRqM5slQ9ml59aTiOw969eykWi5imSTabxbZtHMchiJr3pP+g+iKsFjW8VBbJF53EK072JyuW5MvYiwZHOI6DaZpkMhlM04z7N6rpoLw01ZegvDT7c17JfB0IKUcrmj+0L5KVqhxjJvqbSlj1fOSv7JNw1SBl7iWmdlKXA/U8b595RqVLwOGg0v1QDQMRO1Ku/WGg+RsIA8nfQMIf7DkF0dRQ0idU7plUKoXjOGzcuJFUKsW0adPIZrMHldZgY0Sj6bdu3UqxWIznGc3n87jR0sCWZfXqOiTPoTyrA0HKRL0WyesiZSv1hIqabnd3N5//t88CkEql+O73fkBHRwdf+fIXeeuVV3HppZeBkuaP/uuHnHrqaZz3uvNj/1tv+Quvv+hihg4dyvPP/5Ubrv8Tn/nXzzF27Ng4nSRSNw3kWRwIajpS9qYeTa/RHDYGLEb37NlDd3c3QRDETWbFYjEWdfIysaOVj/rz0IpQCipYEkkIRNlW01TDqf3PJIzjOJTLZUzTJJ/Pxy8ENZ2gwqjg/Qk3ycOBSIapdJyUtZqO6id/k04EsvTVFb9K8UtFr5Z1Mtz+UMu8LzHqR/OMBtEAJqnc1Ws2WEj8yet0INTr3Z/8DfSl2d/8DZSB5E9EIBXu20oY0QdKuVyuKryK1BPygaOK0VQqRTqdjsVoJpNh1qxZ8cIORyvGAKZ2Gsg9q6KWh2yrf9X9cp/vj1UrV3LddT9l6tSprF69mg/90z9jWSY/v+5nvPvdV3POuedCFHdHRwdf/tJ/8PnP/ztNw4cnowLgzjtv5/HHHuOrX/sG9fX1yd29kJasw3GN1ecj0GJUoznsDFiM7t27F8dxSKVSZLNZrGg5SnmQpUIVsdNfVDHQ1wMv8crfQFldyY+W+EylUr3yIC8613UxDINUKnXAtNT8D+RcBoIRCTrXdePzUHGjWQskrPpiUc+30vlQ4ZiggvBVw1byJypPVYyqy4HKNZBwIn4PJ32d//6odJ7V0N/jBpK3g6E/+Qv6mOf2QMh9JPXAgZBwle5FNQ9WtBLO2rVrsSyLGTNmHNWWUTmXzs5ONm3aRLlcpqmpibq6OtLpdCyyvGiVOENp3ZHjK22r8UvZBfv5kNyff/L6qGFl+6EHH+Duu+/iQ//0YX79q19y1llnM3rMGG75y828/wMfZPbsOfExLzz/PLfddgvf+vZ3Yz+VXTt3cu21P2DatOl84IMf6nXNBUlXvfbqvkrlUq2fSnK/ihyv3nd6BSaNZnAZsBhtbW0lCALy+Tz5fB5TsX4mH+7DjfQxE2vLsUy5XO7zPPwqJrY/HHR3d8diVMSnRnOoKZVK8QpM06ZNOyZWYOrs7GTDhg04jsPIkSPjBUIk76VSKbYASutMpWf9QPTHmlpJnJEQgrL9P//zaxYvWsS3v/NdfvObX7N92zZOPe00nn7qKb7whf9gxMiR8fF33H4b7e3t/MM17439hM2bN/OrX/4cwzD47Oc+z9ChQ+OPZslPMv2BlMOhIClGtWVUoxl8DuppDyILhlSEYpWUykStYAabILIylMtlHMeJrYqSP/kt+TsSSF5Up5ah6ifnQySupWtBqVSiWCxSKpX6fAFVivNAbqBl4itlK/3gUPKghhtoGscK6v2u/t2f3+FC0jzcrlLalfzEP5nfpJ/cR8l9xwKSZ/Xj8Uh8SO6v7JL7tm7ZSkNDA9lsjtNOnU93dzdPP/UUdiq1T1P8+vXrmDhxYi8/gL0tLfzql7+gXC7zgQ98iIaGBkg8D0Jf2xqN5vjmoMRoXyRfMOrvwXJEFbs0aUtfUcGP+rKVSqW4P9rhJKjQB1VeRJX8UGYCEKuzdD+QfWJZUEmWS7XuYKh0vBpvMp1k2seLU89d/bs/v8PljhSV0q7kRx/+ql+l/ZrBIwgCWlv3MuqEEwA4Ze7cuE49YdSofSyXO3bsYNQJo3v5AfzP//6Gzs4O/v7q93DiSScld++Dvs4azWuPQRGjRwoRbzLwQoScVJqqFU9EXfKlXY1LWhWrcVQQndU4acJTz0XEdvJloOaxvwzkGI1Gc/wiA1InTDgRgHw+z5xTTgFgwokn9aqnitHMKmPHjOnlv37dOrZu2QLAvffew5e++O986Uv/QXt7e6+0NBrNa5vjQowayijecrlc0fJpWRbZbJZsNhsPIEAZ0CRdDKp10ixdrRNBOhCMqP9SKpXaZ0CWoOYpKYSrcYeDZJ41mgNxrN4zfeW7kn8lv/5yKOIgEU82m2XkyJHMn3967PfOd/4Nb37zW7j88it6ic72tjZmz55DLp/v5Z9Kpxk3bhxnnXU2w4YNw7QsZp88m5ooXCX68j9SyLnItkajOfQc1AAm3/fJ5XLk83ls28aN+gyqFrvD9fCqoqqvJuy+CCqMLN0fA7E+Jq2Yhxqx2A6U5PmoLxTVL4nv+71G02cymdg/CAIsZYopIxLVybQ0GkHuMfUeEb9CocDq1asxDINp06aRyWSO6nvJSAxgGjFiBPl8Pl5BKgiCeIq5wzmAqS/Uek39m7wWleqBvjCiwUlq3Sz1gPwVJC1Jr79pHSoCPYBJozns9L/WO0qRvqLSPN8f+lvhSUXVHzfYGIkm/f463/cpFAoUCgVKpVJsZXailXBEXGo0mtc2IhKrcRqNRlMNx7xlVOLv6OigubmZQqFAR0cH7e3tlMtlrKgPqRVNti5f6V4076WswNQfodWfsII0oSeRPO3Pz1C+0qVsPc+LR9inUinq6urI5/PU1tYyZMgQcrlcLCDV+CrFjTJvaTIt9a+avqAto5pDidyPle5RbRntm8NpGTWVhTIOhITzEivyqX8FSUviNY6QoA20ZVSjOewc82K0uXkXf/rT/1Eulzn11NNpaWlh165dtLS00NXVRRCtAqWKUen3aVkWuVwuFkzV0p+wgghg+lEmyReDiEHTNGMh6rou2WyWxsZGmpqasCyTNWtWUSh0A/3JZ7JJHgzDpK6ujiuueCMnnzwnLkM1nBajmkOJ3FvqPSJ+r2Uxur/5hjnMYtTqR8uTEfXnl/pAPngzmUxcHzjR4imSlqSXrGsOlnK5TDqdTnrvQ6DFqEZz2DmmxWgQBHzpS19g06aNNDQ08KEPfZSOjg52795Na2sr3d3dEK2prApSonwlK7/B5GAqVi+a0kleBLZtx5ZRx3HIZDI0NDQwfPhwTNNg4cKXaWtrjY9zowFdoXXTJpWySaXSpFI2tt3TtSHcl8LzPFasWMbGjRsAeO9738/5519w0GK0PxYVzWsTubdUQSIcS2JU8p0UozU1NXF3oiASo/KR2ZcY9X2f737327z3vf+P0aP3nTqJCqJxIMjxalzJeEWg9YcgEqFBEPCLX1xHsVjkX//1c3F9cu0Pv8/ll7+BmbNm9Uo3WddUy6JFC3n4oQcpFApMnDiJN7/lrdTX1/Pd73ybd/7N3zJp0qTkIb2QtOVc9QpMGs3gc0yL0WeeeYpf/vI6pk2bzkc/+gnS6TRdXV20t7dTKBRwHAeida+lAhXLom3b+L5PqVSKv9arZSCVpKTbHyQNEZ1GtHypCD7XdSmVShiGQS6Xo7Gxkbq6OoheYEYk/OSvxKlWoGoaYqUxDIOVK5dz3XU/IZvN8v3v/4iampp4n3ru/RGjUsHrClzTF3JvVbpHjyUxSpTvpBjN5/OklBWYqrGMPvHE49x8041857vfo7Y2fL6THCrLqPyttI0iRpP1SF8YkWXU8zx27NjBd779nwB84IMf4tRTT6Orq4vPffYz/MM17+Wss87ulW6yrqmGtrZW/uPfv0BTUxPnnvc6Hnn4IaZMncr73/9Bfvfb/6WtvY1PfOJTycN6IWnLuaqWUS1GNZrBwfrKV77y1aRnJZICpFgsEgRBr+mGRNSpYftbmVSL7/v87Gf/TW1tHV/+8teora2NLaCZTIaamhqGDBlCY2Mj9fX18brp2WyWXC5HLpejpqaGmpoa6uvrqaur69PV1tbG2/X19bFLhqsUJhm2pqaG2traql19fX2c79raWhobGxk2bBiNjY3U1taSy+VIp9NkMhmy2SypVCqu/OVFUq2TyteyLJ566gnWr1/HxRdfyty5p8ZiOnk9g+iF6vs+6XQa27Zjf5QPk2CALxfNa4tK94f4ua7Lnj17MAyDpqam+F47WjEMg1KpRFtbG57nxXWUPGNE5yTPljwzyTL4vz/8jsuveAPTpk0H4M47bueXv/w5991/Hw8+cD+O6zJlylQA1q17lYcefJDtO7YzfvyE+PlbtWolzz77DMuXLWPNmjVx3VIul3nssUd56aUXqautY0hDA57n0bxrFzW1tQDsbm5mx86dZLNZdu3cSWNjI0EQsGjhQjKZDLlcjj179vDQQw+wcsUKThg9mmw2C8rHbxAEvPLKy6xYvhwAx3U4/fQzWLliBS+99CJnn30OI0eNgqglaOfOndTV1WEYBrt27mTHjh0MHTqUHTt28OSTT/DyggWk7BRNTU2orF+/npcXvMTnv/AfzJp1MkEQsGLFci644EJOPPFEbr/9NubNO5Xa6Nz6Quoq0zRxXZeWlhZaWloolUqMGDGCcePGJQ/RaDQHQdWmOqlQBBE7UqnKtlQ+VKhUq0UVSEmCyMr27LNPs2PHdq6++h8IgtCy5/s+VjSfaE1NTSz+ampqYvGZz+fJ5/Nks1kymUz8u5KTY2sjMSoCUQSnKlZVl8/nY8ErTtITMZxMS5waXpwI5vr6evJRnzPbtnudZz6yTvtK/6z+OJVSqcRzzz1DOp3mjW98c9yMKNdW0jgU1hiN5njGirrViHC2olk/ROyocx6rVkdxu3fvZvv27cyadXIc5+Ilixk+fARXXH4FmUyGTZs2ArBq5Up+9F/Xsnz5cu668w5+ft3PACiXS/zi59fx4AP388gjD/PgA/dz99134fs+P7/up9x37z0sXrSIa6/9AStXrGDJksV85zvfiuv4hx56kIcevJ9HH3mYv/zlZhzH4dlnnuHXv/4lTz/9FK2trfzg+9/l+b/+lWeeeZrvfudbdHR07FO3bNm8GYAxY8awcsUKisUiW7aGE+LX1NTEYZcsWcy3v/2f8e8HHrif++67l66uLr7z7f/kiccfY8mSJfz3f/+IlStXxPEDTJkyhc/92+dpbGwMPQwDIxLkDY2NjBk9huXLl/U6JgzWU+Z9vbf2V2dqNJqDo19iVMRHEAS9+iGK34G+8KtF0qr00AdR/6M777ydE088icmTp1KOlvkslUo40br0XjQJvDQ/e8pSmhKHjHAXJ8epThVear5Uf3HJOKV5XZw6VVKl9NTj5JzE6ihl6bou3d3ddHV1USgU8KJZAayoOVyuS3/LXvLv+z6PP/4o3d3dXHDB62lsHLqPRVQNq9Fo+kbEp9SL8puofhRLqaFMzaaKovXr1wHE67kD7Nm9m9Pmz+eyy69g0uQpENWRt99+G5MnT+YrX/0aH/7nj7Bq1UqWL19GsRjWi+9+99V8/wfXMnv2HALfZ8nixaxZs4Z/fP8H+eKXvsK4ceO46+47KRaL+L4ff+Dv3t1Ma1sbHZ0dOI5DqVTivvvuAaCjo52HHnoQz/P4t8//O1/80lcoFos88vBDcf0tdfiWLZuxbZs3vfktOI7DqlUraW9rA2BY07C4bi2XyvhRnQjQ3NxMa+tePM/jrLPO5itf/Trf/M9v0djYyCuvvByXC1GXrDFjxgKwYsUK7rj9Nk4YFS5nCjCkYQitra3KESGGMsK/r7pTPZ/ke0mj0RwcVYvR/VHp4a3kd7BIBfDCC8+zY8d23vjGt/Ty74tKeRG/vo5Vj+lrG+X4waigJC315VSJ/e3rL47j8OijD2HbNm94w5uSu6FCGSR/90W14TQa4Vi/Z/qqFyr5V/Jr3rULIO6L3dnZSalUYuzYUHDl83mI+tNu2bKZnTt38rvf/i/33H0XANu2bo3jbGhsIJvN0jh0KAGwes1qAB5++EH++H9/YMeOHezYvh2ivPzm17/i7rvuZNu2bfieF0/O8cLzz7N3794wnB+wds0ayo7DTTf+mRuu/xPlcplt27eFgSO8qM/oyFGjmDJlKqlUilfXrqWtvY18Pk9dXX2v8EEQcN3Pfsptt97Cli2b8TyP+vp6Lr7kUp595ml+8YvraGlpoVAo9DpOaG5u5n9+8yt83+ecc8+L/S3LIkh8RB/oHjvQfo1Gc/AcEjGarED78hsIUkGL832fu+66nbFjxzJnTrhO8oEqi0p5Uf1kW30ZVNqvhqnkknEcKpJpJNnfvmoxIsvA008/SUdHB+eccx6NjUOrireaMPQjnEYjHOv3jNpyEigtKup2MoxKe0fvNdx3NzcDMHJkT/9KonXkgyCgWCyxd28Lpmkye/acuN8kgGGE1tlyqQQB4V+go72dtrZWRo8ZwyWXXBqntWXLFl5+eQHlcjn2a27exUMPPcAb3vimuL9muVzC9zxaW1vp6u5i2rRpnHPOuaDUTdu3b8PzPEaMGEEqlWLKlKk8/vhjLFm8mFFRX9Ekmzdv4sUXX4jTX79+Hd/4+le5+567ad3bimEYuM6+czc7jsMvfn4d3d3dXHTxJcyYMSMZpBdSPsmyF/ry12g0h45DIkYPNUlLn1RoQRDw4osvsG3bVt74xrccUITuDzlWrYhUp/pV2p/cV4nkefSXZFrVuoFgGAae5/HIIw9imiZvfOObk0FAOdeDPTeN5rWA+lyqgjPpVEGqMmliOA2RCLIlSxYDUCwW8FyXjRvW091diKeMOvW00/jEJz/Nxz/xKcZPmEBNbQ2lSHTmcjmCIKBUDn9L0/+HP/wRPvbxT3LVVW+noaERg/C5/ud//ghf+erXGT9hAgAYYX9ywzS58MILSafD2QwaGsJBlZ/69Gf4xCc+xZlnnU1dXV2vumjLlrBv6OgTwqmpZs+Zgxut7DZKaUZX+djHP8m3vv1dTjzxJABeeuklMpkM3/72d/n8F/6d+vp6XDecMUXlrjvvYPv2bbz+9Rfxjne8s9c+Ee8ajebo4qgUo5WQCvuuu25n5MhRnHba6QMWXkmS8cgLQt1O+qkvleQxSQ6XaOsr/WowDIPnnnuGtrY2zjzzbIYPH1Ex35X8NBpNb4wKg/2kztjfdvIZnnDiiQB0d3Xh+z5PPvkEAN/6z2/yqU99gm3btrFx4wa6ujo544wzWfDSizz33LP8/ne/5Z6776K9vZ07br8NgKFDw1HwBBAQMP/0M0ilUtx88028+OIL/PznPwsH90SP+JBIrNrRAMbamnAE+uWXXUEqFU4eb1kWZ59zDs3Nzdx991088MD9/N8ffh8PVpJ6cdfOnQCMGzcegFNOmRtPQL+PGI3Sb5T0bQvTtBgyZAjd3d288srL3HzTjbS1teEkVrVrb2/n0UcfYciQIdQPGcJjjz0az5dMZAWWAU0ajebo4Zh4KqVCW7DgRbZs2cwVV/T0ZUxW3gMlGY8qLtV94r8/dyhJxr0/p4bvL57n8eCD92MYRp9WZ4m30j6NRtObICFGk89rJSfIMzZ8+IhwSqXmZtrb2+nq6uLiiy/hHe94J297+zu4+JJL8TyPbdu2ceVVb2PWrJO5/bbbWPvqWq686m0MG9bE3r0tnH32OeTz4Yj1SZMnM37ceIYOHco1730fzc27uPnmmxg9ejRXXnUVkydPYdr06dTX12MYBqeeNp/5809n5qyTmXfqqZx51lkYhsHJJ5/MjJkzmTfvVK54wxt54fm/8ugjD3P66Wdw1tnn9Dqn2XPmMHfePCZPmQJRX9fXX3QxhmEwaXLvSeinTJnCjBkzqKsP+5GefvoZnHHmmZx//gXMnTuPu+++K2yCv+hi5s6d1+vY5uZmfN+nra2NO26/jb/cfFPcfzYIAnbu3LnPdFAajebIU/Wk91KxWJZFuVxm165dWJZFY2NjPFWJjBj1oqU2xTrQX9RKTK2ov/rVL9Ld3cU3vvGdeP48CZdsNlaPT8aphhEnxyb/Jrcr/RbUvCQJoheTlFMyvxIm6Sqdk5SrWr6qX6W4D8Szzz7NH//4e04//Uw+/OGP9plHEmVpRBN7O1VMeq9OD6XRVELut0rP0rEy6b3k2fd92tvb2bJlC6VSicbGRhoaGsjlcvHzYZpmL7FqRVNByXMSBAH/85tfs2PHDj716c/wrW99k69//ZsQlZFhGHz9a1/l6ve8h7Fjx1V8XvdHf8P3RfI6qPVRcr+aZkdHB0OGDIn91H1GH/XPgejo6KBYLAIBpmHSODScEeT2227loYce5Bvf/E+GDh3W6xi1bhIns5QUi0VWr17N6tWre016L+87jUZz8BwSy2ilB7KSX39RK4aXX36JzZs3cdllb4grgWrT6CucGr/qZJ8aTiXoo/mtr/B9+VVDMl/ip/7tK1y1+L7P/fffi2EYvOUtV1b9Aqg2nDCQvGle2xyL90yl5zP5O7lvf1x08SVs3bqFzs4O/u3fPt9rXxAEfPwTn2T8+AkVn8dKfsL+9h0sahn0da6GYVAfWT8PJXV1dQwfPpzhw0fw/9k77/C6jSvt/wDcxt4piiIpUhJVqGr1blt2LJfETmxv4hInTttkUzbZzZZvN8kmW5JsetuUTc+mOIkduchN7pKtavVOShSpLkrs7fIWAN8fwIBD+JK8l5JsFbx85uHFYDANM2denJk5U1BY6Cgu9uzZzcRJk95ARAUGy+dg/h48eLhwuCBk9GJB/qp+8sknyM7OYfHipUMKuJEikfAcbPAYbNpNhvt6pHCnMZQbKbZs2URz8zmuuWY25eUVjkYi0WAl0kl073zQ1tbGFz7/OT71yU/wqU9+gs/967+wZfNmd7CLgp6engHXb2VePFw5GKofJcJgYauqqvjQhz9CTk5uwuNAhWZRsWddZJfIT753vk5A/u2WS+cjmy4krrtuBR/4wIfc3h48eLgEcEmSUSHohCDbtWsHR4828ra3rcTn811QIZdIaLp/u/0SPeeOQ4ZbcCeLofIwmF+i9IeCYRisWfMMAHfcceeAQWooJBMmFezfv4/Dhw9RXFzMlClT0PU43/ved2hsbHAHvaA4ePAAP/nJjwb4vVV58XDlIRF5G6zvuAmdjNmz5zgbfhIhmTiH8ksVclncfjKGkotvNpYtX35RNLEePHg4f1ySZBSXMH7yySfIyMhk2bLl502+3HDHkShu9/1EYeRwsl8iAZ0KEsWZjF+y6W7fvpWmpjNMmzadqqpxAwY1UT7ZDTbonS9Me+nyZ//hH/n4Jz7JV776NQoLi3jl5ZfdQS8odmzf7uwSFnir8uLhykKifuImb7Jz308F7rjccQ7mNxK48yr+y/JIXAvnwYMHD0PhgpDRREItkd9IsGfPbhoajnDjjW8jGAxBAiEoI1m/REgkNN3CVFwPN02fLJLJW7Jxi3BD5UcehEzT5Nlnnwbg7W+/Y0CYi4Fk4jVsO4uRSISurk5CaWl0d3fz3HNr+POf/8TLL79kb06wUFdXyy9+8TP+9MeH6LCPFsSeav/UJz/OBx58Hw++/wE+8fG/obOz/77AoUN1THYbxbazadrkOxqN0tXVSVpaGqdPneKxRx916lG4F194nvrDhzl16hSPP/4YjzzyMNu2bR3wTtavf42f/u9PeObppwbYO9y+fRsf+fAHefD9D/CBB9/Hf/3nfzj3rnYk02YuNcj9S1zL/U6RNjEmui/HkQrcbVKkM5hzh03VJUIi+ehGIr83E+705bIM9s7k++7nPXjwcP64IGQ0UedM5JcKhBBYvfoxQqE0rr32+jdsGEqUhuzvvu8WLG7hKgsfd1hcgmowYS7uu59x+4t7g+UVKX+DpeV2Qw0yIg25/nbt2smpUyeZNGky1dUT3ck7z10oJCqjG//w2b/jM5/+FH/7qU8QDodZsmQpT65+gl/98he88Pxz/PxnP+Xfv/RFTNNk3759/PuXvsj2bdt45ZWX+cLn/5Xuri6wSWZzczNvu2kl8+bNp7W1hZbmFndynDx5khL7NBsBkc/P/v1n+PTffpJPffLjhMNhFi1ewuH6w7z66ro3bGBbv2E9dYfq+MmPf8gfH/oDLzz/HN/8xtf5v9/8GoBVq/7C//zg+9TW1vLnP/+Jb3/7m056u3fvBkXhjne+i/LycurrDzv3rnYk02YuNYh+rdq7seVr1WUFRL5299VUIPd/WQa8mXDLomRkkpxHt1+icEOFF7/l52QIf3f9iPejKIrzvnRdR9d15+NYfl/CUowHDx4uHC4IGU0Ed0eXnTtcIgewb99e6usPc9111xMIBInH4+i67vx3ayeHIqqyIJKdpmkD3GDCU4amafj9fnw+n+MSPSsgBJ24L/wGy7MIK8y8yP+H85PzIV9jax3j8TixWAzDMHj22acAeOc778Tv9yd8R0PVw8VAMBiiqKiYnJwcAI4dO0pLawv5+QX8+Cc/5dOf/jsaGxs4ffo0Tz75BFXjxvHd7/2Ar339G3R3d/P0M5am9+zZswSDQe67737edeedgGXoW8ahujoikYhjWByJsGOfB15YWER2tpWXxoYG+9jDNnbv3kUsFiMejxOPx61zu02TlhbLpuNP/vdnrFx5M5s2bcQwDJ56cjU333wL3/r2d/jM3/0927dtY+/ePQCcbWpiwvgJvOtdd7J8+XVvaLseLl/4/X6H2AhZgWT6TFzruo6qqs51qnD3Ubf8kWWNYRjouj7iduaWVbJsc8snv9/vyCA5nPgt/0/Wb7A45DwIf3deRb58Ph+qJIsN2/ScMFMYi8WIRqPouu7EAxAIBAgEAihvgiz04OFqwkUjo7IAGApDCcTHH3+UQCDADTfc5Pi5w7uvk4UQdG7BN5gb7Dkh0C4W3PlI1g2Hffv2cOzYUcaPn8DUqdPdt98y/Pt//Cef+/wX+Oa3vsOMmTN5+qmnUBWVjo52fvPrX/Hoo6sIBoMUFRVx5vRplixZit/vJzs7h+rqiTQ0HAHg3NmzzjGGGa41oQLHjh9j5qxZhELW8g83vvBvX+Sf/9+/8N9f+zrTp8/g2WetjV69vb3891e/wmc+/Sl+8fOfEYv1H0moqgq1tQf51S9/wZYtmykrK6e9vZ1wOMx1168AYPr0GQSDQRoarA1R586dcwhxRmaGE5eHKwMyIZL/Cxki+qz84Zgq5H6fqP8nkpOJ/C4UZMKYKD8CQ+U5kd9wGEoGCn+RLwHT1oSKd+Lz+QgEAoRCIdLS0ggGg2iahmEYxGIxIpGI0+cTpePBg4fUMTLJlyJkAZGo8wphLbv9+/dy6FAty5dfR1ZW1hviEPEkii8ZpCqI5TTdeb2YkAevZP3cTkCUQVVVZwf97be/07l/KUAYzQcoGVVirQ9VLE3Sjh07aGo642iPTNMkLS3NCR8KhdDt4wGbmpqcc7B1feCRgQIHDx5gzJgyt7dzNncwGHLqbFRJCZFIHygKoVCIj/z1R7njjnexefMmNm7YMODpzs5Odu3aSWdnJ5qmYalNrbPBsQdqv99PPB7HNE3OnTvbn9e4d3b2lQTDPuhCcR0PiiS7ZG3e+eBiy6JUkEj+JMJQ94e6NxK4ZST2OxDvRdYW+3w+RxaJ96LrukNGo9GoE68HDx7OH+cn/WwMRQhlEpcMhKB47LFV+Hw+Vq68xbkn4pLdW4G3Kt1UIOfRdJ3MVFd3kIaGI1RUjGXGjFkDnruYGKrehMD/v//7NevWruXFF55n8+ZNlJWVoSoq5eUV/OB/fsg3v/Vtenp62LJlM+np6dTWHgS7jMeOHaWsvILu7m7q6moJ94UBOHjACtPT0+ukZ5omJ46foLCg/2hAmRwA/P53v+XVV9fx0ksv8vqWzZSOGQP2VN2SJUuZN38+GRkZ9PT22ylVVYUbb3wb3/3eD/jYxz7Orl07HUIi8trS0kJ3dzfl5eXs27eXSCRCONyLaZocrD1IPB73BjsbQ7WZSxki32Kjmptoust1IWRaqs+mGv5i4M3Mg5xWot/xeJze3l46Ozvp7Oyku7ubSCRCR0cHXV1dxONx/H4/6enpzoflhSbMHjxcrbggZPRCdUgRz4ED+6itPciSJcvIycl1B/OQBGQtgIBia0X7d9Df7tx7MzBUOxHT1K+8/DI//vEP+fnPf0Z2Tg73v/cBfH4fzc3neO65NTzy8MNgG/qeM3cea195hV/+4ud8+1vf5OzZsyxZspS1a18hHA6zZfNm3nv/vfzgB98DYOvrW5z0OjraaWxsYNLkyY6fyN9Ye3p/7dpX+On//oRf/fIXZGdnc99978Xv89PZ2cm/f+nf+PSnP0V7ezvTpk3D7xfrh/3U1tXy3HNreOmlF/D7/WRlZVNTU8Ovf/VLHvrD7/nWN79Obm4u06fP4Bl7jeuvf/0rHnjvfbz4wvPous6OHdudfF3NGKrNXMoQH9WmaeL3+521iO7yCC2p/MxIkeqzqYa/GHgz8yCn5ZaP1gyGRUiFhtRMsJHJ7/cTDAbf8HHhwYOH88MFOZteLAZXpbPpxXUiuAWQWwh/7Wtfpra2lq985Wvk5eUPWHgvIL5mBcEaKdx5SQZv5tf8SODWsMhlPHSolm9/+xuMGTOGL33py/j9fqf+RlIXpmkmfTa9eFeDpdPR0eFoBAOBgLOJaceO7fzh978jFovh9we4ZvZs7r33PkzT5He//T+2bNlMdnY2t9x6G8uWLeenP/1fDh8+xLXXXoeqKJjA2ldeIRQK8e//8Z8ARKNR/vTHh3jgfe8fkAeR18Hy0tvbywvPP0c4HCYrO5tZM2dROmYMBw7sZ8yYMl55+SXWrVuHaRpkZGRyyy23snTZMjo6OviZna+Kigrec899jB8/nr/7zN8yZkwZU6dOBXswfOyxR7npppW85557B+TtaoBot3IbEX6Xy9n0Aoqi0Nvby5kzZ4jFYuTk5JCRkYHP53M2zPh8PocAib4otKkkIE2D+blloCnJVPm3fJ83UZYlSk+W4fJv+X6q+VOljUsyiRSyR7N3wot+Loinu/40e5Oqoij09fWxa9cuDh06hGEY1NTUMHv27CFlmQcPHlLDW0JGSSAsBerqDvKVr/wnixYt5oMf/OsBRFQOl0iQjRSyoHQLF7ff+ab1ZkCud3d5vv/9b3PgwH7++q//hoULFw94T+6wycC8gGT0QuH//u83VI6tZPm11zp+GzduYN26tfzzP//LgLCJILc19/sfzE8MgqniX/7fP/P3n/0HioqKHL9f/OJnFBeP4h3veHM115cCRB0m6nOXIxmNxWI0Nzdz+vRpioqKKC0V65iF9s1A1frLIEiqgNjNLXblG4aBqRuoZv9aUyseExSFOAa6YaDYhEqx7eRqagBV9RGPW5Y0rGd96EaMeLzPiUfkAcDn67ewIbdvuc7j9hpt0e/FOmjreR+KojjxmZL5pIFjRX+8QtaLOlBs+S7khyVDNCddIb8Me3ORvHtfxKmqKgoapqkQjURQVBW/34euW9ZFVFUlEAjY+YmjKiqK9A7a29vZu3cvDQ0NTtubOXOms/HxUm6DHjxcLnjLyajoyOL/N77x3xw4sI8vfvG/GD169IBw7k4vhONISMCVDCG03XV29GgjX/valxk1qoSvfvUbIyZQMsxLkIz29vQQDIXQ7Kk37EE93NtLZtYbz/Z2QwyeqUDUearo7Ox8wxGFvT09+AMB/H7/AP+rAYkIj/C7HMmoYRh0dXVx+PBhYrEYeXl5Up8wicejmMQxDMM57lP0F/FfkDOfz4eJiWKAT1EdIqXZO73jehzFbx2X7Pf7LT/b9JhPC6BpFrkUcSuKiq7HUFRLXov+qdjaQFG1mqY5ZM00TWKxGIpNKgVBTk9PR7c3+JjSGOCXTMbp9pS3IIuWVtgKL96l0AprmkU4TdMkGo064S35MXDTV1paGuFwmHA47JhtEvkwDANN0yxibVjx+wMB/D4/3T3dxGMxNMXKp2HoaJpllioajZKRlYOu67S1tdHQ0EBraysZGRlMnjyZmpoa0tPTHTnrwYOH88MFIaNiOiMVMoo06Iu46+sP81//9SXmzJnHRz7yMeee/N+NkRAAGSN5frC8XCqQyyTyqigKP/rR99mzZzcf/vBHWbbs2oQDf6owUyCjYqA7n/TeDIwkfyNpRx7eCHeblOv1ciSjpk2m9uzZw8svv0xnp3WSVywWs7SjGOh6FNO2OSrkqGEYzjIRQbwE6UQ3CPj6NaWCfMViMdSgn1AohGpP9/f29gImwUA6Pl8AVVXp7e210jZNVBX8AQ2fTyMYDBEIBND1OOFwGF23tI2qqpKenu7kWch3QT41TSM9PR3T1nzquk4kEkFRFIdgG7bmUpE+lMXHVjweIy0tHb/f5xDPeFxHsa1ohMN9gFU/hv1RK0ijsPvZ29vraEsVRaG7uxvFtnxh5QvAGpt8Ph+hUIhoLEY8EkWJ6wSDQXTdIBgMoOs6XV1dFIyucEhxT08PwWCQsrIyrrnmGmpqavBJVj08ePBwfrggZPR8NaPCfec732DPnt18/vNfSmhyx93pLwQBGGkc7rxcSpAHdJHPkydP8JWv/AeFhYV8/evfcQSpCDdSmCmQUTHQnk96bwZGkr+RtiMPAyG3Xbff5UhGsfvCli1b2LNnD11dXQO0loGAj1g84mgERb/x26a/BOESRDQSiaCakJWRSSwWo7u7G+w10IZhoKuWCTGRRjgcJh6PEwymE/Bb9RWPx1EUxdHMqqq1LjotLY1YPI5pGFbdYqDrcQyjX+4L8unz+YhErHwbhkF3dzd9fX1EIhH8fj+jRo2isLDQybPcP6y0DXtK3UcsGiMrKxufT7NIpE2YFRQCwQCmYWCYJnrcyguKRS416YAPbNJu2OtAe3t7HTuhAJFIGL9fo7c3jK7rFmHXNHyKgt9QQLHaXDAYpKury7IlqoacDwRFUcjPz6eiooLJkyczxrascSm3Pw8eLidcMmT0yJF6/vM/v8iMGbP4xCf+1hHOXOSBfqg8DgaR50sV8iAo8vmLX/wvO3Zs5/3v/yArVtyYkLCOpJ7NK5CMenjrcCWSUYC2tjYMZ62mtXzEyruJYQotqQlm/7pR8bxbA6ei4LfXTYbDlvkywzBAAd0maT6fNV2v2yfWqYoP07Q0kqqY8rfXSPZnU3GIYzAYRFEMDNPKi5CTol/LcvPcuXNs3LiR48ePc675HMVFxdxxxx1MmDCBmH1KmSizbq+B7Y9TAdNaw4m95lRRFOK2vV2fT8M0++WU9YwBSv9711zHcwqCLPvr8TiqpqHH4+jSPZ+qoSkqhj3eKPY6X4A41jKEaDRKNBrF5/ORnZ1NZmamo9W9lNufBw+XEy4ZMvqd73yT3bt38q//+m9UVIx1hJJwMhINWENBGWJqeKg8uiHiEe6tglwf7nzI9wx7vdmZM6f5ylf+g9zcXL75ze8NWIsol8Vdz8nA9MiohwuIRH1b+F3OZHRoyGWQf6vStfgv4jSk3wLua932s0nfMDAM3dI82vWvqAaKYpVDVWwCjVhvqqDgAxTONJ3gscce48yZM7S3t1NYWMj9999PVeU4DFNHVcQsjIGJiWnam5HQks7bG2FKzv284rpnAv3rx1OFYS8xUO01sAKXctvz4OFyQ/JM7AJDFtQNDUfYvXsnkyfXUFU1rl/YDUFEU8GFEhoXKp7zhSCQifIj/OT7zz77NKZpsnLlrQOm5z148PDmQHycif/9zuh3NtHrd7rtb6Ibwt6l7WeCrTKUnB2H7cDa7GNpXw1MSe8gywndXgeq68JyiX1UqaKhoKHroNv+etzE0AFTEGV7Zz8Qj0bRY3FifRFiEfvQBgMwrXzrhgmmimEoxGPWBi6rLKK8A2Xb4E7UmfWMYVgaXHEfi/JK8TEgHRmmtEnMiV+qH13alCXCe/Dg4cIjaTIqE0PT1nghmfZQ7fU64p6sJY1LhoTdcQI88cRjANx8863OFImIQyalQzkBn8+H3+931voIYSLnU15r5Hbu+JCInRBaSPWRrFPtqTHN3ogwnBPaZlFnIk+6vTlAnI/s1jiKgcW0CX1LSzPbt28lKyub666zzkaXy+SO/2LizUjDw5WFy7nNyH1MlOON5VFsMazaBC+BM62pbGuaXcG0w5kJHGa/M00rbtNUsFYADCRUbhnQ7ydknKW5VNBQ8KEoGoqioaKhmKpNNK21nGY8TiwSIRruQ4/GUAwTUFBRwDAxDZvAmiqq4kdVfRiGwkDDFckSPanOUK18OVpWUV53PfbXu7vcQkZLAZyfQm4Lk1EinFxnHjx4OH8kTUbdEMRNl9Z2CjIqd2yxfsctAASOHm1k587tVFWNY/z4CcTjlpkTXEJDOEEI3XEakhkT+Z6ATAplgSKHleMWrl9r0O/caafikoUIK8izzzZZIsiqmzjL+RX1pygKa9Y8g2marFx5ywDzLHIabxbe7PQ8XP7w2owFIbusfu++mxreSIgHwi2vFMVyUgiLsCmAoqKpKpGYtblJVVWwD5oAFTQNZJmLtfnIKssbP/wvJYjyC5mrJDCX58GDhwuDEZNR7M4qC5NEgkUQJnFPDmMYBo8//igAt9xyG0gE0U0AB3OChMXjcWKxGH19fYTDYSKRCIa9UD0YDBIIWGZNzAHTUpbWNmabRZH9EqUhBFEq+XM7QZiTcaZt7kVoesWO18zMTDIyMgaYcBF5luu7paWFzZs3kpGRwYoVNyR8Px48eLj8IBMiuc+7nQxx7SZT8rX4+BUfvEgfuiKcaUI8FqOvp4e+7i56enpQUJzZqEhfhM6ODno6Wmk7d5bOtjYMWzaJ9OQP5ksdHgH14OHi47zIaDJwC0XRsU3T5PjxY+zYsY3S0lKmTp0+QODJzw7lBDT7+DbspQPRaBTd3kglNIrYmlrdJpiKbbhZ1joK8iecsGMnO/l+Ks4d93BOs825CLIct5caiPwqtokU3Z6W9/l8BINBp6xr1jyNYRjceONNhEKWiZPB4AlbDx4uXcjyTu6rhm06Sez4Fh/XcWmGSDzvflZAjlvIRVm2Ij0nZGZzczMbNmzklVdeYd++ffj9PtLT0snIyCAzM5PGxkaee+45nnzySerr6zGkU5WE/Bck14MHDx7eFDIqQxZETzzxKKZpsmTJ8gEkNZHAHAqmbZcvLS0NTdMcDamweycEdV9fH729vfT29jprLoVGUfyXyaoQ5u48yYJUDuf2S+TcmtJEToSNx+NEIhF6enro7u6mq8vSQoTDYacsXV1ddHd3OyZZBKk+fvwYGza8RlpaGjfeuBISfBjI5fHgwcPlAdGHFXv249FHH+UnP/kJP/7xj/nxj3/MD3/4Q1588UX6In0Dl/MM6Pv9fqat7bTwRnnn3BH+dnzHjx9n69at9jGZ1klIxUVFFI8q5uzZs2zbto3m5mby8nId4/ciP/1LDt4ojzx48HD1IWnTTtjCSFVVIpEI7e3tmKZJeno66enp+Hw+dOkoNwFB1GShY5omLS3N/MM/fAbTNPnIRz7GjBmzHA2fEFbJQAhIYVaos7OTtrY2+vr6UOwTOPy2AWhhtBksI8+afZydnD/5fyI/kV4iYT0UUhW6pkSwdXvTkuEcbecjbtsY7OnpQdd10tLSyM3NJSsri5MnT/CjH/2AlpZmbr31Hdx1118NHJSkNMR/971kYaZg2knkIdW683D1QLRB0UbkNnm5mXa6WBB9SFEUDhw4wHe/+100TaOiogIAQ9eZNWsW11+/grR094yIqC9JDhg6KAqGaaIo1myMgrxJNYai9JvqU1DQYzG2bt3CCy88TzRmnW0fjUat6XrNR8TW0t5yyy1ce+21qP6gk+bV+M48ePAwNM6LjBqGQUZGxrBk1A3DMHj22af4058eAiArK4tJk6Y4g0uqwkrTNMrKypk+fSbNzc2cPXuWnp4eTPtEDUFG+/r6iNv2S9PS0lDsM5gFURIQxEx2wl8Qq1TziPT8cH7YdR0MBsnMzHSIpymtITXs6blwOIyiKGRlZVFYWEh3dxe//e2viMViZGVl8ZWvfJ2MjMyEWgiRrhjY3PeTgZkCGVU8O6MehoFog3IbEX4eGe2HqJPdu3fzi1/8gptvvplrr70WM2bJN38ggD8YRI/HOdrQQEvLWUaNKqa8ooJYLMa5s2dpa29HMUw0TSW3uID07AJaW3rIzEgjLzdEc/NZNNVPTk4umuZDUWQZCc3NZ/n9H35Hff0hFEUhHA4TjUYJBAIYhklV5Tg+9MEPUzK69Kp9Tx48eEgObwkZNU2TTZs28NBDv6Ojo8N9O2WoqkpJSSmzZ8+jpaWF1tZWenp6AAZoRmUyGgqFUBTrxBFBlISAF79lJ/wFsRqJcE31GZG2WE6gqiqhUIiMjAyH1MXjcQKBADk5ORQUFNDSco7t27cyceJE3v72O6isrEpYFlMi/R4Z9XCpQG6fbj+PjPZD1EltbS1/+MMfuGnlTSxZvASEOFcV0A22bd3K6tWrOXv2NEVFhdx1550UFBby1FNP0djYiE/TwDSYOW8OE6fMYNu2fcybO4dxVSX88aHfo2kB7rjjneTk5DpT+dY4oBCLRXjm2Wd49dW1xOJRopH+k4r8/gA333wrN6+8BU3z2bZLpQJ48ODBg4SLTkZl0iMgiIogKe5rsXYyGXIkSFRHRwdNTU20tbXR2dlJNBpF0zRCoZD9pW5pEsU0vdgg5M6bHKf7t0CiMg2HVMNjP6NLRpcFGU1PT0dVVWezgqZppKenk5OTQ35+PgUFBaSnp2O6Dg+QyyHKIPLlvp8sTI+MeriAEG1QbiPCzyOjFuR+3dDQwE9+8hOCoSDjx41Hj0RRFIUlS5aQm5vL//3f/6GqKtXV49i4cQPV1dXMnTuXRx55hLFjxzJl8hQ2bdxAKDuDGdfMZ92rr3PzTTcSDBh861vfoGRUKZ/61N9SUjK6f12paZl1UhSTEydPsGbNM9TWHnTGhu7ubsrKyrn/vgeYMKEaSDz748GDBw8CbwoZlf8jaUtlQiQTo1RhmiaBQACfz+ds7jHtNZdimh5wdqUb9rS82JXuJkgyKUtE0M4nn6nAtMmoqC/VPo5O5Ckej9PX14eu6/h8PkKhEJq9A1+3LQkkIqIibtkJopgqTI+MeriA8Mjo8BD9VVEUDh8+zA9+8AOi0ShlZWXE+vpQFZWbb74ZVVV5/PHHefe73830mdPZv283CpYFjj/+8Y/ceuutLFp2LQ///rec62hl2qx5vPrq6yxaMI/Dh/awbu3LTJ8+iw9+8EMUFRUTjxtoqm3nVDExDYO4HmPL65t49tlnnc2i4XCYG264gVtuvo309EwU5Y1LhDx48OBBRursQ0IyAiZRGJkgqZJdO0EOA4EAoVCIYDCYlBMkDHtjUmZmJtnZ2WRlZREIBJy0AoEAGRkZZGVlkZGRQdA2gyTyIZycv0SQ76fi5DSScZqmEQgEnDKKsgj4fD5nA5nYrSrI5XDlSOR3sfFWpOnh8obXZt4Id53k5+dz62238Tcf+xif/OSn+OSnPsXs2bPp7e1FURQyMzNB1aiZNp0p06bhs83CKaoKGMRi1mYjw97kuXv3bk6dOsXYykorrJSWaR+xqesGuv1RX15ezqhRo4hEInR1dVFRUcH8+QvIyspx8no1fjR48OAheZwXGXULGPe18Evkj63pk4mXcKrYtZmA0CVyqrR+EskOJ3b6Qkt3PjjfeMTzqTqx298dl/BTbLt/qn0cq6gD94A1GNxxX0y8mWl5uDLgtZmhYdpa0sKCAvILCigcVUx+USG+UJCM9HTisTjd3d0AHNi7h80bNhCNRBz5iP28aZr4fT66u7o5cOAA48ePZ/z48UQiEeL2jJcI5yxLVRU0zUdF+ViuueYa5yCOGTNmUFFe7jwjPow9ePDgYTCMmIwmO0gkCpeITMpOrJNM1kWjUQz7K10WfIZtMF6YdDJcm6kS5U2GIH3DkcNkIeJL1iERdjkOsaZWlEeQeb9tWF+UX9TvW4FE6Sby83Dl4M16vyPtf5czhExw92ld12lra2PPnj3s2LGD7du3s3nTJhobGskvLkLxaby+fRu1Bw7w6ONP8cqr69lXe4j2rh78wTRQfBhqCFVJw6cE6GxrIeDzsXD+UvLzC4jr1np1sAwzmaZimX1SLbljxKJ0dXTQ09FFb1cPPl+ItLQsurv7sGyZDpRdbvl2ISCPJR48eLg8oX3xi1/8kttzMIgOb5omMXsjkLVz0toMhGTUGOmrPZET4QYTICJMss4dPwkEuEzq5HQGg7jnjjtRPMnAHc9QTg7vjkNArmv5vvz8cEiUbiowTdM5+UWQYVMi8CLORAPpmwF3+a5WdyHgJhDiPYt+Jn7L7TJR2rKf/FvEIfvL93Vdp729HVVVyc/P79fuXUUQ9SH6U3e3pclsaGigtraWffv2sXPXLjq7Opk1axahtBC7d++m7tAhVE1j6rTpHD58GL8/wLJly8nOzqa+/himqVA5dixnTp9mxrTpLFiwkOaWJuLxKNOnzeg/wU1R0DQFFOjuaGfL5s288vIr7Nm9BwXwB9M4fbqJM2fOEAyGyM/PGyAvRfuQZfb54kLE4cGDh7cWKW1gwu748Xicrq4ux6xQenq6s0lIQAxcb5agEANiqhgpsbwSMZL6MwyD7u5uotGoM01nShuvxIYrXded5QQjSWekeLPa36WOC1HnIg75vzzbIIiGrJ1PFiIusfFOrOUW9xTbDNuRI0cwTZNx48Y5be1qgCin6D+irsPhMEeOHKGtrc2pJ8MwyMrKYsqUKWiaxv79++no6KCsrIzi4mKOHTtGMBhk7Nix+Hw+Tp1sIhaLk5eXR3NzMzk5OeTl5XCm6RTRaB9jxpTh91tr0nXdJBbp5VzTaTZt2sT69evx+XxMmzqVKVOnYqp+du7cyZEjR8jJyWHRokXU1NRQUFCA3++/KO/L/UHjwYOHyw8pkVEhAHVdp7OzE8MwnM01g2kpRjKtLYRtKhADWCoQ6aSSlviaH+lg64aSwOh9Ij8ZQ91X3oI1WoKMZmZmEggEnLKa9m56kV+ZXKSKkZTHtElxKhjp+71UIer9QpZHfn+J3uVIP/B0+1he0ZdFPELDHolEaGhoAKCqquqqIqNI71L+nep7lZf2WHWnWLvjTYjHQdPANEHXDTSfgqr2913TNGlobGTnttc5XFdLR0cHpaWlzJkzh/Hjx5OdnYPiD3D27Dl27drFtm3bCIfDFBcXM2PGDObNm0d2dvaAfKSafw8ePFyZSJqMmjZp0zSNeDxOZ2cnuq4TCoUcw/JiYBCCyxyEgA0HQWRSgdj8JNIeDiJcqmQFibDI6bivZcj18WZA1ioli5HkTaTR09PjaEbFrn7Dnqa/UGR0JBhp+3uzyfzFhFzvFxLDxTmSdA17jbciWdkQfVRRFKLRKI2NjSiKwrhx465a006DQdS5qBO5/mUZJO6rqoqCgmmCYUA8btWzVf8KqoZjqL67u5va2gO8snYtrefOUVSQz6RJk5gxYwa5ublomoZhmBiqD03z0dnZwfHjx6mtraW2tpbOzk5mz57NggULGDNmjLXDX/rQ8ODBw9WNEZPR9vZ2dF0nGAw6poUEsRPaU94CYnSx4RboyUIMsG8GUs0bIyRuYuDq7u4mEok40/TYWi7DNU2v2mvFRpK/kXygiPQ89H8cjASJ+pab6MhI9T1hvyvDtgZhSusKTdtKhmKT0aNHj6JpGhMmTLho076XI9zvANd7EPeF7BJ91/IUZNQArDWhmgYo0NPTx5Ejh9mzZzd79+3BROe6pcu4ZuYsMtLT8dmn26mKAopK3LTOuNftTZa6rnPq1CnWrVtHXV0d+fn5TJ48hblz5zBu3Hh8Pms2y8qrYmXGgwcPVx1SIqOGYeDz+d5ARjMzMwedpvdw+SBVspIsGSWBpmwkJCLVZzwi2g9BQlLFUKRzMIzkw8HSrFmaUZksCTKqqiqxWIxjx455ZDQBEr0bd92I+hS/RRirvlVMw9aEKhCJRDl14iSbNm1kz55dRGNRKsrLWLhoAVMmTyE7Nw89FiMaiTjxKKqKgfVRIT4+xcdoc/M5duzYTm1tLUePHSMzM5MVK1Ywa9YsCvILrA8PTDBNBC09D2MvHjx4uMxwXmQ0FosRDAYdA/JiEFLsRfRuApIsRjJwCk2KLHCHggiXKgFjhNO4IxmgR4pUSZj8vlKBIAw9PT1vIKPCiLYYjAx7Oi7VehMYSf5GivNpu5caRDlGWvfyM+L3cPGMpE/JZFS0Fez8CzIaj8c5duwYPp/PI6MXCKZpYmKiqf3r7Zuamti+fTt7dm7j1IkTlIwezaJFC5kwfgKFhYWYqobqC4ICsWiUuP3hqdjWVbA/RsUaftM08QdUdD1Gc3MLW7duZf369cTjccaPH8/ixYuZOXMGAX8aYGCY9vs3bfWsBw8erngkTUYFFEUhFovR0tJCOBxGsU82UhSFvr4+ZzCJRq0zkjMyMvDbUznJYiTEQ7NPcFJSIKOGPXWZTHgZPvsI0VQgpqzeDIyELKsj2ACm2EsPxAam9PT0IcmoQFpamrMecDAoioLPPo0LoLOzk56eHpQkSZViW32QNW3DwbSnh0eytORSx0jaRKK6lv3k34Zk51dsaJSX6sRisYS77EUbEP0pGo0OeF+GpGXzyOjFg2madHV1cejQITZv3kxjQwNpQT8zZ0xjzpy5lJaW2uEMTDRM1VqjL2w967qOoqgEAtY7ER8Q4p0bZgxVtdpLX18fhw8fZuvWrTQ0NJCRkcE111zDjBkzKC4uJj0t3U5L9cioBw9XCVIio2KAEGS0t7cX7CM4AYeMmqZJX18fin0UXbJkVJG0lakOMjKJSOZZEU64VKBJO32ThRhUL1UIG6GpQJCRZDWjvb29tLe3u6NJCMUmo/n5+YwZM4aOjg66u7sHEKChoNhkNBqNum8NCtNeE+237eam2i6uNCgJ1jmLuhfvQbHJRWdnJ2lpacTjcXJzcx0ZoGkawWCQc+fOoaoq48aNc+LSbascHR0d6LpORUUFx44dIxAIUFJS4vRReZr++PHj3jT9BYJ4l+FwmAMHDrB7924OHDhAPB5n1qxZTJ1czbiqKjIyMsB+X4qioGg+4rY4d8tq0SZM+4NC9CPdiKEolqwVFjfa29upr69n+/btnDt3joKCAsrKypg1axaVlZWoSv8RxyJODx48XJlImowK0ia+htvb24lGo46d0UAg4BjCF1oMw95Nraa4acUt4C4GZGF5pUAIbLFeUx4URH0OJtSFZjnRvcEgBh63nVFsMmqapqMZEdN2ibSO7msZIr/xeJy4fdRpKkilPEgkONU2e6nC3SZSgdB0uttPov/nC1XawCS0rHLeFXtGxtvANDTc70PIAVzLnzRNIxqNcu7cObZv3866devQdZ3KykqmTp3K1KlTyUoPoSr98th5J4qKbqrAwJ35Ii1Zpoo0FcVAsU9tkvMYi8Vobm7m9OnT1NfXs3PnTgoLC1myZCmTJ9VQWFg0oP1ZcV2YNufBg4dLBymRUSSi2dHRQTweJxQKkZGRMahWbSSDhUxGhxM8yYZLBCVJLdvlBlF/QojLwlz+LUNJoAVLFsmQUUEwBBLlYTikMhClEvZqQbJ1Ivf1kWAk71a0EdFu5I9YQUaFaSdVVRk/fryjYfMwPOR3b5omzc0t7Ny5g71793L8+HFyc3OZP38+NTU15OVZpyYZsT5UBVRFRRcfMqaJoaho/qBDQIW8Ee9CkFHxHg3DBEVHVU1Ms19WizyJmbO2tja2bNnCjh07CIf7KC+rZMGChUyZMnmAKShGKO89ePBw6SJpMiqg2NOfws7oYCcwCYxksJAFW7Jwf3Eni1TT4TwE4UjSGgnerPwJYptoN708Ta/apr4E4U01nTcLghDpIzio4VKH0EqnUq6RtqORQreN3iuSdlr4K5LRe8WzMzoo3PXh/gDs7u7m6NGjbNiwgf3795Ofn8/EiROZNm0aZWVlNjE0UVVAj6PaTUC3zTfpuo6pqNa59nY/F8uPRHsRaSrSx76Jjmn2z9gIf/HRIZZiiHe8d+8+ag8eQtcNZs2axZw5c6ioqCAYDFrxee/dg4crCkmTUXlgikvHgfr9fmeTkiwgxBfsSEmigBxnonjORyglii8ZCG2ADEHMBvNTLwObl+4yJYLp0q7JZDQ9PZ20tP5BSpBRRdKMpkqIBEzJPmIyEGFHUudC03MlIdl6EzBdZ8wngqgj+f9I69yUbFOqriNFRbx9fX1X9QlMyUD0E+x3Lt5FPNrH4bo6try+hUOHDhGPxamurmbx0qWMHlNuazD717Vb9d8fpyMbTFDs92MkWFYhv3vhJ+JVNRU9rmOa1vItTfOBZdAJxT4JSlFUUKAvHGb/gb1s3LiR5uZmQqEQM2bMYOHChZSOLkNsbPLevwcPVwaSJqNIA5rQjMals+mF0XvF/uoV2qVEO2iHg0xk3RD3RDoCAwRmCkg1b4yQrCgprk+VB5RkIQZtd72IuhH35DDifjLlSZQXI8HZ9Eh2RhOtGU0mLTeSzaMMZYTECKkurwSk8o5lDFV/Ii73f3f7ShaijYp6T0SEI5EIhw8fBmD8+PEeGR0Eoq+rtqbx9OnT1O7fy9bXN3P27DnGjq1g9uw51NRMISc3n5ihEI1GHCIqPhpVW2OJoqBgHRGqKP3WRMTHg5Bruq47M2Ry/xFEV0HBxHrPqv1xLt65uLbagYlh6ERjYVpbmznS0MDWrVs5e/YsU2umsmTJMirKK8nOzkZJoATw4MHD5YeUyKgQGvKaUWFnVN4xLwSV6TqbfDiIcGJHvjAZJWCapmP6RbW/zsVgaSTQVg4Hc4SDtJwurgFZ5NcdpzzQkoBM44pH/HaHGQ6KTXrFc7quE4vFnOlPsWte5F/XdaLRqFOfcjzyf/dvAZmMZmZmOmRUvA8xUMkDpLtuPHgYDHKbC4fDHDp0CIBJkyZ50/QJINfXuXPn2Lx5M1u3bePsqRMU5OexbNkyZs6cSVZWFoqioBsmpupzZK6QA4q9YSwejztyQchX0Y8V14yHkDFIMkzMngniqWmao7Tw2RsmRbqK/dEajcYwjDiaTyEYCqDHdZqamtiyZQv79u3DMKBsTAULFy5k5syZAwjwpYbf/vb/mDVrFtOnz3D8nn/+OTo7u7jrrrsGhPXg4WqG9sUvfvFLbs+hIARQJBLBsDVfgUBggMZLSbD7NlUIAeeGEITiy132d9+7WE6QPbdTbYEqfg/mhsqf+9mhwiZyQqAL8ifH5/P5nIFBQJBGEc5dn/J1Ipj2B4JhGASDwTcQWpEnecDx4CER5L7k9seekWlpaQGgsLBwQFu72iHXW09PD7W1taxZs4a1a9fi0zTmzpnNddcuY8aMmWRnZ9vT6zooKopqyTO5r2LLBp/PN4CMKjaJFITVlGZdVPtD05Q+ugUBFYRRDivLUXENoAk5qFkfz4qikJubS2VlJaNHl9DXF+HIkQbq6+vRdZ2srCzS09MTpv9W4y9/eYSsrGwmTpzo+L300os0NTWxePHiAWE9eLia8aaQ0VQFgyBgpr2OTKxLku+JNIQTkNNOBjKRS9Yxgq9wUQ/J1IUcNlVn2vYdI5GIQwB9Ph+aPUWOnXcxxWZKO5flvIn4ZLivcZHRQCDgDFzivajSAMEgcXjwIJCofQg/QUYVRfHIqARRP7FYjIaGBp555hnWr1/P2bNnqaio4JZbbmXB/HmMHjXKmcHSdR0FxdqYpPnw+fqN1SNteBNkUJ5Z8dt2eIVMFrJCkEvTJoPieRFelgkifvExjDSzFAgEUFUVw7RklGIT4PT0dIqKipg8aQoFBYW0trZy5MgRjhw5QjgcJi8vj7S0NEfmJGpLbzZeeuklVFVlzpw5jt/27dvo6+tj8eIlAGzatIlXXnmZaDTmHC5w7tw52tvb6erqoqury1EkePBwpeKSJKNy+Lh9io4QhPK9SCRCb28vvb296Lr+BiI0lHMLUiG8RL4F3GURv93hBkOi54UAFoOCYU/hizwlejYZiPCiLG7yHIvF6O3tpauri3A4jGkvhRDaUjmtRO/Nfc0wZBRp3a/IU6I4PHgQSNQ+hJ9HRgdC9CfDMDh16hSbN2/mpZdeora2lsrKSpYvX86CBQuszV7BAD1dXVb92QeVqIqCiUJ3b5jW1hZisRh+v59IJEpXVxe9vb3EYtbBEXHbzm9HRwdtbW0WofT56O3tJRq1pvN7envps0/lM+0Tnbq6ujHstaS6rhMO9zkfvlH7lD4k+WAYBj09vbS3txGPRwkE/ESjUTo6Oujr6yMc7sU0FYqKihk7dizZ2dkcPXqUXbt20dbWhqb5CIWChEIhO+43tqc3E0ILWlMzlb6+Prq6uti0aSOqqrJ48RJWr36Chx/+M729vaxbtw5VVZkwYQL//d9f5emnn2Lt2lfYvHkzo0ePZsyYMe7oPXi4YnDR14y6NW7D4cSJEwNOYWlvb6e1tRXdXijvs9cZifVMurT7diRfjqkQJCEwk0WisDIBFSRUhFVsbYLQHGCv6UwVpsvIudBC6Pb60FgsRiAQoKCggEAgwLZtr5OZmUlNzVQmTpwEg9SL+xppzWgsFiMzM9MxvSLKJj5SDG/NqIckIJMTt184HKaurg5FUa7qNaNyP+zq6mLPnj1s2rSJU6dOkZ+fz9y5c5kxYwa5ubmOvDl+rJHNmzdw7OgxSkaXcN111zFmTBnHjx5j3dpXOdV0hlGlo5lSU8PZpib279uHEddJT0ujtHQMNTVTOHDgAPX19UQiEaZPt3a2Hziwn4MHDzofo6H0dGbPnk1bWyv79u+nva2dwsJCbrn1Fvx+P9u2bmPa9GmcPXuWuto6li1bRnlFOdhHwe7Yvp1du3bT3NJMXl4ON954I+3t7bz22muEw2E0TSMtlMG1117PrFmzME2TkydPsmnTJg4ePAgYVFSUs2z5ciZNnISq+gADwzBRlIEaUyXFj/2R4POf/xxnz551ezNx4kQ++tGP8c///E/ccsutvOMd72DVqlW88MLzfOtb3yYUCrFq1SrWrHmWL37xSx4R9XDF45Iio6Zp8k//9E+Ew2EAKioqKCoqoqGhgba2Nvr6+hxio6oqfr+frKwssrKyiMfjdHd3J00YhSByayOTgZpgul4mb4nSF2mJwUHWiIo8CxIqnGmTylQFpqh/sdnL7/cTDAYdzbKmaeTk5FBaWoqqKjzxxKPOs5/97D8xe/acAeURcF/jkVEPFxiijcltRPh5ZLS/Lrq7uzly5Ag7d+6ktraWjIwMZs6cycSJEyksLHRMrBm2MfnHn3iUtrYWCgsLOXT4EJVjK7nhxht46bkXOFJbR9WkibR0tZOekcGY0aXs2bmLwwdrmTZ1GnPmzMHv87Fu3TpGl5YSiUQ4Ul/PTStXkpeXx44dO9ixfTvjxo9n6qwZpKWnsXnzZnKyc/D7/ezatYu58+YybepUnnvueebPn8fevXvRdZ177rmXsrIyfD4fDQ0N/P4Pv0dTNXJzczl48CATJkxg5syZHDp0iHXr1pGVlcW8uQuYO3c+1dXVjhwPh8M0Njay/8Budu/eTVZWFrNnz2bKlCmUlZUR8Ivz7t/c9vL5z3+Ovr4I9913HxkZGZimySOPPEwoFOJtb7uJH/7wfygrK6O0tJSGhgbOnTvHv/7r56isrGT16idYvXo13/zmN8nOznFH7cHDFYVLioy2t7fz+c9/nsLCQm644QbOnj2Loii0tFhTSEKQxGIxYrEYqqqSnp5OZmYmhmE4JDYZKPaUkCBNqUBoL2XI5M39HxcZFRpdcS3CCjIq1nia0hR4MnUo6lsM0uFwGN1evpCWluZYJzDszUb5+fmUlpZSX3+Yp55aTU9PNytX3sL73vfggPIIuK/xyKiHCwzRxjwyOhCiDuLxOKdPn2bdunXs27cP7I/2efPmMXnyZGcGRPQ1n8/H5s2beezxVdx22y3MmzePV155hddee425c+eybcvrTJs0hRtuXcmhRuujf/q0aRyurePxvzzKu+64g4WLFnHs2DFOnTpFWVkZZ86c4bHHHuOaa67hrrvu4uTJk/zql79kzry53LDyJp566ikOHDjAvffey6hRo3jkkUc4dOgQS5Ys4bXXXiMvL4/09HSWLVtGTU2Nk8+1a9eyefNm7rjjDsaMGcOzzz5LXV0dDz74IKFQiJ/85CeMGjWK++97AE0LOPZKDXuTlKJAX6SH/fv3s2XLFurr60lPT+fGG29kwfxFZGVZhM58E9ewf/7zn2P06NF84hOfdPx+9rOf0tHRwfLly/n5z39OXl4eBQUFABQVFfHAA+/D5/N5ZNTDVYVLioyePn2aL3/5y7ztbW9j6dKl9PT0EI1G0TSNjIwMZ3F6X1+fvVbJMkkUDAYd0pMsFEkzaiapTRXhRNihfrv9BIRWdDjNqM82Ki20we54EkEI5czMTBRFoaenh3g8jqZphEIhfD4fuq4TDoeJRqP4fD4yMzPJyspi1apHWLXqERYtWswnP/nphHl3X+ORUQ8XGKKNXc1kVO7v4r9hGJw5c4YDBw6wY8cOTpw4wfjx45k9ezaVlZXk5uai2uaTBMRH8+OPP87mzRv4wAcfpKamhj179vDEE0+Ql59H08nTrFxxI3MXL6S9txtd18nMyGD/nr08/pdV3P6O25k/fz6nTp1i586dnDp1iqamJk6cOMHy5cu55557OHv2LD/96U+ZNn0aN968kr/85S+cPXuWBx54gNGjR/Piiy/y4osvMmfOHF555RXa2tpYsWIF73znO8nMzHTe4bPPPsvx48e59957yc3NZe3atbz66qvcc889FBcX86Mf/Yj8/Hze//4P4PcFidubqkR9aZqKz29dnz59mu3bt7Nr1y76+vqYPn0Ws2ZeQ3l5OVlZWU4dcZG1pZ/73L+Sn1/AZz/7WcdPkNE77ngn3/jG1/nwhz/M/PkL6Onp4aWXXuId73gHgEdGPVxVSGzR+i1C3N7JWVRURE5ODgUFBRQWFpKTk0MoFHKIjWLvuMzOzqawsJCSkhIKCgrIzMxM2mVkZJCZmUlOTg65ubnk5OQM60Q48Xx6ejrp6elkZGQ4To5bdtnZ2eTm5pKXl0deXh75+fmOKygooKCgwLnOy8sjNzfXCS9+J+tEft1xC7+ioiKnvhR7I8Ho0aMBuIhy2YMHD8NAECMh50zTpKenh02bNvHrX/+a559/HoC3ve1t3H333SxcuJDCwkKHiIpZF1ParCm0pfF4zPl47OzsJNJnbUJFsUhva4u1O72nu4dQKER6ejqhYBBd19m1axfbt28nOzubSZMmkZmZ6XzUmqZpf4RaH7ChUIh4PO6UIR6Pk5aWRlpaGgUFBfZsTD1Hjx4dMBsUCoXo6emhu7vbybOYGTLs2RxNs5QhpqToUJ1lU2INqMno0aO5+eabef/738/06dPZsWMHP//5z3nkkUc4efLkgDpX7A9vQfwvJEKhEJmZmQP8NM2HqmpMmDCB0aNLefLJJ3n99df55je/wSuvvOyEy8zMIhAIEAxatps9eLiScUmRUSGILcFiGZf320bahVCLRqPONJRwQljJcSQDIciENnI4J6bPxSCBNOUjpyuEmlu4ifzKAliUTzghWEVYES4Z57dNqMRtCwRyncRt81hCiMu76HVd9768PXi4BCCTq+7ubrZs2cLDDz/Mo48+SktLC8uXL+f+++/n2muvJSsri3A4/AbZJ8tFgNLSMZjAvn37aWhoYM+ePZimycRJkwgEAhypP0Lj0UZeW/8a69evp7vHWnsvZEg0GuXIkSNoqsqsWbOoqKhwZLRpmmCCpmr4fNamy1AoSFNTEwcPHqSxsZG6ujrnY1jXdWpqpuDzaWzZssWZ+QLIzc3l3Llz7Nq1i8OHD9PQcIS8vDyKi4vw2TNFimLJLvGMkKWWzMTOExiGteG1vLyclStXcsvNtzB6dCnbt2/n17/+NU8//TQnTpywHpDk+IXGDTfcyLXXLh/gt3TpUpYuXYqiKHziE58gIyODX//6V+i6zoc//BEn3JIlS/jgBz/kzDZ58HAl45Iy7dTZ2cn69euZNGmSY5jZdJkpksmaEJThcNgx/ySTw2ScyJsgasM5Q9I+uGG6hJl8LT8nyLMcp/gvnJjKF3G485HIifKHw2FHaxGLxYhGo85v4Qzp5BSfz4eux3nhhecoKytnwYKFCd+b+xo7X0J74Zl28nC+SNQ+hF/8CjbtZEqaPsOekl+zZg0vvPACHR0dVFZWsmLFCubNm0dubi7Ya+eFDBZ9H9fUvqIoZGVl0d7RxqZNG9m9eze1tbXMnDmT66+7jnBvmG1bt7Fn/37ONTczffp0pk2dSmdHJ0cbGqmeOJHCwiKOHGmgtq6WY8eOc7i+nu7uLkpLS5kypYZoLMKRhgZGlYyisqqKjMwsWlpa2b1rN7v37KGzs5NFixaTm5tHXd0hrrlmNpWVVbS3t1NVWUV6WjqGYZKRkUlzczM7d+7i4MGD9Pb0Mnv2HKZMqSEej7N79x5ycnKYNm0GCv2nP6mOLWOrvIZpYpqgqhqmCX5/gJJRo6mqqiI/P5+jR4+yc+dOjh8/jmmaFBUVOZs7LzTKy8spLCwa4FdQUODsjs/IyGDp0qXcdtttXH/9CoqK+sNqmubMWHnwcKXjopNRIWCTgSCjM2bMYPTo0Y6mT2gjVcmEk9DsYa/D1DTNsp3nmroRhCuRnyBKI4GIT8Qj/xZ5lp1uH8spk1BRR9iDkUxKBREV5UnWmZLh6mAwOEADij1AyfkXfvF4nDVrnqG8vJz58y0yKsLJ/93wyKiHC4lE7UP4XUlkVPRVXDKyqamJTZs28fzzz7Nt2zZKS0u59dZbWbRoEZWVlY4sEf3YTURF3AKmaZKRkUHxqCKisQh94T4mT57MihUrGDNmDHn5+cTiJvG4wdQpU5k/dz5paenocYPsnDzKKipJT88gPSMT1RfAQGFsZSVTp9VQPnYsxSWjUDSV9MwMSseUkZWVR052DgUFhei6id8fYOYMa71mMBAiFEqnqmo8o0eXkp9XQG5uAT6fH0M3CQbSyM8rABPy8gpYsGARU6dOIy2UjmkoaJqPiopKCvIL3kBEhewEBQXVIqs6KIoKporPZ1leGTNmDGPHjsXn81FXV8f+/fvp7e3F7/eTk5PjjBUyLobcSja+ZMN5GBnEu5WdG4n8EiHZcB4S45LawHTs2DG+/vWv8973vpe5c+eCRNLE1LyYkhYkJxqN0tfXB+B83cqCeTAorun9kUI0YDdpdF+Hw2Enn7K/DJFv0yaqqm2+KtkyCcRiMXz2GixNslcatY1Xi7iR6re3t5e/+7tPsXDhYj71qYuzgUnUSSpl8XB1QbQx0UbkNnclbWAS/UCUr7e3l8bGRp588kkOHjxISUkJ06ZNY8GCBVRUVKDYx/zKclX0r5h0hrxiyzW5/nw+HygGfX09RCJRgsEgaWlptpyBcK+19EnIGjHrI2SAJdtN4vEY8biO5lPw+fo/7sWslKpqKFgfCLquY+jWelRN0/BpPnRDJxazlgtpWv90u2EYxGJxTNOSESJtoWxQVRXTMDHs3fNihimRPLHqxloyIJQUcl0Iv3A4zL59+9iwYQNHjhyxTEbNm8fChQsZM2bMG+L1cGVBvF/BAaz2mzxXSQS5P3tIHRddM+p+VvwXv0WDME2T9vZ2Nm7cyNSpUykuLnY0AOK+cLp9RKgQSnJa7rCDOXe4ZCDCyQ1OLoeIVzgxeIj1mkg2SkUdJHLifiJhOxxEWJEXua7k/Mt5UFWVkydP8OqraxkzpowFCxYOuO+uMxGHSCdZzaj8nAcPiZCofQi/K00zqigKsViM2tpannnmGdauXUtzczNz5szh9ttvZ968eeTn57+h/wrtnZAp2P1LfHiKsCINRVEBA02zNn4KAmg9B5pqfeCLZ3wJ1sYbhkX+/H4/mqqgqtZ6dhFXf3oqum7JP83Xfya9kCFCHqg2mZZlnMivTApE+uK+eBbXOCLkqhXedJQW4nkBkVdN0ygpKaG6upqCggK6urrYu3cvR48exTAM0tLSnA2epmTvWdSxYROYVJ2ISx5/cJXTdM2SyfWUyAm442CQ/jQYzAFtJjUnPz8cziedkTikGUG5bSmKQmtrK2fPnkXXdWf8kp81DMOZ0VSksVA8L5yu60QiEbBnKzykjotGRpE6h/CTG4GAeLmmTUY3bdpETU0NRUVFAzqjgJHAcLy7wckdXTybyE+ON1XIZRCQ8yvyKRySwMTVkN1ODjcSiDLKdSTKKqeD1DkPHz7M1q1bKCsrY/78hY7QleMTTuRR3EuWjMrpevCQCInah/C7nMmou4/HYjHOnTvHK6+8wpNPPsnp06cZP348N910E9deey2lpaVo9pS86DsinkRkTb6vSCRSyBJVVVCU/r6sKBbBNE0FVXnjmlNd2iQqYNpaRxGXIKwW+bU2F5mGAvTLMCF75LLLhE4mWYJMijBy2kKGineu29pbkY67/Nj5jdn2qEV8sjzy+XxkZ2c7U/eqqnLy5En279/P8ePHyc7OJmofWer3+x1iLeKR85cqRBwiHrke3E6EGwxymeX/qeZvJM/ISPZZd14vNuR6lGGaJo2NjdTW1tLS0kJPT88A4umzZ2DFtcivaY/vSOObYXMS0dY8pI7BW/gFwkgauHhGdsneSxRmML+LAXc6cnpiIBgOyYYbCoot0DVnp2l/mUVnkv/H7XWmw+Fi1p0HD1cDurq6WL9+PQ899BDPP/88oVCId7zjHbz73e9m7ty5ZGRkOIMi0oecTNAGygeFfrNG1nIln8+HYg+U4oPUMPtnmXTdcDSYpmmlI+SFYpNJbPInEzixSUi1iaMYgJGWPSlKv+ZTlAFJdsgDuRjorQG8P11rRsfKtxjghZwSdSMIgKw1FvEZ9jp4OZ+maeVBTqOvrw9N0ygrK2PFihXccccdTJ06lVOnTrFq1So2bdpEc3PzoHJPfPAn65DqWchlOW5xrSbY2zDcmOB+FmksGakT9SzXdyLnfm44N1KY9rtM5CfPQAqIvLnfn2ma9Pb20tLSQkNDA1u3bmXdunVs2rSJQ4cO0dnZ6YyJYt+F/C5EuUV6mqYRDAYTauM9JIeLtmZUNF65s7n/m1JjN02TY8eO8Z3vfId77rmHGTNmvKEBXSpwC5BLDaIzyPUsoLjWqgls2bKJn/70JyxYsJBPfeozA7RO8jsSZRdff0YKa0aFoPQ6q4fBMFib5QpYM9rd3c2hQ4fYuHEjtbW1FBQUMG3aNGbPnk1ZWRl+v9+xdiEIhSAAou+QoD/K5EMOa03PWwQurkcxTeuekNUWCVXBtAdZE0zeqB0VaQpyFwj4ULV+WWI6szAGmP2bNk2bPMokWgziobQ0NFUlGo05JqFi9il7oixCVliEWEPXLdLpJp+CKFh5NjCM/joQckrk0zBMVHVgG9NsDTR2uSORCPX19bz88ssEAgHy8/MZNWoUo0ePJjs725Fxot5TaYPyM8KRoL3LTpRZHk9Ffcr/3X6JyJkbIn4Bd52J/4ny6b4W6Qo/Ebechuwn5zlZxO2leeIjyZRmALHzL6ba5XoT6YvyaZpGNBpl9+7dbNu2jdOnTxOLxcjLy6O8vJzJkydTXl7OqFGjCAaDbzCv5e5/pjTGpVomDxYuCTIqGvuxY8f49re/zT333MPMmTOllC8tCGF5qULUeSIBIv+Wr/fu3cP3v/+dpMioEKjiXrJkVJXWhw2FM2fO0N3VRXlFhROf+5l4PM7hw4coLh5Ffn7+gHsyhhMM8Xicw4cOUTxq6HiSgTuPw2G4vF2NkGWDfM1lTka3bt1KXV0dBw4coLe3l5qaGpYuXUp5eTlB27C86Btx12YkwzUFaJo6pmlYG4KiMUv7A2iqgk/14dM0fH4/sViUrq5u/D4faWkhVM3qs33hPvoifZb1ERRURUUNBojqcbq6utA0jdzsbNBN5FMwTHtJjj8UQNEU+sJ9hEIhFHvZgZVHDVXVLAP7upXHQCCAX/PhU/vXoSr2YRvdPd34Q0EyM7NQgLiuE+nro6Ojg6yMDPJy84jrOrFYlHjM0lRpfh+a34eqqJiY6HGdWDxGMBAkGLLqsre3F0wIBAPocR3FXuNq2uS2X0aCafTLNCG3DMNg37591NfX09jYSDwed4hKeno6pmmSmZlJKBRyxr1kIMpvJlg7KupFlrE+276qWAol5K4I53ZIJF4QN+E/FEQ/kpcjyPkSTvZP9DuZtEYCEW9M2qwnk0CZjIoPE3EvEokQtU8cDAaDKIpCMBhEVVWOHz9OXV0dZ8+epb29HcMwyMrKoqysjNLSUioqKiguLqa4uJisrKwB8ctlNaSPNU87OjJcEmRUdEhPM3ph4CZ9gwkO+X9LSzP/+q//nBQZVS6SZrS3t5fvfufb7N27F+x6XrHiBt77wAMEAgFM0+T1LVv4/e9/R3NzMwB33nUXd955lysmC0O9py1bNvO73/7Wieeuu+/mrrvudgdLGnLdJouh8ne1QpYNbr/LmYx+5jOfwe/3M2nSJGbOnMn48ePJzMzEZx/RK/qW6Dcy5P4DCpoGmk8hHo9x4MBBtm7dag2EisL4sVUsWriQzq4uXn31VRobGxkzZgyLFy1idGkpx48fZ9OmTXR1deH3+wn4/EyZPJlxkyeyt/YA23Zsx4jrzJl1DXNmzqKttY3Dhw8zZcoU8vLy2LJ5M75ggLyiQg4eOMC8efPIyspiy5YtRCIRZs2axfHjx9m3bx+6oRPpi1BeXs6yRYvJyc5BURS6u7vZtm0bp06epLOnG18wwKJFi5g8eTLHjx/n9a2vc/zoMTKCaSxauJBx48axecsWamtricfjZOVms3jpUqrGVdHc3Mz619Zz+vRpioqKmD1nNuVl5axfvx7TNFm6dCnt7e3s2bOH6upqKioqANO2Q6pgGGAa1s5+IZsEsYlGo3R2dnLy5EkaGho4ceIE4XAYgPT0dHJyckhLS3PGvWQgyIwgL0K2ijhk+arZNqDj8Ti9vb3OB4noD/J/txPlSJWMBgKBAQoA0fbEb9nJYYRLJi2BkTwjCLaoH1FOkUdBBkVfEu/SZ1uXUVXVOShCtQ+W6OrqwrRPOuvs7HTuxWIxiouLGT9+PKNHj6awsJCsrCzy8vLIysoiIyPDGSdNm/yrw6zv9TA4LtoGJrmhJeo8AnLD7ujoYNOmTUybNo1Ro0al1EjfTMhluhThzp87r25BoigKaWlpPPnkE5SV9e+ml8PL71aRpgzNC7iB6Rc//zmvv/46b3/HO/jY33ycmik1rFu3loMHDrBw0SJOnz7Nf//3V5lQXc3b3/4Orr32OhYsWEggEHBHNWR6p0+d4qtf+QrV1dW84/bbue6661i4cFHCeFKBSDMZDJW/qxmJ6kP4xS/jDUy//vWvKSoq4vrrr2fKlClkZGQQt89WF5Dbgymtt5T943EdFBOrWyls2LCBdevW4ff72bd3L92dXUybPp2NGzfy8ssvk56eTnNzM21tbVRWVlJXV8fTTz9NJBIhEomwffs2MjMzSMvM4IWXXqSnp5d4PE5dbS252bmcOnGC19avp7q6mpycHJ5//nmaW5oJpYV4/fXXqa6uJhaL8ec//9khhGvWrKGxsZGsrCwOHjxIS0sLM2fMICc7B9M0aW5u5vHHH+fE8eOMKinh8JF6urq7KS8r4+WXX+bIkSOMKh7F4UN1HDnSQHl5Odu2bePw4cPk5ORwpLGR5pZmSkaVsH79ejZu3EheXh7nzp2jqamJMjue1tZW5syZw/Hjx3n88ccdTRe2wXxFAUMXU/eWOUJR39gG6bOzsykoKKC3t5fjx49z9OhRWlpa0O3d0+FwmM7OTrq6uoZ0nZ2ddHZ2Eg6HiUQi9Pb20t3dPcD19PTQ29vrHFrS19dHX18f3d3dtLa20tXVlfC5rq4u57+clvBPxomw4XCYnp4eurq66OjocOLq7OxMeN3R0ZFSOrJLpt4Sue7ubnp7e+np6XHy2tXV5dSfcCINEV7Ue1NTE01NTbS2ttLe3k4sFnOIqugXPT09tLW1OUtm2tvbaWpqorm52fkwEEfciv4q+mkiGeZheHhkdAS41BtcKvkT4TRN46mnVjNmzJi3hIx2dnby4x//iCk1NXziE58kMzOTMWPGkJaexuOPPcaMGTPZt28vDUeOcO+99xEKhRhbWUl2djaRSISmpjOcOnWKQ4cOkZGR4QiJffv28eKLL7B3zx4KCwrIysri1XXrOHKknvvvfy9paWlUVlaRk2Mdh9rc3Mzjjz3Gtm1bycnJJS8vj56eHrZv38bxY8c5cfw4ra2tFBYW0tjYSHZ2NgAnTpwgOzsb0zR57bVXeeXllzl+7Bhjxoxxpr1kPPznP/Pd73ybxx59lNVPPEEsFqOmZioAe/fufUOeu7q6ONrYSEFhIdjpxeNxWlta6O3tdc6/PnBgP7m5uTz15JNkZmY6+QNob2/n8ccfY9q0aZw8cYKmpjMUFBQQi8Wor6+noKDACftWIVH7EH6XMxltaGigu7ubxsZGuru7ycrKIj09HdWljRPaLOGPVH5LA6Sj2bvZdV1n//79ZGZmct9999HV2Ul3ZxeVlZWsXbuW7Oxs7rzzThRFYf369YwbN47u7m6OHDnCX/3VX7F8+XIO1dUR8Ptp6Wjj8JF6brjxRqbWTGX3zp00nT5DMGgd7Tl27FgURWH37t0YQFFxMY2NjRQVFbF//362bt3KqFGjyM7OZu/evSxevJjbbrvNmf6cO2cOmRmZxONx2tvb2bZtG9OnTee+996P5vexb98+CgsLicViVFdXM3v2bLo6Ojl69ChVVVWcOHGCgoIC7rjjDto72qk7fIjcnFy2bt1KaWkpK1euJD09nT179lBYWEhLSwuRSISxY8dy5MgRduzYwZw5cygrK0sgy3zOWl0B0zSdftvd3c3p06c5c+YMPT09+Hw+cnJyCIVC+O0DRYZzmr35JRQKORo1ofkUzm8f5hIIBAiFQs5aRZ89JS20lkHpMBPxX7jB4hvOyXGJ9OR8Cydkv+zvs7WO7jiHciKdVPIoXNC2kyvSFGUPBoOEQiHS0tKcehKzJ5FIxMlvJBJxtKniZELsJQCC16SlpTFq1CgqKiooKCggHA5z9uxZWmx5C5CXl0deXp7Td8X0vYeR4ZKcpr/33nuZPn36Jfti5TJdilBdRDKZ/6qq8tGPfoh58+a/JdP0+/ft47/+6z/57D/8I3PmzHH8o9EoH/rgB3j3e95DXV0d27Zudeo+MzOL//ryl3ly9RM8//zzZGVlEwwG6O3t5Rvf/CZHG4/y9a9/jaKiIiKRCKZp8vVvfJNf/sLSwIp4srKy+Op/fw1VVfmX//fPRKMxsrKzaG1p4V8/9zkUReU//v1LTvtWFIW//+w/8D8/+D7f+e73WP3EE2zYsJ7vfu/7/OWRR3jyydWMLi2lrbWVioqxfP4LX0BxLeb/3L/+C5rmY8GCBaxZ8yxV48bxj//4T+zatYuv/fdX35DnvXv38tijq/jGN78FwH/+x38wZ84cTp06haqpfPCDH8IwDB547/3815e/wve/913e/Z57WLRokVOX+/fv59vf+hY//8UveP7551j1l7/wox//hF/84ue0tbXxj//4T07YtwqybHD7Xc7T9CdPnmTv3r3s3LmTrq4ucnJymDVrFjU1NRQUFKDYJpLEwOb3+zGl3eqKvcZSVVX8fg3NB+FwH4888ghpaWm8853v5JGHH6bx8BEWL17M008/DcCUKVNobW3l0KFD3H///XR3d/PSSy/xsY99jDFjxvA/P/gBwUCA3niMg/WHmDJlCgG/n/q6QxTlFTBl8mTWr1/vTFE2NDQwbsJ4Jk+tYf369VRWVtLQ0EBzczOVlZUsX76cF198kWAwSFVVFZs3b8YfCPA3H/5rSkePRtd1Ghoa+NOf/sSypct42y0r2bFrJ3/605+49tprKSkpYefOnXR2dNB06gy93d3cdffdrF+/noaGBqqrqzlQe5CKqkpmzJjB6tWrCYVClJSUEIvFOHPmDNdffz2NjY0cOHCAsWPH0tLSwrlz5/jMZz7D/PnziUajmM5GKcsclZBXgmhpmsbJkydpbW3l9OnTtLa2EovFSE9PJyMjg/T0dAL21H4yEO1UkClT2lyjS7vRhYwUeRDyMy5t2hJhEzk5rZGMUyJ9BklH1JOcltUmUz+cRcSVCIPFJdePyKf4gGOQNaNC0xwKhQiFQsSkI7JPnjzpLL/o6+vDsIloWVkZ48ePp7S0FNM02bdvH/v27aO7u5ucnBwmTpzI8uXLmThxovNu/NJaWw+p45Igo6Jxiw1M9957LzNmzJBSvrSQrAB6qyALIHfHcF8LP0VRkiajqrQuxkiBjIpBNVEe1r/2Gj/84f/w+S/8GzU1NQPufeDB97NkyRIOHDxIS3Mz3/zWt/H5fHz961+jcuxYTBN27tzBl7/yVQC+8PnP8fZ33E55WRn19fXcfscd1mD06b/lU3/7af7yyMO0tLTwne9+D59P46tf+SqVlZWMHj2aRx9dxde+/g3y8/P5j3//Eoqi8sUvfYnOzk6+8PnPoSgKn//Cv6GqKp/8xMf54Ac/xGOPPcqHP/wRpk2fzpo1aygqKmT27DmsW7uWn//8Z/zgf37oaF4F/vojH+ad73oXt99+Bz/4/vfp6wvzj//0z+zbt4/Dhw69Ic+6HueRhx/mu9/7vl3Gz7Ng4UJOnToJJvz1Rz9KNBrlwfe/j//68lf4wfe/x9Rp07jzzrucjVkWGf0mP//FLzFNk69+5ctga4/vvPMu7rp75GtmLxRk2SBfc5mTUcUmmx0dHezdu5c1a9bQ3t7OpEmTWLRoEePGjSMzMxPdPjbY5/OhKJas9ft9aKpGLB4HTBQVQiEfra1t/OY3v2HcuHHcfPPN/PGhhzhz4iTTpk7j+RdeoLi4mInV1UTsU+rmz59Pw5EjvPTyS3zkIx+hpGQ0P/7hj8jOyqQ72kfjqRNcM3sO6aEQ7S2tFOXl4/f5ee655xhVPIq8/DwajjQwZVoNk2qmsGrVKgKBABMnTiQWi9La2saHPvQh9uzZwyOPPILP56O3t5fq6mo++P4HKR1Vggk0NjTwxz/+kRUrVrB8xfXs2ruHVX/5C9XV1Q5xrK6upqutnaMNR7n9jtvZuHEjDUeOMH36DI4cbUDHZMKECWzdupUJEyYwduxYDHvGrrq6mtdee40TJ04wc+ZMmpqaOHbsGB/4wIPMnTvP0YRZhvv9mEb/7nZBANvb23nllVc4e/YsnZ2d5ObmMnHiRKZMmUJRUZFDelKF3J6R5KTcjoWMdYcdCkLGit+MgIyK8rsh503kVc6zyG+qEPlNBYqkCJEhcw83xEeeXzoWG/uZ3bt38/rrr3PixAlnhqm0tJSpU6c666RN02TdunW88sorNDU1kZaWxqRJk7j++uuprq52PioC9jKvy0UmXWp445t7C+Bu3MLvUsWlnDdc5BFX/QoBJbuRCL6RYKjn0tKtafXBEI/H8ft8jK2sJDc3l8zMTObNm8ehQ4cAmD59OtnZ2WRnZzNz5kxOnjjBlJoapkyZwqq//IXvffc7AITtc6j748li/oL51B2q4/Tp00ydOo3CwkJUVeWa2bNpbGwAIDs7m8LCIiZMqKbQnioH+OUvf0FmZiYzbOsPN954I6Zh8sc/PsQjjzxspWlvehDo6uqir6+PsWPHgr02TUAIQXeeAc6ePcuPfvhDfvq//+vkC2DLli388pe/4LvfscILvPTii/zdZz7Nv33h8+zcuXPAPUVRmDd/Pnv37qWsrJybVq4ccP9SwVBt5nKCbpujKSgoYPHixbznPe9h7ty5HD9+nMcee4wNGzZw7tw5DHvpE4Bp6qgqmKZBNBbBNHWszTeWjdAzZ87Q1tZGKBSy1iJGo/T2RcnOzSMjM4vRpWOYO38B48ZPIJSWjj8QJByJEjdMFM0HikpfLIapaOTk5pOZnsX8ufO5/roV5GTn4g8EUDWVvIJ8brplJXfefRdV46tAUUhLy6CluZW2tg6uuWY2eXmFRCLWccNiUF+5ciXXXHMNwWAQzefDQMFUVHzBID3hPhqOHqO1tY2T9pKTWCxGQ0MDM2bMYOXKlWRlZxOO9GFgEolFGV02hpW33MziJUtobm4mHA6Tn59PVVUVN910EzNmzCAQCBIMhlAUlUmTJnPffe/llptvJTc3H103MQ2sY0sVSyuqKhqa1j8t3dHRwZYtW3j66afZv38/ALNmzWLZsmXMnDmTnJwcZxrcLUeTcW4IUitPrwvNXipQpE1Pwgm5nqxLROSQSK0II/IrLw1wx5WME3WeilMGqZfB/JFsgLrLp0pLDAoKCqiurmbu3LksWbKE6dOnO0ufRNy6y5ap8Bf/rxRZ9VYhcevzMCSGaviXAkxp+cNgX59ugfBWl2lU8Siw1+3I6OzsJBaLUVIymuzsHDRJoGiaRl9fHwB+afORsK/47DPP8KUvfZEXX3yBaDQKQDQWIycnB03t/7rWNB+Rvj5MzAGkOBQKEXcdBqDYNgpl+P3WTn/TNPn+97/H9773XXZs3+7UaSxmpS3Q1NQEQEnJaADien8aTz/9dMI8C+zZs5tdu3Y601IAvb097Nq1i7q6OscPYNGiRXz0Yx8jLy+Pn//spwPuAbS0tABQWjqarKws9+1LAm91u7xQUCXbkn6/n5kzZ3L//fdzzz33UFxczIYNG/jd737Hiy++SHNzszVQ+lVUzQRFB0VHUQ3rv2KdVrd27VoOHTrEa6+9xq9//Su2bdtGw9HjmKqPseMmsGXbDv78l8dY9fhqjp44RXNbB9t37cVUfATTMlH9QXzBNNKyc5gxYzYZoUxeeeEV/vzQI+zYsRtfMEBadgZZudkUlRSTU5CHoYLq82PoYJoqkyZOoXrCZNLTMvFpQfbt28/W17cxc8YsbrzxbYwpLcMwTGJxE0PR0E0FA42obrJ2/UZ+9nNrycjYsRXMmTObvLxcDh48wOrVq9m+axcRPU7MMEDV2HfgIA/9+c9seX0rVZXjWLJkKVNrprF+/QZ++tOf8fvfP0RLczs52fmYhoqCD78vSDCYjqr4UfCjaQE0NYCCDxU/um4C1nKIo0eP8vjjj/Pb3/6WnTt3UlFRwdSpU5k9ezbTp0+nqKgIYcpJ/sBP1Y0E7jgSOVneu/0Gc+4wI8mfnJYc32B+5+MM2wqBKeXTcBnjl+Fe3iC0pALp6emUlZUxY8YMFixYwOzZs5k4cSJZWVkDZI94Vkzxy/HqCY539ZA6PDJ6hcLdieVOIn+dytfWSS5vDUaXllJSUsJTT64eQEgfe3QVpmkyddo0xk8YT0dHp1OettY28vLyAJNTJ086/ufOnSU7J4dXX13HtOnT+eGPfszf//1nAYjHYkyorqajo91Jo621lby8fNLT06mrq3Pq6mjjUcrKyp1wiXDrrbdy8uQJ9u/fT09PDzu2b+euu+7mv7/2de545zsBiEUtY97C7dy5A2yNaTwep/7wYXps7eer69YmzDNATk4OP/rxT/jhj37MmDFjnDwsWLiQ733v+3zbpRmtrp7IokWLmTCh2ll0L9DZ2clLL75EMBhk8+bNrFnz7ID7Hi4eRPsKBoPMnTuXd7/73SxZsgRd13n++ed59NFHqa2tpben1/lQFJouwzDQNI2enh5OnjxJSUkJ6enp9PVFyM8vwDRNmpqaWLZsGdOnT6erq5NRo0axcuVK205mGUuXLnU0fAsWLmTy5MlMnVrDihUriEajtLW1smLFCpYuWUp5WTk1NTWkpaWhKgo1NTXUTJlCXl4+N9xwA29729vIzMykurqaGTNmoCoaU6bUsHz5daSF0hk9upRJEyc7U5iKYmnWMjIyKCoswjAMJkyYwLXXXkvVuCoWLFhAIBCgt7eHZUuXs+L6G8jJzmXmzFnMmDETTfNRXl7B29/+DmomT2X58mupmTKVjvYuSopLWL58OcXFxcybN49rrrkG0zTJz89n2bKllJSMGqCFFHZXjx8/zvPPP88f//hHdu3axbRp07j//vu5++67WbRoEUVFRc67E1rAmG3vUiZBybhkiZ/pInCyzB7MyYoF8dutLXU7dxikmTW3k2WY7JA0vHJ8g/klm7dETjwrQy6/NY71Q/bTbc2mrN3Mzc1lwoQJzJ49m6lTp1JcXIyu6/T09KAPctKTIKQiDkFSh3qfHobHJbmbfsaMGRQXF7+hYV0qGKzRyfmVhYRcB28G5DRFZ3T/doc3TZPVqx9/y3bTK4pCQWEBq1ev5tV169i7dw9PPfkkW7du5dZbb+W6664nLy+fxx57lO7ubtrb23n0sUdZccMN9PT0sG3bNhQUdu3ayYYNG7jnnntpaGzg9KlTFBQUsmrVXzh79iyTp0xhyZKlrFr1Fzq7Omlra2PVqr9www03Mm36NJ5+6ikaGho4VFfLSy+9xNvfcTvV1dUAvPrqOjIyMpg3z1p39uSTq/n4Jz6JAjy6ahU33bSSF55/HuxB67FHH6W3t5dly5ZTZLdn0zT54f/8gGg0yksvvcjjjz1GR0cH7e3trFhxA/v27k2Y54yMDOrr61m58mYANmzYQGnpGLq6uggFQ8yePRufz8ejq1ax4oYb2L59O9u3bWP9a6+xYcN65s6dx6TJk9i8aRNvf8c7+NWvfkljYwM//NGPOXDgADu2b+fW224b9P1cbLj7lHwt8hSLxRxtbkFBgdPWLje4y5aVlcWECROYMGECkUiEuro6Dh8+zOkzp9A0lezsbAKBgENmfD6fszP/+uuv57bbbmPu3LlMnjyZU6fOkJWZxeLFi5k6dSozZ87kmmuuoaysjOzsbCZNmsSECRNIS0tD0zTGjBlDUVERgUCAoqIixo8fzzXXXMPUqVMJhgJkZmZSObaStPQMNE2jrKyc0tFjyM3NZ8qUKZSUlGCaJtnZ2YwdO5aysjKqqsaRm5sLKBQUFFJZWUlmZqZNKCw7jzt37mThwoXccccdTKmZTFFRMT7NR0nJaGqmTGX69OlMnDiZCRMmUFhYTGVlFbNnz2Hu3HnMmnUNo0aVoCgqGRmZTJ48mTlz5jBn7jxGjbIIZ1lZGaNGWbMtaWlpVFVVkZWVRcw21aPrOp2dnRw8eJCnn36a7du3k5GRwZIlS7jtttuorq4mKO1kTwRZnqbiBMRv2S8Rkg13sTFU+kPdu9BIVB/u+lWkDaPua0UaC30+n7MhTRBdEVZ+96dOneLMmTOEw2H8fr8zrV9QUDCgX8p58JAaLgkyKtDZ2cnGjRuZPn26I0guRYiyyZDL5v79ZjdOVfoilfMwXF6SJaPy16aZAhmVn0uE0tIxVE+cyNmms5w+c5qiwiL+6t3v4bbb3o6iKGRnZzNu/DheeP55Nm/ezKJFi3jPe+5h586dNDY2cubMaU6ePMn997+XufPmUVlZxf79+9m2bSs1NVMpGV3CvHnzqaysZNz4cTz/3HNs2rSJhYsW8e73vIdRo0rIL8hn544dnD5zhutXrOBd73qXk+eW5hYmVFc7p+Y0tzSzePESxo+fwJEj9UybPp2qcVVs37aNI0eOsHDhInJzc1h+7XWkpaWhKAqdnZ089uij3HrbbSxcuJAZM2ZQUV5ObW0tM2bOZP6CBQnzHPAH6O7qYt68+WBrbcvLylAUhfyCfCZMmICiKOzds4fFixczfsJ4srKzKR0zhltuuYV33H47ubl5lIwqoaysjFdffZXrV9xATU0NpaWl7N+3nyVLl+D3n5+t1fOBkBeD9a9oNDqAjIrdq5cbEvUBVbVIZ2VlJfn5+fT29lJXd5DDhw+Dva44LS3NGfBM0yQcDlNZWUlJSYlt9iaIgsbo0aMpKSlxzAgFg0EMezOpIFjY9S0GXMPeYChsa2qahh6Po6oagUDA0miqPoLBEOIMeSH3DXua1NqtnI7P50fXDVRVcdZwarbWTbGN3tfW1lJdXU11dTWaZm3QMk0Fn+YnMzOLYDCEqvrw+aw1iVY8QXw+6+hPKy4VVVXw+QKkp2cQCAQxTdA0i1TIdSU2r4h6q6+vZ926dWzYsIGWlhYWLFjA29/+dubMmUN2draj9UoEWQaejxsOyYa70HDn863Kx4WGIs0wiPIIjassbxT7yFwxdsXjcZqamjh79qwzwyT6anFxsfOM3CY8pI5LYje9YU8BCNNO9913H9OmTbtkX6pMzATcZXM3ykQD7MWCTCSThWmafOQjH2TevHnD7qZXLoJpp/PBT3/6vxxtPMqXv/IV961LDr29vfzLv/w/vmfvihf4h8/+PX/z8U8wfvz4Af5XC2TZIfcV0d4URaGnp2fAbvq0tLQL3pbeagiZ0d3dzabN61m9+gnC4V6qqqqYN28+s2bNIisrC8Mw6O3tQVUtbSMoBAIB4jETXR8od93Eyi2bBJlUbc2Q6O/Q399F31dVzdrtr/kIBK0PF8MwbI2jtTEobp9EI9KwXpGBz2dtzAmHwzQ0NFBUVGQP5v3vWs6rYQhZqqIolowSU6eCRCiKimH0r9mDgUdmYqevqgq6rtPS0sKrr77K9u3b8fv9VFZWOmtChW1ikQe5jjxcmehvI2/8+JWxceNG1q5dy7Fjx4hEIpSUlLBy5UoWLrQUN1ZbTByXh+SQOmvxcMljpJ3hcpa9pWNK3V6XJNLT0/nP//wvtzef/8K/XbVElATC/2pHZmYmy5Yu48Mf/jDXX7+Crq4eHn30UVavXk19fT3hcB8ZGVm2xt0aCONxi1AKbaeoU1ljIwinuJadGFRFGEsL6QMUe1OggiLWTarCjqO1w1+QRdMA3T7VSEEFUwGzX/EAJunp6UydOpWiokI7bRVLJ6Lg8/lRFNU6M94EBRUF69hOTAVN9eHT/CiKhmlY8Wqqz64DK9/iY8bSzAYIBPwOCV21ahWvvfYaWVlZ3Hnnndx///3Mnz+fNPtYz37S7Q2NVwPkD18Bxf4oEhtIkT6Ssdee9vX10dPT4xjTt/rfwM1RHlKD1+M8XPa46aaV3HDDjW7vSxbyqUgC1ho7D1c7xOBomibBYDrTp13De959H+9/3weYMnkau3bu5ZGHH+WFF17maOMJYlETvy+Iqlg73HVdaDWtQVUQS6G5EaRQJl2avalHDMIWkVPxa+BTDDRTx6+YBDQIaAoBn4JuRIjFw+h6lLgexTBjmGYMEx1r0sTARMdER1FNNA0U1bpGiaOoBiZxdMPa+CEGe7HRx8qfgWnGQTFAxKUYqBqoqomuR9HjVvqgo6ommg9U1UBRDeLxCG3tzWzbvpk///lPPPfcc3R3d7Ny5Uo++EFrFkhYkRD1Ib8HD1cvrJkH62hW7M2GmZmZpKenO6djiY8+1Z4t7urqIhqNOh93HlLDJUlGvRfpIRVUVlYyefJkt7cHD5c1xAoqVdWYNGky99xzL+9857vIyytgw/oNPP744+zZs4fOzm4URcPn618XKYimkKWJNH4yWRVEVew2VlUVDBPTMNBUBTDtwcLSgloaVAXNZ02ha5qKqikoiqWRBMMipKblrHWcVjyRSB/RaARVtTStVhn713P22ebarNQsbaoVn2n9mdaxqCiAwgDtrAIEggGi0Qi7du/ikUce5pFHHuHY8WPMnTuXe++9l9tuu42KigqnzB7x9OCGaq+JDoVCYM9oCVN/PT09hMNhFEVxlnbI0/QeRoZLgoyKLwn5ZV7OL/atzvvFTn+k8Y/0OQ9XB7z24YZFkgRZKiws5Lrrrp6QRd0AAONiSURBVOO+++5l+fLltLS08Je//IWHH/4z+/btRdd1gva53fKGIZlsGq61224zNYq0HvxIwxHq6uqI6zpdXV3s3bePI/X17Nmzh9bWVlRVo6enl7q6Os6ePUdDQwMvv/wS69a9wquvrmPLls2cO9dEff0hjh0/hmlaZpSeeuppVq1aRW1tHYZNBoU5t4B91ng/RJvobxumObBcllNRFJW+SISjR4/ywgsv8Kc//Yldu3ZRUVHB+9/3Pu6++27Gjx8/4NhGj4h6cEN8uKWnpzv9Brtt6rpOOBymt7fXMRFl2hr9RBt4PSSPS2I3vXCyaaeioqJLfnCS8+cum1zutwIjSXv16scpLR1+Nz2uXfLJ7qaXn/fgwQ0hL2SIfqTYth1bWlpQFIXCwsLLdjd9snDXhfBLT0+nqqqKoqIiZzPQsWPHnB3tGRmWGaa4fWCD4tIAyvGazlrO/vh9Ph+xWIzn1jzD0YYGJk2eTGtrK08//TR9kQgHDh7EwKSyspL6+npefvll8vPzqa2t5cUXXqCtvY2jx45y6FAdpaWj2bFzB2fOnKGgoIA1a9awY8cOTpw4walTJykZNZq8vHwMeze/mPoUeRH+4rfiIteqqjqn67S1tbJ580bWrFnDnj17KCws5Pbbb+fGG29kbGUVPp9/QD2INDx4SATF3mx3+vRpWltb6ey0TAH29fURDAapqKigoKCA7u5uZzO33H49pAav1jw48ASzBw+XNgSZCoVCzJ07lwceeIB3vetdZGRk8Pzzz/Ob3/zGOcVJfBwazu74xMRU7EwX2lLTtA5k6OjooKe3h76+PsLhMG1tbWRlZZGRmcnBgwdpaWmhrq6OcDhMUVERkUgfo0tLuP32t7No0QJ0I05XdyfnzjVx+vQptm3bRl1dHTfddBPvec976OjoZOeuXRiGaZuP6iecPvu4SeGPPRUqoErrYFtbW9mzZy9PP/MML7/0MgC33XYbH/rQh1i+bDn5edZGqURk3IMHN0Q77OnpoaGhgV27dnH8+HFUVaW4uJjRo0eTkZHBuXPn2LNnD7t37+bEiROORQoPI4NXcx48ePBwmUGQy6wsy8D9XXfdxfz58wmHwzzzzDM89dRTHDhwgHA4PGDKHvrNNNmrAMDeIdxvNsnSNoaCIZrPNfPaa6+xedMmenp6yMrMomTUKE6fOU1tbS1HjhwhPz+fnJwcYvZRuxMnTqS0tNQyNWWvPz1+/BibN28mOzub6dOnM3v2bMrLywmHw5impf0UZFEmy9ZufmtjlrXbvv/s9lgsxsGDB3n00Uf505/+yKG6OqbPmM59993LrbfcQnnZWKx1pro1t+/BQ5LQdZ22tjYaGhqora3l+PHjRCIR8vPzKS0tJSMjg6amJnbv3s2+ffs4deqUs3nJw8jgkVEPHjx4uAwhptgVRaGqqoo777yTBx98kOnTp1NXV8dDDz3E448/zvHjx61NRD4Fv19FFbvdFR3DFDvXB2548vv9ROJRjp86ya69ezh4+BA9fWFMTWF0aSnRaIyNGzdy6tQp+wACyzA+9klZuq4Ti8VRFBW/309zczPHjx8nFLLWtIZCQbKyMvH7rV38sv1Q1bZ1qusx4noE0FFUA1UzUTXQ9TinT59m/fr1PPbYY2zbto2CggJuv/127rrzrxg/bjKK4rc3O6lgqt5Q5yElqKpKWloa6enpAE777ejoIBwO09nZSUNDA0eOHEHXdTIzM53NTvIyEA/J45LooYprA9Pl/nXxVuf/Yqc/0vhH+pwHD5c7ZBmXbD8YKrwsK8U0fCAQYNKkSdx9993ceuutFBQUsGvXLh5++GE2b9lEa1szKAY+n4qJjq7HME09QRoK0ViUmK5TPXkSd737r7jltlvJLywgbujkFeSTn5dHbW0tAGPHjiU9PY3MzEz8/gC6bhCPW/FqmkYgEGLBggUsWbKYSCRCJNJHd3e3s/5XkGoxxWmaJoqqgGIRUhSDYNCPz6/S2trMyy+/xG9+8xvWrFmDqqrcddddvP/972fBgoVkZGTZdk2RSOglMcx5uIygaRoFBQWMHTuWsWPHous6jY2NHD9+nLNnz9LW1kZbWxu6rjN27FjGjx/vkFEPI8MF7aXyF0Gir4NEfiTwF9M08hqfNwrMfgzmnyoSxSP7Jbo/HOS8ywPIxXAibrneVNt0C67pr0TPWmGcnwkhx5EqRvqchysfidpGIj+G8L+SIfdRN+Q+DpCfn8+yZct43/vex0033UR3dzdPrl7Nqr+sYufOnfT09DjPuNe4WVPgEI9ZO4VzcrIZV1VFZWUlwWAQRVEoKSlh4sSJ9PT0UFpaSkVFBUePHuXYsWP4/dbxndjaVb/fj6JAYWERS5YsQVVVnnvuOZ588knqj9Q7x7qqqqVBxV6CYOiGY9pKUVR6e3vZv28/q1at4tHHHqWnp5cFCxZwzz338La3vY3i4mJH9pny+gMPI0KisUG+N9T15Q5T2khZUFBAZWUlqqrS1NREW1sb0WgUv99PMBgkNzfXWZYSi8UGbAa8WjFYuxkOSZPRoUiIm+CI324MlUlrWqZ/qiYYDOL3W+cQy3GKhe3CCWPNmqYN8E/WicX7YnpIvnb7id8iDz6fL6FzPy+7RH4X2gWDwQEbAgzDQLPrNBQK4ff7UWzBrev9R+mJTpjoHQn/we578HA+SCQ7Ev2/EtrgYHJ0KCT7jOjHmqZRXFzMddddx5133snUadM4deoUq1evZsOGDZw5c4Z4PI6mDrSPqCgKpmmdslRWVsbo0aMdmTd69GjH3mJpaSnFxcVMmzaNtLQ0Dhw4QHt7OxUVFYRCIfLy8igrKyMjI4Pi4mJysnMoLx/L9Okz2bfvANu27WDmjFnMnDELxZ6mj8fjjgwyTRPV/pg+efIkTz75JL/73e/Yvn07kyZN4v777+ed73wn1dXVTvhk68jD4BBtIR6PO8sthL+4JxMuU7LG4O6X7v4rh3mr+2+i9BP5ZWVlMXbsWCZOnEhJSQnRaJTW1lai0SglJSVMnjyZiooKkOoi2fIlG26kcNd7qn7DvatEvE9wCt0+uCJZmKaZmmkn0zalYRgGfX19DskRpp0E3JkfrFDiWhCm1tZWXn/9daZPn05VVRWapjkkVTR4megp0hSPZpNRYVpBDpfIia93ucLc+Uvkp9jE100A3S9Pfk7kM5WXMxKI9xMIBFBVlb6+PscEl9/emSrqJhqNEo1GnQHg6NFG1q59hYqKChYuXDwgXlEeuawykjXt5K4XDx4E3P0mUV+Kx+O2fUuVwsJCp615GBw+n4/S0lKmTp1CUVEBx4+fYNeuXdTX19Pb20tWVhaZGVmO/NZ1HUUBn09jVHERFRUVZGZmEggEKC8vp7i4GMMwOHLkCB0dHSxbtoyioiIyMjKoqalh4sSJBAIB0tPTKSsro6ioiLKyMsaUlpGdnUNFeQXl5RVMmzadZUuXU1BQ4JwaJWSkJWOguaWZ7du38uyzz7J//35GjRrFdddfx223vZ2qyirn/cvkyJMv5wfR38LhMNFodMBYi0Q2sGW7sLUp90V3P3b7ucOl6lKF+3kRx1B+SGNWIBAgMzMTVVU5deoUJ06cAGDy5MksWLCAkpIShwOJfpQofreTMRJuMBjvkON3/07FT4Y7bsG73HxAfFS677mfl58RfV8xxFzIMBCJ+3w+4vE47e3tjm2tjIwMAoHAG8ILlygDAoZhOKd+nDhxgu9973tMmDCBxYsXk5OTQ19fH+3t7fT29hKLxVAkMigqxbQ1AakOTiJtw/6aGQ6iLKLRpdKARP25IcowmJ/4nYyfaABpaWmYpukY5lVtbanfngaLx+MoikIoFCI3N5eurk5+/etf0tbWypIlS/nkJz8t5WZomKZJd3c3sViMzMxMgsEgSA1M1JOoY1XaNevBgxuiH8rtWiAcDlNXV4eiKEyaNIlgMOi1pWFgOvJRwcRa97Z161b2799Pa2srEyZUs2DeYirGVjhyQ3ywaj7rdCNBPnw+H+FwmK1bt/Lqq69SVlbGu971LrKyst7w3sRHaCQSQdNUFMUPZv8JUKqmgmkSjcZQVWtpgKqoqJpKd3cPBw8e4PXXN1J/pJ78/HzmzZvH7NmzrY8QzdsocrEgxsS+vj4U26ZtquPqlYhIJMKuXbt44YUXqKurIzs7m2XLlnHttddSXFzsDu5B4gBuwipDyCfDMC4NMirYdCwW47vf/S5NTU34/X4mTJjAqFGjaG5udgipIDXyF9tgcQ8FQd5SVScr9lIBIVSTRSppXAjIg7kg74ZhEItZZ0FnZmYyatQo8vLy+N3vfu0MOCtX3sKDD37QFdvgMFMgo/IHhAcPieAmNXK/9shoahB9zZKZYoOQQiwe5eTJk2zYsIF9+/ZjGgoTJkxg2rRpVFVVOaQU4qD0x+Pz+YhEIqxdu5aTJ06ydNkyqqurnb4uZLOQOYqiEI1GURUFny+ApvpAsQZ27HHBMEx8fmvZUzgcprGxkd27d7Nnzx4CQT9Tpkxmzpw5VFVV4feF7GNBAfqPPZXhtYeRQdSjOJFLvO9AIODMookxXiiFZM20mGFzv49EEOHEuHQx35nVxvrt7KYCMX6pqkp3dzf19fXs3LmTEydOkJ6ezvTp05k5cyb5+fnOUaHxeNyeXRi+HrDTEB9/op8lC5GG/IwpzcDKv0cKUQdC4yvXpeBA4v2r9qEVMjcTYYRcSARHdlxIMio3RlERwm8w8iYIoSBDsViMM2fO0NTU5Bhe7uzsdDSjSOY/5DhFPMlCvHghSJOF6ISpakbfDIgyyVPzYv2oqqrEYjH6+vqIx+NkZGRQUlLC6NGjWbXqYU6dOklhYSGf/OSnqaysckc9KMwUyKhoB5davXm4dJBIwAo/j4yeP6yqtOqzs6uT/fv2s337do4dO0Z2djZz5sxh7NixFBQUEAz5rPPj7fpXVRVd1+np7sU0VUcjGtfjIB3RaZomKODTLIP7uq7jU8GvqZgmxGJRTEBVFBRNJW7qdHd3c+jQIV599VXOnTtHeXk5y5evYPq0GY5MMTEH2EYVkAc5rz2cH9z1p+s6x44d48SJEyiKQiQSoauri2g0CracV6SPD/fzg0E8k+p4IHOJ4Z4T7SJVsixDEKt4PM7Zs2epr6/n3LlzBINBxo0bR1VVFenp6WiaRiwWIxaLEZdOPksGYnxMBYqi4Lc3/rmfNYcgpMnmSYbow2INsWpvNpT3pYglHWlpafj9fkaPHs3EiRPJyspy2shgaQuucNHJKEmwYl1aExqLxWhtbXXiF+saxX1BQkUliK8RcS9VDNegZYjyiU6UCuQ6cDcOdx5kP/E7GT/suMV6XjcZjcfjRCIR4vE4fr+fnJwcSkpKKCwsdJ5NFaZHRj1cQAzWR/DI6AWHqNeOjg52797Nli1baG5uJjMzk+nTpzNn7iwKCvKcNZ1ChqmqD1WxdskLRYJpmqiqhs9n9feobQBcyGrV1NEUiNuyXowXZ86eYe+B/Rw6dIienh4KCgqYOLGaqVOnUVw0xsnrUO9ZlINhwnkYHqL+xIdHR0cHW7ZsYf/+/YRCITRNo6enx5lh628Tg0/FuiE/l+wzAiKtZKFIm+NShUhLENJwOMzZs2fp6urC5/NRXFxMQUEB2GWK27O7qaSlSDO0ycLqa/17Q2QyKt6f6SKkAqnUtwgreJh8BHwoFHLIqNCm67qOZu9HmThxIrfddhujRo0aloyKvF5QMuoOLze6wSDiFeRFvFS5guUGIeI0bYEXDoeJRCIEg0HS09OdexcTouOlks5w9XChIepT1J2AqG9Rj5q98UvcSxVmCmR0JPXm4eqC6COijch9xiOjFw5uWaTrOg0NDezcuZPdu/fQ3HyWKTWTWLhwARUVFWRkZDgkwNBNFMWPpvVrqAx7E6n42BRTuaqYwdJjYOhgy8FIJMLRo0dZ99qrHKirJTMzk/nz57N06VIK8gtQVR+gYhimrc0dHHJZvPYwMog6jEQixGIx0tPTiUQinDp1ipdffpmDBw8yZswYSktL0ez9GZptoQW7bwrSkSzkcShZjGQcNW2FV6ppIaUnPp66urro6+tD0zSysrJIS0tzNIbYyrRUNaOkGFZAJuWi3ZuDkFBZnqaaliDLMXtmWizf0OwN5pbt4Ag9PT10d3dz8uRJKisreeCBBxgzZoyjTR0qXfNCk1H5ZYtKGa7wIpxomEjkMxkY9jpIobL2kDoE8R/qPQ0GMwUyqniaUQ/DQJYfbj+PjF4YDNXPI5EIhw/X89xzz1Jbu5+s7EymTKlh/vz5VFVVoShg6AqaZpmHE3HJ/d2QzMkp4uPTiKOaBn2RCCdPnuTAgQPs3buXvmiUKVOncc0111BVVWUZrUeMBZ48f7MhFEHBYJBwOMzx48dZs2YNtbW1zJgxgxkzZpCTk+No5UKhEKa9WTZVMipmRFN5ZiQQ408qEG1btOVgMIimac7MompvClZV1dEYapo2QAs7XLlkvjMS7iLLPvFb/p/o/nCkUIZ4Rq4LpGWSiqR11nWd9vZ2Tpw4wY4dOygsLOQDH/gA5eXlTn3J8iIRLigZdYc3bc3ccBBhB6sw+d5wBXozIL/kVPBW5Fs0FEHw3e/DtL8alRSnPwTMFMioeK8jrT8PVz5EH5H7u4BHRi88BqvvkydPsmv3dnbu3MGJEyeoqKhg+fLlVFVVkZ2dSzCQjq73b9aQnxcDuNCeARjxKJ3tbezevZvNmzfT3t5OSUkJ8xcuZNbsuWRlZdv5kEnDmy8vr3bI/a2vr4+TJ0/y9NNPc/jwYZYtW8aSJUsoLCzE7/c7Mh17nDFT1DyKMSIVyFwgFYzkGc1eKxq1jdwL7iMItNjAFYlEAAgGgxgpTrlzATiNXDbxW/4v33dzq2QgyLKIR7WXBshjvM/no7W1lbq6Ol588UUCgQDvf//7KS8vJxaLOXEMlfYFJaNyYxSVkCzBkStPjkN8PQn/wUiVCH+xIcolGuSlCDlfcocXjd7tzqfezBTIqHh/55Oehysbct93+3lk9MLAXWeiTwon+inEOXP2DBs3bGTTpk1omsbYsRVMmzqTKVOmkpmRiWFa6/bFM2JavV8GKbS0tHDo4D4O1R3k+PETZGdnM2vWLGbMmMGoktGg+d+QJw9vDeSxo6uryzlw4MiRI9x4441cd9115OXloSgKfX19TnsRWvBkIJ4RLhUIspfqc9hlk8dCd5tz39fsTUl9fX3Oh5XgI9hk1bSXC6qSSUVxPxkoI1gzipQ/eTyV/7v9xO9U3pOAKJNcLqER1exNS2lpafT09HDw4EGefPJJAB588EHGjh3r1I9wg+G8jd7L6wdwNeZE14NBbpziGVGp7sYrF0gOI+KRX8BgfjKSzePlAvnrTdRXojoTON/yRz2j9x4uEBK1D+EXj8ed88w9o/cXDu46V1BAsfprZkYm5eVljCkdg6qpHDxYy8GDB+np7cEf0MhIT0PzKaiagqKCahj4NBVNVejr7eHw4VpeeG4Nm7dsIRyJMblmKrfc9naumT2XzJw8cAjsGz+M3fnycPEh6ty0N8L29PRw+PBhOjo6mDx5MuPHj3c+AqPR6ID1koJUDefcxEYoLoZzSFP7Io/JOhFeQP7t9hP/FZsoirWSij0tLedfvi/IaaK4B4M7j8nCPZbKeXeXw/071X4l4hQEVGiLxaYl1V6yEI1GOXfuHPv27SMejzN79mzy8vLQ7Y8Hd57duKCaUXd4MwXNaCoQeRGN37RtoomNOFczTNOkp6cH0zRJS0t7w5eQaFSCrAq4CWuyMFPQjKreNL2HYSAPhvI1nmb0gsKUZqBEnxSyQXXW7BtYtpQsudAXCbNr5y42bdrI6TMnycjIpKamhpkzZzJmjLXzXdWtwfn48RPs2rmTvfv20dvTw/Rr5jB33gIqxlaQk21PyVsZGTBOiHyIfHl4cyHq3DAMent7aWlp4dlnn6W+vp6VK1eyZMkSQiHr0AGxWUeMwan0RSVFbapAqumMBKJvCK7T19c3YJo+bq8JFQq4SCSCoigEg0GnLyVTLlGO/v6WHEQaot4FxG/5v/xbSaCYGgriWaEVjkQiRG0btOLdm6ZJIBAgKyuL7u5uDhw4wBNPPIGqqnz84x9n/Pjxb51mVA7LeQgUd4MTFStIqPwiR9qwSeGrTHZDVehQcJfpQkMuv2av41BtNb74KnXXm/zsSOqPJDSjcgcdaRoerg6424d8res6ra2tAJ5m9Dwh+qW7vnHJAqvvWv5+n2U/sLyinOycbFqaW9i2bRstLS3WYK1p9HT3sn3bdl544QWONDSQl5fHtddey4oVNzC2spLQEB8QIt3B8uXh4kPI6kgkQjgcJhaLcfjwYVpaWqioqGD06NFOGEHK5LaSinOPq8m4VCHSkXnDcE6EE2OnYZtJlJVdqm3gXVEUh5TJvMAdZyInQ6STinPHJzv5vvw7lboX+RIkUnx4qJKdUc22xuP3+4nFYrS1tXH06FECgYCjGY1Ly3iUIfr1BSWjorAy3NfJQK4I8d90NShRODfpShbJvpBEbrhKTQTx7MWEKX3RiY5i2vUmT29otpksdzlSLZPAUGRUxOm+9uDBjcHahvCPxWLeNP0FhJAPbj9R39Z/obG0nKZqZGfnMK6qisqqSiKRCLW1tezes5vGhgb27d7Dtm3b0DSNm1auZOXNNzNt2jTSMsUGpcQyUKQ72H0Pbw7Euxd2Jfv6+qitraWpqYmysjJKSkqcsV4mGak4oTgayZgo2kkqDlvplApEubDbrNCMyvcE79DtZQru8TRZiDE6VSeXbyiIMCK8KFcykNOIxWIYkv3yoH3EuM+elY7H43R0dHDixAmCwSAzZswgNzcXQ5oVHSq/SedKbjjuypMblEw6FGlxrrsiEzmZMMlxyI1YEK1EZMrd6IdyIl45zmTdUBU6GORyXEznzpsi2RINBAJvMIEl7st+qUC0C9EmBMT7FP5iesO9fuRqdyOBO45kHEMQgbcSsryQIedZOCEf3HLCw8jgbg9vbDPinSgoioqiqJiAaeqASenoMu6+625uvvlmTMNk167dvL71dYKBAO985zu5fsUKiktKUVQV0xx85/Sl3D6vNoixOD09nfT0dAz7dB2hBRVjjCqRylQh93n3+DWcSzU9kZYY44Qixj2my87v9zuE27SVT7quO2skZXmk6zo+SSEn8ufuS0M5OV+pOFEfom6Ev7ss8tivSXt7knWGvS5WkG5Rr4aL++m2LVJhd1SspRV5U6TlBXF7X4t43jTN5MmogHgRcmbEwGC6NKNyRaXi3JUxWDxyWiOFO51k3OUAuZEgEXWRf/EOZQhBJL/jwZx456pk3UA0dOHvrjclxa+yCwV3OS8luOsnGXc+cL/Ht9qJPLkhh3ELvfOtAw/nD8PUMdHJzMympqaG8ePHW2d0B0MUFhVZNkk1P8SjJDzD08MlCdHnFHsNpCkdQqNIy+EU17Sru18n49xyLRk3Eoi8inFqqLFJ3FOlmVZFWpYgj4/it5scpppPOX/JusHK4C6LcPIzqcIcZH2qm0wattIpZh+L6tYYi7RFWMEhBEbEDOQGJRNSOQFxnxQGDzmcnEYyTrDyi+nE7sFkCZvs5PpJ1p1PmeRGkcgJTaXbT3y1DOVEWEOytyY6iYAqrakRv/1+y1C2eF/u8g7lTBdhcdev7AQM+4suWSfvDnWnP5h7q7R07jIP5uSwoh4vReeuU9EW5bqVBa3c1jycL8zBCaO4JTmrWWkoqLanQjAYIj09jWBaGnFdpzfcZ93TfKB47+pyghiHRd9zEwkB+fflhKFkj+zcGIzHyHGJukrFJYpnOCfCu/M8mBOyVDybCpQESqTB6kKUSSa+idJ0lx1S2E2PHalqnzjQ0tJCb28vqnRGqlg7qCgK0WgUbEOwmq3yThYjqbREhbsYkBtCKhADaLLPKdJ6TzPBWty3EqJDBAIBgsEgvb29RCIRMjMznRM5ROMXZdalI8FEO0kFI3m/oiMmW38inMhnsu8KacehgIhLxCF+pxqvDEUyKJ5sHCJNd/4uNcjtQbQvXJr3cDhMfX09qqoyefJk8vLyHCGZbH146K8rq+4Me9pdlXQTis0xE9epaYr+aF0fOVLP008/xbHjjZw9e46yMeW8/8EPUD2h2g7rvZ/LBaIfappGX18fx44d4/HHH6e+vp6bbrqJpUuXkpaWht82ei/k6qX+fmW5K+dVljXytRhvkhk33iqkMradL0zblJdpj/tC0STagN/vp62tjdraWp5//nlUVeW9730vEydORLfPrBfxCC2rKmmiTTOF40DlAgt7Ut3d3ZiS+R6x+86w15kwQjI6EgjN3PkM9sNBxC20gqlAaAZJseOmms5IkWqDNu1F3YFAYAAZTUtLA+nkJ5/P59SZTEb1FA0XpxJWwJSWEySLkQogQZiShSzwUoHcmZOBSCcUChGwD6a4FCH6lOqaHlOljQJ9fX0OGZ00aRJFRUWOSblLtVyXKga2Ox1QME3hlxoZra8/zOOPP0bT2dO0tbYxatRoHnzwA4wfP8Ejo5cZkiGj6enp+Hy+y4aMym3ddGkW3U74I8n0VMqWqjwfCQQPSUUpITDS/Jm2OSfTHvdlrqUkIKOapvHe976X6urqC09GxcvS7FMJWltbnZMJxJdS3DZxgNSoUxmgBc6nwkTBZFxIv5HmzRLeqT0r6txdLrkRjNRPhshbsvkTz6u21qqnp4doNOrYGTWl6QPxISJrRsW9ZNMTSDW8yIe7vEMh1boQSCUNATmt4d6P+z0mC/Gc6PiXIkzpA89NRsVHphgc6+vrURSFCRMmkJmZmXJ9eOiH1cZNDDNuT7kr/c7ENnxvkc8BMAGJjB46VMfq1Y/T1t5Ga2srJaNG8773vZ+xYystMgqYgy0D8HBJIRkyerlpRmVZbkqkU4wN4r/wF//FR3AqZRvJ2JEqFGljuJDvw0GEG0n+xLgjNKPyRigRr9/vp729nbq6Okczev/9918czah4aT7b8GtbWxuxWIxQKERmZqajofBw9UEYw83IyLhkCY+HSxtiQBCCSQwA4gscW3taX18PwIQJE5wPHQ/DQwj/eDxOY2MjDQ0NlvIAg0DAx9SaaYwaNdomo+IUJiwa6R7wbDKK/a+xsYEnn1zNuXNNnGs+x+iSMTzwwPuorKySiKz3ni4HXIlkFImQCtkinFCMyDJHlEuQ0VQwErKXKmQymqpSR5C/VOAmo/KSLyEb/H4/HR0d1NXV8cILLzhkNBXNaNI1rdhaCqSGJyIWU7LyBh/hL399DOdEuLh93JR7g0kiF5WOpXqzIJd1OPdW5O/Nhihr3Db/gd2hRZlNW/N1JddBsm3c3d7fLIj3cak6UR/CiToS7UYIQ2EyRL+C29LFgBiAYrEYr776Kn/4wx/YtHET69au4w9/eIh9+/YBoKoKqmod7SnGLPFOBkC6FINKLB6XpvClocX0uOiVhFTJzFsNd34FYdy7dw//9I9/x2c+/Qn+9lN/w3/+x79RV1f7BkIpy6WL4S4HDFcnFwJJk1FcL1VkTggi2Yl7Q7nhwg13Xw6nuk4ZutjOlAzfD+dE/pA21CTr3Oleai5RPgWEf6Iw7nIm49xpX0znTjsZd6E65HAYaTtnCHNbw7lEz10MP9mJqXlxrbgEoYeRIRqN0tvby+TJk3nvA+/l7rvvpqiwAF3XUVUFXTdobmnj5InTdHR0YDLIIR/SpWFbrYjHrY8E07Sm9wfAfe3hssXl3v9E/l9/fTNtbW3MnHkNixYvJRqN8ZMf/w/hcO8bwiYDN0FLxY0EbhmajBspEj2fKP/nk1bSZFSOXPwWQkr8F+pb4SdPsSWqlMH85HViwzmfZIjePQBfLKfamyrc+XDnzZ0/N4EZzpm2hsid/sVw7rSTde6O5G6cia7dcSTjRvqcu5zDOffzybqRwi2UhnJyeHf6wznsvuUmfcm4RM9daD/3PU2yXStkg7gvrj2kDtPeiDBq1CjGj5/A2PIyCnOyUVWVSNxk09bt/OrXv+HHP/kRDz30EI0NjcPWubhnGFbcclhF8YjolYah2sJlBdOkrKycD3/kozzwwPv5f//vc3R3d7N//z40yei97CKRCIZrFieRfB7OxeNxIpHIgH02qUD0SVkmJutSxVDPyOUWGCr8UEiajLorPNF/8ZJkxIexd5nIpTK4i3ypNkF8M5ySYCOJ+1pA5E9JkWTLzp3+xXAjTUezT3cKBoP47LoRZfXbpz2J32Lh8/k6kW4yzp3f4Zz7+WSdm1Ql49xCYjiHtGksVSeev9QwXL+RZYHwG+wZD8ND1F8gEEBRFEvmRqOYuklLayt79uwhPSOdmpoaTp8+zbZt2+jr63NHMwA+Z6OHgWbL4QEy3HtdVxQut/43uNywFFhCvh492ghAYWER7e1tfOHz/2/As6Zp8seHfs/qJx6jq6uL59Y8y0N/+B3PPPMUnR0dTpimpib+7ze/4n//90fs27d3wPOtrS188pMf4yMffpCPffRD/M3HPkxra4srX0PDXQ73ODGUGynccbjrxY2RpJU0GXVDZEJoXsRvOWOpkEo3Ui2MMoS25UI7OW/ul+12yYYbzLnTvphupJDLmQzcZUzWiXxe7Hpxp5uMk9t/ss6tvUzWjaT8SB+Ll6oTMAfZWCCH8ZAaRN2Jo/oyMzNRFKsvmqaJblibDK65ZjZvv+3tLF68mJycHM6dO0c4HHZH9waCaRgGgUCA9PR05+hBoH8Dk/fqLhtcDf1MUawNeidOHOeTn/gon/zER/ne975Nbm4uU6bUcPbsWc6cOUNHR8eA5xobG+jo7GDNs0/zpz/9ge3bt/LE44/y1a/+F4ah09HRwVe/8h9s27aV06dP8Z1vf4OdO3c48qz+8GF6e3q4666/YsWKG4nH43S0W2koSY6jIpwYB9xj0XBuJJCfc8trN0aaTtIMZLgE3IOKIe3KE1qxZJ0YPN2VOJRz5+FiOjlvcvmbmpqoq6sdILzd4VKFO+2L4TjPDS4xe6OWLq0ZFf6iE8pab5Fmqvj/7F11fFxV9v++Nx7XNlp3d4G2VLACi1P4YevLGm5LoVDcFxYWXRYWdy9SL6VOvU3TpGlcJ55JMv7e74955/Xm9k0yM03SJJ3v53OSN/ddPffcc8+7yue7qygUEP88GjdW+SPiUTDkYc645fPdHhF495NNfJ7Y3zyoLZECDiNwEL9oWjAyMhJQeE0zGlFRUQCAtWvX4qOPPsL+/fvhZqbdVT0LAALUdaG+di/DbDZD1Om0px7D1dVrEGjbCtRfTwCrY/h8Z2QOwJix45CalobGxkaUl5XhyJFcyLKM5597BmvWrMKR3BwAQFpaOmRJRn1DPRISEvDkU//En/70F1itVbBardiyZRM8Hg+W3f8g7r33AYwYOQpff/WFmra12gqTyYRzzj0PCxYu8uUtxC810oeB0InoTArHhg81rvYQsDHKdhBsAYnYgvP+uwNdlRZfqWz5JOVw/7Vr1+L222/D3Xffhcceewx//etf8OKLL6C0tDRkPoQaLhTw9RoMUXg+r7w/Pkyw4OPvSoSSFls+flTSH2n51Zry590QYh5DhVaddYWbzBz7Qbzh/ZJbd5a/L8HpdEIURdXw1Ov1MBpN0Ov0KCwsxLZtWyHqREyfMR2jRo2CQTnChyAIPmuUrRVBucfcZDJBVDaTejy+D1NBQNgQ7UVg25vMbNRlBxF0yqk6NPjA6r5giNVprDsL6lv4WZJgQWFZggykpqVh6dJl+Pvfb8Zjjz2FqKgorF23GqKSD4PRiC+/+BxPPvkY9u7doy5ZEQURDQ2NeOvN/+Czzz5BREQEEhOTUFVViVGjRqu3w40bOx7l5WVq2Wpra5GZOQCCILT5IKSBHZbPPD+IDzSQwZeH3hOxA0YURouPfL3w6bFhZOa8Ur7uCBQmWARsjILrALUyRB0l759nWFdQd0JWKmn37l24996lePfdd2Cz2TBz5kxcdNFFGDJkCHbt2oVly+7D//73Fmw2WxshCxTB+j8RsHUZKLECTL8JvF+dsn5TZIypYKi7waffEQnMmmC+7P6I1qkaDIbj1q76oxNZ/8nWVzCkFbaz3cidlCzLRyj1ITAyGkZwEJQNnkePHkVTUxO8Xi+ammyoramB3d6CltYWFBYUoqGxERMmTMSkiZNgsViOa3v0k3X1er3Q633rwWn0XhQZGe3+5htGiGDbItsOZWb9NmuMykGcLMMSqwfpN6XLpk/psumfKCheQIbR4LuVjvRLVFQ0PB4PLBERAIC77roHDz/yGADgzf++jv379wIABFGALEsoKiqCw+GAJEk+Q1UGzGaLWh69Qe/zr5S7utqK/ikpEAQBHuYoRDIaj+XtGFh+sEYmyxeeeEOUnY3j+cjXDYHlPxH5Z+uNrTvWf7Docq3OM7anQasSCFQZLEmShNLSUjz77DP497//jZqaGsycOQvLlz+IX//6NzjnnHNxxx134i9/+SuSkpLw008/4R//+AfWrl2rCtupALacp0qZgwXxpSNeabn1dXTEkzACB+m2/Px8rFq1Cvn5+fjhhx/wyiuv4KNPPkVeYQlycnJh0IkQZQnfffs1vvrqS5SUlKjGJdh64FQlTfPT5RcOh0MdGVWrLlyFYTCg/lTrd3e1d0EUUVpagk8++RCrV6/Ee+++jYqKcgwZMgy2piYAwEcfvY8fvv8OADB+wkSkpKRCEH32QkZGJh597Ek88MBDcDgc2LdvDyIiItQpfkEQUJCfjwEDBkIQBLS0tOBo3hG0NLfA6XRi7549AACbzZcW/Og9LX7wdgv/n39uD1ppdgTeH/87FHS5MdqbwFYeMZf9KrDZbHj//ffxwAP349ChQxg8eDDuuutu/OY3v0F8fLzaoGRZxsSJE7F8+YO46KKL4Ha78f7772H58geQnZ2tftG0B38Gcm9GR2UOI4wwug7V1dVwuVyYOXMmhg0bhuTkJAwYOAijx06Aw+lCv6QELJw/D8lJiUhMTMSFF16IGTNmwGj0jR4RSCuRk9frRXNzM1wul2p1ShIzTc8GCqPXoSO93dF7f5A1pt/Z/1rxarl1BH9hBg0aDK/Xi+9WfIv33n0bP/20AWeddQ7mzJmLMWPHAQA2rF+HDRvWYdas2Viy5P8wevQYpKamwaA3oLraihUrvsH7778LAOjfPwWTJ09BTU01nn3mSbz+2svYvn0r5i9YCEEQsGXzz3A4HNi7dzf+9tc/4YMPfOF27dx5nDGpxQ8Ca4gKzCilP2JHLzvbpvDH21DSCfg6UCgJi8qVco2NjfB4PDCZTIiMjGyztkgUxTbTbUIPXuPFM41vGLKynuPnnzfiq6++QnNzM2JjY3HxxZdg1qxZqj/2P8VJlV9XV4tPPvkEe/f6hvhnzJiBJUuuRGJi4nHp8+ipfCPIsozm5ma43W71bnowO7d1ynltknLveE+WhTBOHgRlXZpvirft+aKyMsrgcDhQUFAAQRAwZMiQ44ykMI4H8U4QBOzatQt79uzBBRdcgMTEREiSBJ1Oh6ysLPz4448499xzMXHiRLS0tKibSSXl9IY2eko+ZmUKAlBQkI/PPvsUtuYm2JqakJKShiuvvAqDBg1W8kCBwugNkJV+vrW1FVVVVfjyyy+RnZ2Ns88+G2eccQZiY2MhK2duGo1GiMo0/om2RTY836fS83GyGCD85c1ma4IgiNCJIswWS5u4m5qa4HQ6YLFEwGQyqWXU6XQ4ePAAvvziM3glL8wmMyZPmYqzzjoHoihi69YtWLNmJQBg5szZOPfc8wAAb731BooKCzF/wUIYDEbodCLWrVsLyevF0nvvBzhDkwXLD+IDOz3OvuOf2fcENqzILXsiO05m+m1RFOFWbr5jN5nTe6PR2OZuep1OF/R1oLoHHnhgeZucdABB6TTo8FffAnijanSQH/a5J8Nf/qgicnJy8PLLL2HTpk2QJAlnnXUW/vjHP2HgwIHHVbi/yjebLZg2bTqGDh2CgoIC5Obm4qeffoIkyRgyZMhxQtXb4HK5IClHu+j1vjUyVHYS2t4iD2GcHJDOIOOHbRMkO16vFw0NDRAEAfHx8aqCC0Mb1KmxfLRYLBg0aJB6LrAoiqo+z8zMREJCgqrP+XpoA8YYbWlpRn7+UbjdLkheL+Li4jFu3HjExMT6DFEZ4ZHRXgZBOYO2paUF2dnZqKmpwdChQzFo0CCYzWZAaY/sYJOsGEm8HdCRG4v2+lOSQ015bAd8PCxMJpN6FBkfr9FohMUSAb1er+aZ2kNKSgoWLFiEBQsWYe68MzB06DBA6e8GDhyE+fMXYv78hRg+fITaBrOzD2HatOmYN28+BgwYiMzMAYiJjkZtbQ2mT58JMG2W4I9P5I83JHke8XGxz/xv+OE/+eUHGMkP5cPpdKK2thb5+fkQRRETJkxAYmIiZMXw9BcvxdXl0/R8oXsDZFlGdXU1Xn31VTzzzNMoLS3FhAkTsGzZ/bjooovVEQOZmZbnK5GI/EmShFGjRuO++5bhoosuhizL+PLLL3DvvUuxZ89u1V9fRm+TgzB6BnqjDukJ4PVTamoqJk+eDIPB0MY9MTERixYtQmZm5nFhiI4D46TX6xEREQGdToTL5YLdbj8+jEYUYfQOBNL2qL7Zeu/IrSPyB95fR9QZICOU1UUUt9zODnOWLr3kcsyadVobtylTp+FPN/wV8MNnrfyz4f29Z/93BNafv2et3yzaexcoutwY7UyB6CqwgutwOPD1119h2bL7sGvXTqSmpuLGG2/Cn//8FyQlJWkaoXz5+HdsGJ1Oh3POOQfLlz+IKVOmoLq6Gi+88AKee+6fqKgo79NGaV8tVxhdC602FkbwEJXpNH40xWQyITo6GkajsY17u2D6Ho/Hoy7VkeG76tCrHvtzvP8wehe6qu3x/SRP/sD764hCBYUnw4+frdF6T++0YImI0JzNoQ2ArIHpj8gPOGOYSMu9I7B+/D1r/WbR3rtA0eXGaE8HO3K5bds23HvvUnzzzTcwGAxYsmQJ7r33PowaNeq4ym6P+fxXAissRLGxsfj97/+Am266GSkpKThw4ADuv/9+fPLJJ7Db7X3aKA0jjDC6F+3pLFavhQK3261e9BFhiUBkZCSzXIfzHEafRTDy43Q6kZt7GNXVVkjc0UEErfi03NpDe3LfEdhwvDHa3nu+r++IQgUfj8zNxPLuPH97GrrcGGUt+Z4EEhpJklBYWIgnnngCr732KhoaGjBv3hl4+OFHsGDBwjbrI/yVg/2qYckfWCEZOXIkli69F5dccgl0Oh1+/PEHLF16D7Zs2dzjhSdYtMeTMMLwh47aUxgdg/jnr/Pz5x4IDAYDzGYzdDo9dHrfjXs+/Ro2RvsCgml7vHGkRbt37cQ/7r4dz/3zady/7B4898+nYLPZ1Pd8fDz4+NqjEwHb7/NEYNNh21igRH08Hy8fDxs/65c3OilOnshdVkZXWbC//T1r/WbR3rtA0eXGKMvMngabzYZ33nkbDz/8EI4cycWIESOwdOm9uPrqqxERERFQ3lkB1VovwvtlISs7ywRBwKJFZ+KBB5Zj2rRpaGhowBtvvIHHH38MRUVFbcL0ZnTEyzDC0EIg7TCMbgZTHTqdDhEREdDrdHA6nbDb7co1olApjN6LQNoe20b5Z9atqqoS//nPKxg5ciRuuOFv+NWFF6O0tATvvfe/48Ly4PvPrgabD7aP5/PB9/ftlYEF+dPy649/4IxefwZne888WDd/z1q/WbT3LlB0+W56rco72ZAkL9asWYOXXvo38vLykJCQgGuvvRaXXnoZYmJieO9toFU2ElL2N4H1y64XIcFgBcRkMmHKlCkYMWIEioqKUFxcjJ9++gmNjY0YOnRYcGu6uhGB7qbvibIQRs8AtStJYzc9vfd4POHd9D0FSt0IAtDcbENubg4cTjtaW1phMpkxceJExMbGha8D7aUQmN30hw8f7nA3vRTgLF55eTlKSorx9xtvRb/+/TF48FBEWCKwfv1ajBo9BpIkYc3qVTicnYUjR3LR1NSI9PQMAMAvv2zH+nVrUFNTjQEDBh639jk39zASE5MAZR1zVVUloqOjUVZWCrPZDL1eD0mSUFRUiLi4eLjdbmze/DM2b9qI+oZ69ZpOANi2dQt27NiGw9lZKCwsQEZGJkwmE37ZsR3r1q5GTU01MjN9eWD7f5vNhuLiIiQkJAAAKirK4fF4YDabkZ+fh9WrfkRFRbma/6LCAkQoR2MKgoCSkmLExMRAlmXU1dVi9eqVOJx9CKlpaTCbLSgrLcFPG9cj6+B+ZB8+hOKiQsTGxaGlpUU9HUOWZfzyy3bfAf2CgIKCfKxdsxIFhflIU+IRBAEulwvr16/Bzp2/ICoqGnFx8aoeJsjMOlUyaLV20+v1ejgcjhPaTd/lxigldDLBFjorKwsvvPAvbNmyBYIgYPHi8/Db3/4O6enpbSqBB884cmOFkX/Pgu1cyQAlIjdCUlIS5syZi8jISOTnH0VeXh42bvwJZrPvWBa+EZ5sBGqMoofIQxg9D6QzeqsxyuqH9vRAV4PPQ5flhTFGGxsbcPDgAbS2tsLucCA6KhoTJkxSP+zbUat9Ev543yX10EUQOskYLSjIR2VlBYqLC7Fp00bMmzcfc+fNh6icRd7QUI/amhocPHgAcXHxcDgd+Oqrz5GXdwR5ebmoranBtGkzsHrVj/j4o/fhdruwb99eFBUWYuq06Wo6jY2NeOzRBzFmzDjExcVh48YNePedtzBn7hl44P6lSEpORmbmAPzr+Wfx9ddfYMGCM/HxR+9j1cof0NLSgh3btyI2Ng6DBg1Gbs5hvPrqv1GQfxQFBfnIzc1BbFw8sg9l4cMP34Xb7cb+fXtRVFSI6dNnQmCugt6zexe++PwTzJ17BmRZxptvvg6vV4LL5cSLLzyH5uZm7Nu3B0eP5mH69Jl48YXn4PV6MXz4CJSXleLRRx/EhImTAAh4+qlHUV5WiqKiQmzbuhmzZp+GiooKrF71Iw4dOoj8/KNoaW3FwIGD8MH778But2Po0GGoq6vDS/9+HqNGj0F1dTVeefkFNDY2oLS0FDt2bMOMGbNgNBrx0r//hZ07d6Curhbr16/FsGHD4fa48eUXn2HI0KH45JMPMXToMJhMZrW+/BmjOmVW5ESM0Z5l1XQRJElCRUUFnn/+OTzzzNMoLy/HjBkz8PDDj2Dx4sWqAYUADEX2WWAWK0saazRYv1pheWL9CYKARYsW4ZFHHsWsWbPQ0tKCd999Bw88cD+ys7OPiztUaOUzjDBOFrQ6bL49ngy0l76sLLdh74CmKzT5tt1XQTqQ/e37jz57rJM/ufR6verVqHSqALnzfnsa+PxRX8bKMdUzO9CgRfV1dXjxhX+ivLwUK779Sr2kguiHH1bggfuX4qOP3geUA+hnzpyNJ558FlCu37xn6f0wmc1YvXolFi48E8vufxi/+/0NOHBgHw4f9vWDMiN7tqYmyLIMW1MTWlpa0NLSDEmS0KyMWObkZAMAqqut2LZtC/7wxz/joYcfxxnzF0JW7nRvbGwEANy37EE89vjTiI2Ng8ftxsqVP2DhwjNx/wO+PBw8sB+Hsw9BUsJ5PB54JS883mN3zrtdLkiSF1999QWGDh2G+5Y9iD/96a/IzTmM7ENZkGUJNlsTJElCg5JuVVUl1qxeCa9Xwj/uWYZl9z8Eh8OJNatXYtz4CXj4kScwZuw4DBgwEHfeeQ+GDx8Bl8uppCWhptoKAGior8f6dWuQnp6Bu+6+D7fceidaWlqwft0aHNi/D7m5h/Hnv9yIhx95EgMGDsKXX36GuLh47Nu3B3t278KB/XvVvSsku2TzgNFtsnzsBA3WjfwFii43RjtDGfNCTmANOS0CgNbWVnzyySdYtuw+7N27F5mZmbj11ttw3XXXq+tCtdIgosbIGpmUNuuHKoxIyy/5IzdRmbpnieWV1+uFyWTCNddci1tuuRVpaekoKSnBk08+gVdffRV1dXXHlZnCs2n7I76MXQ22bGGEwYOVD5JHti2SH1bOuwvUdvk2BCWPHo8HLpdLJY/Ho7b1vgqqAlEUlWlGn85qbW2F2+065qd7q6rbwOtOkgmPx6MYQi3qRwkUfU7GaXfLbzCg8ojKhQgk92R8UhloZoL88LThp3Ww2+1Y+eP3qKysxKKFZ6nvZFnGrFmn47LLlmDGzNkAAJPJDJ1Oh+ho34h6XGwcBEFAU1MjHA47Tjt9LgBg5MhRMBqNKCkpUnVDVFQkdDodcnKy4XDYUVFZDhYRERFYt3a1+rumuhpRUVEYN24CPB4PLrtsCWafNsf3IakYk4mJSYiLi0dkZCScTiccDjtmzjoNXq8XI0aMhNFoRHFxkfrx4XA4IMsyamtq8O67/8MH77+DkpJiuJwulJWWwGqtwjtvv4nvv18BKFP4sbHxKCzIR0NDA4qLCwGFn0eO5MDtduHjjz7AB++/A5fLibKyMni9XrjdbhgNRhiNxjZytHnzRnz91RdYq5TT4/GgutqKiZOmAADMZjMGDhqEkpJi5OQeBgD88MMK/PeN11BZUY7y8jKIooj58xdhzZpVOOec87Bu3Wqfoet2AxoyAUUeSOediFx3uTHKdiSdhUDikyQJmzdvwtKl9+DHH3+AxWLB1VdfgzvvvAuDBw9u0yg6A3yn2RkgZSdJEoYMGYJ//OMfuOKKK2CxWLBjx3YsXXoPvv322zYKj8JRPjrKT6D+OgPdkUYYfQ+d3a5CAekKPh/USet0vl3kBoNBvdHF7XYrhplPkXcHWD3E0omCDC1ZBiBLECQ3IHkBSDDoBFiMBhhEHSLNZkRZzBChGOKyBEH2oDcOj/I85Al+Po7IOGdvsmL9Utw9Eby8sOX05+avLM02G6BsFBZFERGRkTiwfx82b/4ZANCvXz+cdfa5uOKKKwEAaenpalhLRIT6TNGbTGbI6hpFA7yeY6POOp0ep8+Zhw0b1uHOO27B/n2+q7dJ7D788D3s2bMbI0eOApSlZW63r9+UuUEnKg8Z306nE4LoKytdCyqKoi8PzGg3y4fD2YeQrYya0juHw4n6hnrodCLGj5+AceMnYMHCRSgoyMfSe+7A1199ASh8dTqd8CrLGFpaWzBi5CjMPm2Oag/40j82owsln/v27UFJCbvpWVav6AYAk9EEr9cDp8MBAGhqbERDQz3S0tJx1lnnQpIkRERGoqamGpFRUWi22ZBz+LBaDmjUN883LT+BoMuNUb6hdgbYRsAXWpZl5OXl4eGHH8Ibb7yB5uZmnHnmmXjwwYcwZ84ciNymo87OW2eCVXSU3wULFuLBBx/CrFmz4XK58Pnnn2Hp0nuwd+8ePvhxvGkP3cGH7kgjjL6HrtAhgYLSbU/nCMoCfjJG9Xo9dDodPB4P7Hb7cR+LvRoCIAgyrFUVyDqwD/m5OSgtLoLb5YJBp0dyQiLiYmJQUVaGnKz9yDl0AHU11YpF4X9tYW8Eq5dZ0I1UFotFNRhIRnrSOmd/6KitsW2BfmvR8BEjAQATJ06GJEkoLy9DfX0dPvrwPeTk+EbmZFnGju3bYDAYMXHiJDUN9tlsNkMQBOQfPQIAaGhoQGtrC1JT01Q/AHDZZUvw+z/cgCVXXo0hyvWcZERKkoT58xdg3hkLAAAmswlOpwOVlRUAgAMH9uHDD98DALicLvVyCFmW4XI5IXl9I4FHj+ZBEAQ1D2lp6dDpdBBpAzOA6JgYPP7EM3jk0SfRv3+KqhumTJmKm2++HTfdfDsGDhqM6OgYTJo0BbfceieWLPk/zJx1mi/PEBAXH4/ExCTcettduPnm2zFr1mmIjo5uI3N6vUEpuS/U6NFj8MDyR3Dd9b8lJ5jNFhQVFaq2TkVFOVJT0xAXHw8A+Mtfb8LNt9yBSy69AnHxvg1MRYUFGDBwELZv24LExET1SlM1JU4+KE+8W7DocmNUS3kHAgonM+tV2EKz7yVlirympgb/+c/rePTRR1BQUIBx48bh/vsfwGWXXQ6z2fdVBT/M66nQKnt0dDR+/etf44477kRGRgasViuef/55PPvsMygrK1W/1trjO8sL9ndXoqM0yspKsW/fXhzKykL+0aNobm7mvYRxiqIj2ekqULp6vR565aYUmVkj6na72xBN0zudToiiCIvFAoOB7TR6NwQAEERYrdXYtGkTfv75Z2RnH4ZOp0NUVBRMZjNkAIcPH8aqVauwcePPaGxsVGbq2y5V6ungdS8RO4hBssCWSatvYfur3g6tMmiVbcaMWRg/fiJSUlIxbvwErF79I2bMnIWo6Gi8+sqLWLduDT784F188cWnuPSyKxAZGaWG1Yk6CIqRb7FYMHzESHz00fv45usv8MZ/XkFMTAxGjR5zXL1MmjQFc+eegalTfZubdKLP+NfpdL5pfiWLI0eOQlpaOv77xmv4/vtv8cH778BoMKC52Ya1a1chIcG38Ybq1Wg0YtiwEfjs048080DGKJSLH0gGIiMjIepEzJgxC7t2/YLt27bg7bffxIpvv0ZTk2+N6NChw3D6nHlYsGCRmtfTT5uD6morvvvuG6xa+QPefectlJWVtikr6SNKKzbOZ2CSkarT6TB27Hjs2rkDX3/1Od5793+oq6vF1GkzMGPGLBgMBnz6yYfYsWMbXn7pXziUdRCVlRXYs2cXFi08C7m5Objyqmth6OAUH77e/bl1hG7ZTa/VONsDXxB/4akBuN1u/Pjjj3jttVdRUFCA/v374ze/+Q3OP/8CREZGqn5ZUJz+4u5J4PNKZYmPj8fpp89BdHQM8vPzUVZWho0bN8LhcGDo0KFtvsrZ/1oIpZ4Ige6mby+N8rIyLL//fmzbuhVbt2zBzxs3YsvmTTjn3HP9hgmj74DqWOLWZYKRJa+yuUA4Cbvp+fzQtBQRgf3N6sa+BEEQYDToUFZahuzsbLjdbuj1enUtocfjQVVVFUpKStC/f39MnDgRlohIeCSf4cZ23D0ZrBzyMsnKAtvXgVtfTOXkw/VUsHrb4/GgsbEROTk5qK+vx9ChQzFgwAAYDAa1v+fbKI9Jk6dgwMCBmDFjNkaPHguLJQJDhwxDZVUlDmcfgs3WhPkLFmHRorPa8Ca/4CgmTpiExCTfUU1jx45HWVkpDhzcj4SERFx9zfVITExkUmqLiIgItLS2Ytas09DcbMPcufMxbNhwWCwWCKKI0aPHYtToMcg9koP9+/YiPT0Dl11+Jerr6nDoUBbmzj0DAwYMBABUVlZg+LAROGP+ApSXl+PgwQNISEzENdf8GklJyW1kw9bcjOaWZnVkt6y0BKmp6Thj/kJUVlVi06af0NjYgPPOvxATJkxqw7+oqChUVJRj9mlzMGjwEAiCgK1bNuPIkVxMmTINixdfoMpTTU01UtPSkZk5AABgt7diwICBSE1NQ0REBEpLizHvjAUYMXIUHA47Dh06CEmScMGvLsK4ceNhsViQlpaO3bt3YteuX5CZOQBXXnk1IiMjkZaWjkmTp2DsuPEYqoww8/03tWHShVDsgKamJhw9ehQAgt5NL0iSpC1FGqBISUg9Hg9MJhMilXOyKFOixjEA/oRVC9TA2YxqvZdlGXv37sUnn3wMq9UKs9mMxYsXqzcnBZNmbwTxVRAENDc348svv8T27dsgyzLi4uJw+eVXYNasWeqXPMtL4h898+8DhSzL6r3UUVFR6voU6qypHiRlnYs/WdixYztee+UVXHrZZThj/nxA+cKjY0TC6NsguaBF8LyyE5R1VEVFRRAEAUOGDIHBYNCUpa4AtQ3KD8k3FH3Hth/enXXrCxAgA5BwcN8+fPLJJ3A4HIiIiIDD4YDBYIAoimhoaIDJZMJll12GqVOmQDSa4ZFkyMoARm8xRgMB6VJ2Rkpgjvvh0ZNlgfpwnU4Hh8OB4uJifP311zh69CjOPvtszJkzx3fBgXJmJ7Vb+hAJBoHylwXb7gIF1Qn7m//Pu/E6iPJK7Zxt72w5KC6t9Aisf+If8f1EwKbNl4nKQEtF+Dy1B9J3bP+t0+nUD1CS++bmZpSUlGDVqlUQBAHXXHMNRowYAa9yBBiUvJB/4q8aZ3eMjAYLlnl8xRHKy8vxxhv/wXffrUBraytmzz4Nf/zjH9UFyiy08sDH3VPRXh6Jx5IyKjl+/HiMGTMapaVlsFqrsHv3bhw6lI0BAzIRGxsHcHXD4kT4EejIKNopT3FxMXbv2oVfXXgR0tLSYTSa1LighN+6ZTO2bt2KrKyDOHr0KNIzMmAwGLBj+3asWb0K1dXV6jms9fV1cDjssFgsqKyshNnsOyuNcORIrvplbbPZkJ+fj+TkZBQWFmDN6tU4dCgLMTExiImN9Zu20WhEXW0tvvtuBfbs2YPY2FjExfn4nJNzGJs3bcLRvCMwGIyIj4+HLMvIzclBkvK1f+RILpoaGxEfHw9JkrBj+3ZkHTyAkuJiJCcnw2g8tvC8r4Pkgjo4Vh5Jdk72yCiB10+8TNN7mTFce4PxFSgEWQZEwGw0oaqqClVVVeqZlE6nU9UxM2fOxJw5c2CKiIAgiBCUjoc10nsyyPDxR7yMsoYS707EvuuJoPyL7YyMsgYNXxa2Tfgj8hcqWB4HQmwYf+Dzw4fnn6k982mRbGi90yIe/PuOiAe5se/pmTX+giEo/GN/s4Y6yfWJjox2uTEaiuLhM0vPAOBwOPDpp5/izTf/C6vViiFDhuCGG/6MOXPmwKixtoGNg3fvDfCXfwLfyOLj4zFnzhzExcUjPz8fVVWV2LhxI5qaGjF8+Ai/69c6Sqc9BGqMticL1qoq/PLLDkyYOBGWCMtxowqHDx/GSy++iKN5eTial4ecw4cRGxeLQ1lZ+OD99+B2ubBn9x4UFORj5qxZePnf/0ZUVDSs1VY8+fhjmDptOmJjYwFlScAjDz2ESZMmIzYuDl9+8TkO7NuPjMwMPP7ooygrLUVRYSF27NiOs84+Czk5OZppJyf3w0MPPYj8o0fR0NCA1atWYuSoUYiIiMDy++9HzuHDKC4uxprVq5GZmYmG+no8+8zTOO/8C1BdXY1HHnoIFRUVmDJlKh5Ydh82bvwJWVlZ2L9/P5KSkjB48BCGQ30bJBf+jFFBEHqEMcr+Z2WZlDJ1RkRkhLAfVm0hc8S8kY/XU6xu1PrdBkp0MqBcy6nhpx3w/D8GGQIAk8UCSBLy8vLQ0NAAKPfUi6KIqKgonH766cgcMAAQBMgQIHP1Sgg0V+TveE4dQ6BxEbT45+P7sXNB/RFBYGaoBI1RfXZNKWsM9ERQudozRtnNPaGUI5QwPIKJg/yy/7XcWP9sPfL+WOLjI9ng4/PX9/FyFCz4dOi/P2LLFAgExsBmy8nKOJWBNUYFQQjaGA08VyGCb7jBgK/YQ4cO4d57l2L16lXQ6XS4/PIrcPvtdyAjI0MzDbagPE4kX92J9vLZXvnmzJmDBx98CKeffjpkWcb69euxbNl96i5Ggr+4uwLtpUXC+srLL+GO227DzTf+Hf994w3U1dUBymHGAPDIo4/h2eeeR1xcHLweD1at/BFnnnUWHnnscfz1b3/Dvr17kX3oEGpqqnHkyBGsW7sWi887D5mZmWpaaenpGDd+PLZs2QwAOJR1COcuXoyVP/6ItLR0PPvc87j3vmWIjo6GLGunLUsStmzeDJfTieUPPYxHH38cAwcOxOeffgabzQa3241rr7sOz7/wIjIyM/HLLzvQpBzI7PV68NWXX8Dr9aLZZkPWwYNoaWnBAw8+hIcfeRT9+/eHy+U7pzEMH9qTne4AO7JFilhUjnSiZ1bh00e62Wz2u3lSgOCzngSJIS8EwQsIXsXkatvGtdo8qyNkWYAsAbIkQNn67kunAx62yZdGGqy7+k4QkZGRoc5G6JVNXna7HUOGDMEAxRCFJMHt8cDj9cIrS5Dgs/ZkQSm/P8i+vAtqGY79p/AyfCQp/30cO75DluVjfGL5wPPW99/3m05H8Ecsv2ja0sCcpmAwGGAy+WZ46DfpufbqoqeDzzvPw0ApVPDxdERsGLadavnh2zHftln/hLbtr61stUcs+HeBUHth+Tyz5fAXRosCAS8P/tw6QpcboycCtkC7du3C008/pRonN910MxYtWgSZGZFghYdnfF8FK2hsmWVZRkREBK677nrcdtttSExMRF1dHZ566mkcOZLbJnxPgNPpBAAsOvNM3HTzLbj4kkuw85cd+PKLz9v4S0xKQlxcHCIjo+B2u2G32zFn7jwAwJixY2E0GlFU5Dtnbd3aNcg+dAjnnLu4TRwAMGnSZOzauRPNzTbfqPGIESgoKMBpp58OvV6P/ikpWP7Qw21G39i0AaCqshKjRo9GYmIiRFHExEmTfMdoKDzd9PMm/O+tN1FZUeG7blYZzykvK8cvO3YAzFSg3e47ZqSxsRHuvnQUUC8HtQ+PcsMI684S6SHWaCU32rTDtjVB8BliAkQI0EGAXn0GdBCggyjqVMOIT49IZAxi329A1AkQdYAgwjciKvoPT9QmXwwojTbugugjyEhKTsbMmTMxcOBAGI1GtLS0qEuGEvr182VAFGEw6GDQ62DQidAJgAgZOgAiGZsqMXkVccxYFY6RKEDhEqATfKRX/ou+CI7lVYEoHq8nifi+gojWw/FEdepwONRzZNkRUGrTHo8HTqdTPTPyOD72IbB8Y93Y/6y/UBFKWKrjziA2fdYApbbOv2P5QiQGMTIZKFhes8/t5T8QnGh9BYPO5wqHUApDlcuGTUpKQlTUsaMf8vLyVL9aIxZs5SNEIe6pYMtGxJYd3HqnIUOGYtiw4Uro479YQqmjUNBeGmSoXXTxJZg4aRLOOXcxZsyciT27d6sNG8ytH06X7+gcALAom5xE5bBp9lxHWZY1l2+MGzcOdXV1+Ndzz2Pc+PEQBAEet7vdMyHZtKHk2WKxqO9NJjM8Hi+oM6yoKEf2oUPweDxtjNr/vP4axo4dh9PnzIEMYPyECYiIsOC1V17BM08/hbraWtVvGD60JztdDZk5yomVRYLH41ENk5aWFrS2tqK1tRWNjY2ora1FXV2d6uZwOFQDpbW1FU1NjWiyNaDVbkOTrREtLTbYHS1wOO2w21vR1NSExsZG2Gw22Gw2NDY2tnGj9FpaWtDc3Oy7H95uR2trK2w2G5qafOFsNhuam5vR3Nys/qZ4Ghoa1HhbWlpgs9lQV1eH2tpaNDQ0oLm5WfXb2NgIW2M9mhvrYauvR0tzMxISEpCW5jvz0W63IyLCd7RNbVUVaqqqUGO1oq62FnW1NWhsqEdjYwNqa6thra5EdXUVamurUVtrRX19Lerr61Bba0VNjRWN9fVobrKhobYeNVXVqLFWo9Zag7qaWjQ2NqGpyYbGxibU1taiuroaNTU1qKm1or6+Bk1N9WhsrEdDYx0aG+vR2FQPm61BJd/7OjQ11aO5qQGNDXWor61GQ10N6mqrUVtThdra2oCorq4O9fX1aGhoQH19vcqnuro6WK1W1NbWorm5uV3d0pvgry2yfS3f7/J9DP87GFDYYIi1CXg7gf/Nh+HdBSbfpA+ov2XzyOaVd+8M8Pnh88gTlaOzoRWnlltH6JTd9BERETAajW2MQlpvEwoD6AuTFRIAaGpqwttv/w+7du0CAIwdOw5XXnkloqKi1GkxcF8sBC233gIyzMEJOYF1k5UvcuLf/v378fnnn6Gurg4JCQn44x//hFGjfJu8tBpPsJCD2E1PDUKrDrZu3YI3Xn8dTz3zLBITEyFJEp579llkZx/CG2++hZ83bsSHH7yPl199DQBw6803YcHChfjm66/x+z/8EbNPOw11dXW48/bb8PebbsInH32E9HTfGazTpk/HhRddxCeJe+6+G1ZrFW74y18wY8ZMPPXEE4iJjcGf//JXSJIXL/373zj/ggtQVlp2XNrnLl6MhoZG7N2zB4898QQEQcBbb/4XxUVFuPGmm3HnHbfjb3+/EVOmTsX/3noTuTk5+NVFF+GN11+HIAhY/uBD+Pnnn7F/3z48/uST+PeLL6CwoBCLzzsPK779BucuXqw5ottXwcouFMOfZMWr3HnscrlQVFQEURQxePBgGLphNz3ly+VyQRCENjrG7XajqakJ9fX1sFqtqKurU0fBBGX3vyz7PlhIp5GupNuZvF4PBNG3ptStfAyZTEbodHp43DIk6dioC7VRnU4Hp9N53BptmiaWJN8IXmtrK2TZdwOLIPj0KBuX7xYat7o+W6/XIzIyEm63G42NjXC5XDCZTDCZTOrInyAI0IuATpCh1xvgcrngcDhQUVGBkpISOBwOJCYmIjMzU53KFgTfcKZo0MNsMkEURfUyAINypaHb7YbZ7LsOsrW1FbIkw6Q3w2Iywyt54bA7fDoFMtxeDyKjomE0GuHxeNDS2gKH3QGT2Qi9wTdSrNfr4Xa5IMsyBKXcPnmRoNPpVbkSIUAn+z4snU4XDAY9PB5fXRksxwY/tCAou5PpVh7Su7LS71F9Go1GJCUlITU1FQMGDFA3Tna17IYC6sN13G76vLy843bTy0y/FEpZiFfUxlj4cwsFqgxq2AREvJvIzDhovfcXniD4GXGHEk7q5BsgtcDyi0070DQpjMfjUQdUBGXPEC3JkSQJbrcbsmIHlJaWqrvpr732WgwfPhwSs4FTZnbTC8ryFqrrTjFGtY52YhullmC1B6ooMkR5Idy9exc++ugj9Tinc845FwsWLGhzDBAvNCz43z0ZakVpNERWwOlZVpRiWVkZvvjic+Tk5EAURcybNw+XXnoZoqKi2ggmG1coICEMxBhtTxbIGO3Xrx/69esPq7UKVqsVc+bOxRVLluDRhx+B3qDHw488CjAG4f79+1FUWIj5CxbiUNZBNDQ04ImnnsZDDy7HOeeci9jYWLz4wr9wz9J7MWTo0DZpvvGf17F923b868UXERERgZ07f8GrL7+MM+bPR0NDAw7s348nn34aTz3xpGbagwYPxlNPPIGJEychMSkR69etw5KrrsKsWbNx6803YebMWRgydAh+/OFHJCUl4YJf/QrP/fNZzJw1C3+64c/48IMPcCjrIP52401Ydu9SXHvd9Thj/nw8/tijmDJlyilpjHqVqXBq+yQ7gmLcFRb6bhPp7qOdKB1SqpIkwWazoaKiAuXl5aioqEBtbS1aW1vV9b4ulws6nQ6xsbEoK/Pd+xwdHQ2dTge73a5slJHh9jggKIau2+2749nrlaDXmWA0+ow3Vre6lIP1Dcp5j5IkweuVYLGYIUkeSJIXoqiDw2GH1yshOjoaRqMJsnxsuYFHObCf1QVmsxlRUVGqIUuGqsVigVO5e9tgMEDyuGEQgQjlDGdf+hSfCFEQIMm+PFH9eSQPRGXdpM+/FzpRRHRsDARRREtLi3rTTqu9FaIgQvQARoMJZpMJHq8XDrvdV3avB5boSJiMJjgcDniUEWujyQhRJ/vShawasKIowmA0wGQ0wul0qvWj0+mhEwSIXhkQAEmS4fV4ICuHnIsmX/l4yEq/RmuC9coRN2TcU5oky2azGUlJSejXrx/GjRuHESNGqPH0NJCckTFaUlKiGqPnnHMO5syZo17kQH4RYllkZgY0GASbFttPEihteubfCYqhRDqIzSvJtL/wlBb1d2y/p0XBgu1D+fB8OcmtvTDtQVCWq3iUI/coHloHzb6jo51WrlwJALj22ms1j3bSsu/kUI1Rl8uFhoYGSJIEi8WCyMhItUES88l/KGDDaTFXVkYlVq1aiRUrVsDpdCIlJQWXXXY5Ro8efZxfAh8XLyhg/PN55+OhuMidjYMF+WtPeMHEyfIPikDLjOCSAmDTZam1tRXffvsNNm7cCEmSMHr0aFx11f+pG3h4Hpwo5CCMUSqbVvkLCgrw6ccfo6GxAaIoIjU1Ff3798evLrwIlRUVePO/b2DhokU4Y77vOre3/vtfTJ0+HYMGDcLb/3sL+UePIiMjE5defjkGDx6MVSt/xIiRIzFo0GD87603MW3adIwbP75Nmp9+8jEKCwtx5113q24rf/wBK1euhADgggsvxJDBQ/ymPWHCBGzc+BNWrVwJr8eLqdOm4bLLL4cgCHjhX8+jorwcUNaaXn7FFUhO7oc3Xn8N11x3PZKSkrB71y6UlpZiypQp+Pbbb/C73/8eJpMZK779FkOHDsXoMWPUfJ3qEAQBdrsdeXm+6/hGjBgBo9GoKUtdBbbteDwe2Gw2VFZWorq6Gnq9XjXkZGZkhUYQGhsb1Y0vsqK/fJAgiDJEwWcwiaIObrcLkiTDoDdBEHzrRkXFIPV6veqIK42KSpLkG2U0GOB2OyArhpnX44UkKyeeGMzwen3haVTWZDLBYPDdr00jH3rlDFBW15jNZrjdbvXYJo/bCUHyMqOmMryS17e8UxCUNdMCZPmYrnJ73L6RSJ2ojNIKkCUZkdFRkAVBPYZNkhTeyDJ0sgg9c56hy+WCLMmAKMBoMkGn0/muapR8ekanEyEJlJak5Mf3R6/3dYa+kVxfOfR6HfQ6PfSyAI/H7bvxRym3wWiES/K/io1kQWRuwqFOVuaMFi+zljQ5ORlpaWkwKSPE5I8lcqc42fS6GpR/vV4Pl8uF8vJyfP311zhy5AjOO+88zJ07t43cULlCQShlIh4FE5bC8NByY0HGEhS58Xp9Mi9JElpbW9X2woKMLvrQI15JyglE9CFEH5L+8hYItMIFw5dAITO3jPnajU/eSZdAuSWrpaUF+fn5+OGHHyBJEv7v//4PI0eOhMvlUvUgGydflyEZo06nE/X19ZBlGZGRkeqwPVnIVCEUpitABWhoaMAnn3yMrVu3QpZljB8/Hpdeepl6lqNWGPY3NXxoGKJs3tln1lgMFHIAX1Mk/BQ/KSQwo8UUB4WncLIs46efflLPXU1OTsZVV/0fpk6dqqbBp9kZkDvJGO1ueDwevP7aqxg9ejQWLPRdwxbGyQffFtk2a7fbkZvr23w3atQodXq0O8DrDjJGq6qqUFdXh6SkJAwYMEBtvzpl+on1T7LPjxKIyv3ZACAInG6RoW7ioXZPxOoHkI6QlREHMnIAyJIEKPfCU1hJmWoTGGOI4qNn8s/qSK/XCzBGE7mx9abT69RrGAFAkiVIXmU0RCcqO+KV+lWMbEEUYVQ6bcqfLPuMdPotiILvmki13MqUHwBRECEom5QkSYLb7YFO59sB5fX6DG01HkUPeTxeCILvpixJkiBLks8ffPv2dX6P4/KBPjx8hrD2MWOSJMFut6trck0mExISEtTRReKbpBitYIwgvg66A7LSnkRRhMPhUI3RvLw81Rg1m80wGo2qMcLWf6CgOmTlhn/PurF84v22B4qHeNse2DKwfNApo8SSJKkfnDabzfeRp3wQk3+qU4fDAShGGhmj7Dm8ZrNZdZdCNOa7E7425ZuONypLazzK9L3BYEBUVBRaWlqQk5OD7777Dh6PB1dffTWGDx+uzuIYuNMk2LKLohjaOaNe5esczPEXrJHRXQ0Hylf7tGnTMHr0aJSUFCM3NxebN2+C1+vF0KFDVeHghR9+hE9L0Hk3Nlwo4MPz+ePzyQo7/RcY4zU7+xBeffVV7NixHaIo4uKLL8Gf//wXpKenq3F0JVydcM5od+PB5Q8gNycH1//61202IYVxcsHLB/vb4/GgtrYWgiAgKSnpuFGJrgbfJl0uF1paWuBwOGBS1s57mR3X1G5J6dIzuI9Lis+3PtT32+v1jXZ6pWNnXVK8EjPaxuoFtVOTfYaS1yurZ5XSe1Z/kDuBDDk2r23iVXWR0r6ZNb0ylE5fMXzZNL3KeIegDFR4vRI8Xi8EQQefsegFbZX3KkarJAGSL/O+NAFAUAw0JR3fSK+Pb5LK62P5ozx4vcQXMrRFiKIesiz5jsJS/Pim9wFZBryyDKfTCbfbfRx5PB51qYRHWSfqZZY+kDuNJjscDtiVJQZGo1Fd1sbqQ74eWL1JvOsOsHlyOByoq6tDVlYWamtrMWjQIGRkZKgfWlRGMspZme6IeP+sbLfnFiyx6fhk1z/x4TzK8g+SI1EU1aUkXq8XBuUYL/IvMKOGEmNk0W+3soSDRlTJneq4J4P4QXVN0Ol0MBqNMJlMcLvdqKmpQW5uLiRJwsSJE5GUlASvMk3P9/8Uj6DoopCNUYdDmQ4yGk+qMUqIj4/HaaedjoSEBOTl5eHQoSxs374dcXFxqlFGjKDC88LIMpne+wPL1GDAh+PzxBL8TO/T++rqarzzzttYsWIFWlpacNppp+HGG2/ChAkTurUOAjVGoVH+k4WIiAhMnTaNOWUgjJ4ALfkgt5NpjPLyKytT7bRDPiIiAjExMeooGT8yyrZzXs+wOOavrWGgpZ/IXauzPYZjbqQ3iHjwHSOfNnWwbHiZG7Xzlc9nSBBR2mTsUtl8ODZNx6cvKQYelU/i4iSweWHdKM+CcGzUmC2LL0/Hh5VlGdDglxbvqFxa7gSvMoLoUTYzWSwW6JXlEGzeKQ9sOqxbd4BNx+l0oqGhAXl5eWhqalIPvTeZTOroGBEZG8FQKGFOhNi22RGJinyKygktVEYaCfUoy1pE7upzPbOWkuWPxIx8Uxps/fZk6JVNegQqN/HGqFyC4HK5UFVVhZycHADAxIkTkZycrBqjVGZw7Q2K3PUZYxRKuoMGDcIZZ8yH2+3B4cOHsWvXLuTm5mDQoIGIjY1VmUGCwCoBQkcN/0TLR2mzeSGiSgajoNj8CcoUwDfffIN3330HVVVVGDp0KP76179i4cJFsFgsHea/sxGoMUpl7AnIyMhARkYG7xzGSYaWfJDbyTRGCZQXWTFG7XY7nE4nIiIiEBsbqypddgo8GPSkNqKFUPJHei3YcKT72HD0zOaDf8/+1uI/+QmVqCyUN+qc/fnxKka1R5nS7MnGKEFQTltobm5GcXExWltbMWjQIKSmprYx1vgPiGAgczMFxAOKT8vtRNIKBuSfysrm1e12w+HwbToUlI2VkrLshfzSRxMZoVT/MvPxJnOjjZRGR6TlryM3eg7Wzev1Qq+c0sGWgYggiiKamppQUVGBI0eOQBRFTJo0qY0xyrYJlseqvIe6ZpQ2MLFrRlnLnw1zMiDLMsrLy/Hhhx8gKysLorKj/Fe/uhAREREqMynPLIg5WmjvXXvgK4DSp7goXlExRqnS2FEAWZaxefNmfPvtN2hubkZcXBwuvfQyzJ49W/3qYCu7OyD30jWjYfRMUHtgZYTcaM2oIAgYOXJkt64ZpbZKeZGUNWDV1dWor69Xz9qk9kujI1KQ68F4/cLrC96tM8Gm4c8tmPzRs8DtTA4UxD82PXpm88G/Z2WI+K9VBr4swUBm+g4yQth3AjMy63Q61fNgTSYT4uPj1V34lD5rDLB9AOvWHaByCcruaKvVig0bNqCwsBCTJ0/GuHHjYDabYTKZ2vCZrf9AQWGCrYNg/SPItkL8poE2QTl6zKOs+/YoyzRoPajdbocoioiMjITAXZZAZaR6FJSpfKpPdilATwW1XYdyRjLxUlD6c/r4bmhowJEjR7Bx40ZYLBZcf/31GDFiBJxOpzpiDE5eqOxCXzJGtSqTCrtnzx589NGHqK6uRmRkJC688ELMVW7tYY09AjFHC+296wiUDuULGsqVlJCoTGmRsOblHcFnn32G0tJSGAwGnH322Vi8+DyYzWZVefHpdAfksDEaRieC2gMrI+R2so1RMCP9ZIzW1NSgoaEB8fHxSE9PP86Q0PrYbQ+8ftHSGfz/zgKbhj+3YPJHz0IvMUbZ544gM8YoPzNIZYZSBt4YjYuLU3dZk7+eYoxSPqCMANpsNmzfvh35+fkYPHgwMjMzVQNEVE4SQAhGFclLMPIAxgAKBsGmQaByCsr6WK9yixblOyYmBgaDAU1NTRCVY9vYUVMo9e9RlpoIiiFKHyGSso6U0uqpoLKQQc62G6oPnXI+cGVlJQ4cOICoqCj86le/wsCBA9Xd9FRG4h/JGcVxQsaorFw52VONUTAFd7lcWLlyJb7//js4nU5kZmZiyZIrMXjw4KAaEU5QcIgfLF+oclkioa+srMQXX3yOvXv3AgCmTJmKJUuWICkp6bgwfBrdATkIY5QUbHfmL4zeBZJjkhFWrk+mMcp+TNFv1hhNSEhAenq62nmRn840Ruk/79ZZYOP25xZM/ui3EKQxSjqiM4xRlng//uIIFO2NjBIkSYLD4TjOGG1vZJR4Re5yNxqjBJaH+/fvR15eHpKSkhAbG9umn6e1o7RUKxg+8vUSCNg6CwbBhBGU0c3W1lZIyoYjAo3w6XQ6xMXFQRRFVFVVQZIkxMTEqKOH9IHiZU4cEBXjnQx4SRlswgnaFF0NMjbJeKTy8++9Xi9aWlpQXl4Oi8WCyZMno1+/fvAwB+ZDqXeSa5Jt8USNUakHjYzCj8DxCqm+vg6fffYZtm/fDgCYNm06Lr30UsTFxbUJw4L/fSINgm2AssY0vaB0eG63GytWrMDq1avg8XiQmZmJK6+8CiNHjlT9+MsHn9+uhByEMUr57s78hdG7wCos3q2nGqP19fVITEw8zhglYyoY8G2a1RXsM/u/s8Cm4c8tmPzRsxCkMUroDGOU+K9VBn9xBAotY5QvX28bGYUGL6qqqlBVVYWIiAgYDAa4lSN+9MrGFoFZN8mHbQ+8bAUCts6CQbBhZGbkW2Qu8WFl3Gg0oqmpCYcPH0Z1dTUiIiKQmZmJzMxMmEwm6JVbquh0BVHZ8MP2iV7ubPaeBpJByicZomTjUfsieZWVUyj0er16hBn7Hky7ZMOKp6IxSm5Hjx7FBx+8j+LiYphMJixefB7OOussNe+8f/Y3y9hAwfpn46J3bCPbvn07vvjiczQ2NiI6OhoXXngR5s2bp3Z0vH9Cd/KaIIeN0TA6EazC4t16ojFaXV2tOTIqhKfp1WehFxijoYDtoNnOmMoMZfqaNgL1ljWjlH9Ks7W1FXa7HUajETqdTp2S1+l0bYxRCke8pmfejU2rO0BpBlrXxG8qL8kRbeChOvV6vSgqKsKmTZtw6NAhGAwGLFy4EIsWLUJERIR6I6SLuXaXPlxY3UC8ZvnUE8DLMC/rYOSW/NPIr6AsbaCysfJL/KRwqrz3RWOUTZOetdwA4Oeff8YXX3wOm82Gfv36YcmSKzF+/HjIjAFKCoHCUYcTDARF8bHxsPkQBAGFhYX4RLkVSKfTYeHCRbjgggsQERHRRmC10mbj1XrfVZDDxmgYnQitNkxuJ9MYpXRIqUoaG5jYNaN8hxMo+PbN6gpeb3R22dk0/LkFkz96FnqBMRpMvgRmcxK4aUviA8XLjoy2KFee9kRjlPLhdDrhVA5mp/MjHQ4HHA6HmmfW+DAYDICfvReBgvgZilsgYOs5EFD98TynumXrvqCgAKtXr8bu3bshCALmzZuHhQsXIi4uTt3Q5FbOpxWZtba8MUZ5DKR8Wv46cqPnUN1Y0Hty9yrrYmXGiBeZ63BZexCcrIMxRk9IwrUyeTLBFpKtbD5fxEhRFLFgwQI89dTTOPvss1FTU4t///tFvPjiC7BarW0YzsOfeyDgwzY0NOB//3sLTz/9FAoLCzF+/Hg89NDDuOqqqxAZGdlGOfFhwTQSvpLDCCOMzgPf9qjddUX7o7TYNPn0uwLdkUZH6Ow8nEh98HWsReSvI/89GZQ/6mPY/pP6ShrZoyP8BG5jj55ZT9kR0QgahWF/d+TGxxUIqQZPAET+ZW4giuWDQbnsJzIyEjrmjna73Q673a6uBQWzplLUmFFl06X4OyItfx250XOwbgI3Na9jZn4oDFs/AmfEikF8RAXuMwDwjO5OkOCwjYjceRAzCRaLBVdffQ0eeeRhjB07FgcPHsSDDy7HF1983mZnXHsIxA8Pj8eDH374Hg8+uBw7duxA//79cfPNN+Omm25G//79ASavfJ61wCq9jvyeDPTEPIXRs9FTZYbaGW9wsNRXEGgdtOeP3gWixzobgabH15+/OuTdWVlg3bT88W5aOBk8gpI/o9GIqKgomM1m6JQRLYG5WYgFjfrSFH0wxPbRwYCPJ1AKBZIys0EbkLQ+NCVl+p5GP8k4ByN3ZLCxhrGgGGrkToZdTyOSAQLVHcsHQRkhNyg3UolBGKAsAg7FVwINy1NmZWbols9sd4HSD4YIsiwjLS0dd9xxJ/7+978jISEBq1atwgMP3I8dO3ybndjykdAR8b95Iv6IiiDu3r0bDz64HCtWrIBer8eSJUuwfPmDGD/ed3sSEZ9PNr88KIy/9ycbPTFPYfRs9BSZ4Ts1apN8+yRlHaoOpPCs7qC42Dj5uCl/wRCYcpAb+0FPeov8aqVDbixY/Ur6iDpsWnPH8ognesfHxfIcTLp8eJb4euJ1KeuXBZ8u30HzepYPz6Oj9yy08tOdEBTjQqcssaKRQN7I0DGjl2zYjoj8nWgZ+Xh5YhFsWiQ71AdTnfDt2uVyqX7Z9yxPKCwrMxR3bwTxhAdvf2j5AVNvrI0DIPA1o8RQnU4Hl8sFq9UKnU6H+Ph41RoWmdsH2N89GcQIyicJEx0F9eOPP8DpdGLIkCG44oorkJk5QFWW/pjNguKlL4fi4mJ89NFHyMvz3VIwd+48XHrppYiOjgb8dG49GXJ4zWgYnQi+PbJuJ3PNqJfZrAJmzSjtpo+Pj0dqaiqg5Jf9SA8G1FbkdpS5Fsh4CwZsR0s6jdLOyTmMzz79RB31SkpKxqWXXY5Bgwbx0bQLgbuXm+2AWCLIjCHGvwsEoYThQeHZuNg46ZmOM6L+j3jJ1rmkHHpPG5jMZjMSEhJ63JrRjkBl490I/Lu+ACoffZSRG9WF1+tFXl4eVq9ejZ07d0KSJMycORNnnnkmBg0apG5goo8vWl9LfSHL0xOV2b6AkyvhPQi8AjIYDDj//PPx4IMPYfr06cjPz8dTTz2FDz74AC0tLaq/joiUis3WhHfeeRuPPvoI8vKOYOTIkVi27H5cd911iIqKapOHvtiwwwgjjMDRHZ0TbziB0X979uxBXV0dho8YgfHjJ6CpqRGvv/YKHA5HG/8nAkqLh1a+Tjb4/PC/+zq0ykv1pPWur6CjsmnJbxihIWyMMuCNSFEUkZiYiD/+8U+48867kJGRiS1bNuOhhx7Ezz9vBLgFyFokyxLWr1+P5cuXY9OmTUhISMSf//wX3HHHncjMzFSFOSzUYYTRN9Db2jLb4arGhSwjNTUV1133ayy58ircdPOtsNlsyMo62CbsiYA3ZPjfJwt8nvjnnpDHME4O2A8o1l7gP6zCMhI8OsUY1VK+Wm69AVoGqSAIGDFiBO677z5ce+210Ol0+Oyzz/D4448jJydHXZjM04EDB/DII4/gq6++hCzLuOSSS/DII49g2rRparyU5qkgvL1VJsI4eehtMnOy8nui6WoZgl7vsXWblZUVAIDo6BjIsoy9e/dgz57dajii9959B802G5qbm7Fhw3p89eUX+OmnDWhtbQEA1NXV4ssvPseHH7yP/Px8oAs6bj5PwRIbD/uff2ZxovxnwRs2YZx88HXC/ubd20NH709l6B544IHlvGN7EJXzo1paWiCKIiwWi2pYEaNl7hyqngytPPJ5p9+iKGLQoEGYM2cunE4XsrIOYvv2bcjJOaxei9ra2oqDBw/i7bffxrp1a2G32zFz5iz8/e83YuLESdBxZ5RqCXRvA62doiM/wChtkVvo35vLGUbXQ0s+yM3j8aC2thaCICApKanNJoGuBuk0Vp7dbjdaW1vhcDhgsVj8rvsOFv4MnvYQShjKI2t0EWUdPIjDh7OxefMmrF+/Dtu2bkV0dDQuv/wKAMC6dWtRV1eHsWPHtYnzjTdex9Rp07Fl8yZ8t+Jb1NTU4sD+fTh48ADGjB2HF/71PMrLy+BwOLF+/VoMGjQYiYmJaGxowCMPP4hvvv4KP/7wPdavX4eZM2ep6+6ChaBxdqK/9+25kTv/X2bW9vL9HwtZ2UNBB5/r9XpYLJY260zJH5tfItYtjO4F3z7IjXWvr69Hfn4+Kip8H2vp6ekYMmQI4uLi2qwRlf1s9mbjPdXRKSOjfRUCNzpKz9HR0bj66quxfPmDGDt2HPLy8vDaa6/i7rvvwtKl9+DNN/+LkpJiDBs2DPfccw/+8Ic/ICEhoY3SYoUxLIhhhBHGyQRrDAGADN9zUlIyBgwYiLi4eDQ3N8Nqtap+SktKUFJSrP4+BhkNjQ2Ii4/HQw8/gt/89neoqqrCpk0b4Xa7cdvtd+LOu+7G4MGD8d2KbwAABYUFaGpqwjnnLsbs2afB6XSisbGBjzhgtCmLhoHZnhvLC3rm3cLo++DbBLi+mu/L2Y+LMIJH2BgNAKygsf/T09Nx22234Z57lmLatOlISEhAfHw8pk6dijvuuBP33LMUQ4cOa2OEkkHLUhhhhBFGd4M3tNoYXTLQr19/3HjTzfj9H/6Ie+9bBrPZjE2bflbfFxUV4Zmnn8LyB5bh+++/a2OsCRBga2rChx++j+9WrIDZbEZrSyuGDRuO2NhYAMDo0WNQXl4OAKitrYXRaMS55y7G/AULlXiYzAYBvizBEhsP+593Y93DOPXAG6NEYYSGsCUUAnijcsSIEfjb3/6GZ5/9J/75z+fw97/fiLFjxwZsdIYFOIwwwjgZ0DKq6DdNM8rKtGJ0dDQ8brfqLyMjE7/93e8xe/bpWPnjD21GTQXlWKL8/HzYbE2AMl1pMvuOfpNlGXqDAZJyJFVtTQ3S09MhyzIsltCm5jsLWsYp/xzGqQV/dc4OMoX78RODfwspCGhVgpZbXwH/JRQIdQTej1Yn0dvBlzGMMDpCb5OZk5XfzkqXdI6gbFr6/rsV2LplM7799htYrVakZ2SofuLi4zBhwkQMGuw7e9Tp9B37JMsABAGpqam4995luPPOu+FwONDc3IzCggLVAC0pKUaaYoDW1NQgObkfZFmG233sKsVgy8UbksEQH097z/Sf8hdsPttDoH1GGN0Dvq5ZsLOegdRbR+9PZXSKMco3ZH9uYZzaCMtEGMGit8nMycpvKOm2Z4ylp2fA6/VizZrV+PTTT7Bh/TpMnz4DM2bMhKxsxsg6eBDPPP0UXn7p30hO7of+/VMgiiL0eh30Oh3q6uqwft1afPPt1wCAkSNHoq6uDm/853V89OEH2LVzJ2bNnOUzUgsLYLfb4fV6kXM4GwDQ3Gxrk6euBs8Hnj888WE7C1rxh3Hy4a9OyCBtb/aT4C+OMMI3MPWoLxWWV/Tck/KnBTl8A1MYnQiSdy357y03MLHLcoLNH7WVYEH6ORhQGGqrPDU1+abXReXUFJq2BwCrtQp79uyBLMvo168fRo8eA4vFguzsQxg1ajQOH87GdytWKKdsGDBq1GgsWLgIu3fvwmZl3emkyVNw1lln46cN6/H1118xOfNh9uzTcM211wVVrlD4wIPXueyIF/uO6knH3DfOpy/1kRuYTkWwbQFK3VO9EIqKirBmzRrs2rULkiRh8uTJOOOMMzBw4EBYLBYgfANTwDjljVE2f1oCoeXW1eAbQE+GzBijkZGR6lEsYWM0jFBA8q4l/w6HA9nZ2RAEAWPGjIHRaOw2WepqY5Qtt9fr5V93iPbS8feO2iXpG94oBZMv6jyDhSAI8Hq9cLvdkDlDi/5/8vFHKC4pxuzZp0EUBMgAtm/fBp1OhzvuuAtopww8qByhgC+fVtlZP1RPp8J1oKcqiP9Q6p7aP6G4uBirV68O2Bil9kAyxbezUxkBSzjbIOk3684zU+t9TyM+n8GAVdqdTb0V/njI87yvgpevrqCTAa1023Pj5TkQYsMTZO7OdK/XC5PJBJPJFJLB1lPAl50vJ++H/8260X+v1wuPxwOv19uGeAOTwhAExihk+c/LHb3j3QIhURSh1+uh1+vVUUQ2TZPZjAXzF2LOnLmYfdrpOO2007Fo4ZmIiY5pU4aO8nai4HnTEbTywPOYnnl/YfR8aNUd/6HD1yvbhqHEITCDMPQ7LAfHIyhjlP06Y3+zjPWn9HoiSChYxciTFnjl3hXUnWmFSjz88UsLfFy9nYIp+4lAYEZfupooPfrPtwstN2gYkYEQD0FR/B6PBx6PBy6XCx6PB9HR0YiOjlaNre7ie6DQyg/PVyJJMbDJkKQRFIkzIPnfvBvxye12q8QbplpxCNxRdaIoQqfcHscbjFp+AyFBGU0yGAwwGo0wGo0wGAxtDNPFi8/DtOnT26Q/afJkXH3NtWo5+Dyz+eRlkP0dKFE4HlpuBIHrE7Xqh/XLptUeAvUXRteClTeqZy19RTJI70leKQ4KT3LB+id5CSMIY5QYSSCms//7OlE5WQE9lUlQDAaWPyQrrEKmZ/rdF/nHlrGriU+7qyiUDlFQjA8aCQuUtNJiO3CK12QywWw2w2AwQOyBSz46yg/bSbHP/Ht/qKgoR1FRIdzMEUsEirM9In8stHjPgn/Px9kRgVm6QHXJgm7xI5AfWobBxgM/6VPbOBGwabTnxoMvD6G9sB29a+99GCcXbN2w+oneSdyHCPnj3dCBHJxqCHjNqKQYG0ajEQ6HA1VVVRAEAfHx8epaCFEUISlf6fTl2heZTV/kpzpk5UpEdgOTxWKBoKyL8Xq9MBgMkGUZHo8HojKiodUh9XbQh0pXQ1CMsu7gH7X5YBFK2yAlDsZwcbvdqvFNMtTS0gKdTofY2Nhes2aUzyPrpvVeC06nE/978w0cOpQFADCbzbj4kstw2ulzVJ1L/CPZYNuZ1n9WhsiYo/zweWL98+8CQSgyQXmivoU3ZikfbL75cgUKiosNq8Ur9j2lR3mTNQwRWZbhcrnQ2tqqrhmNi4sLrxntBSDZY+WN9BHVR1lZGdauXYudO3fC7XZjzJgxmDNnDkaMGIHIyMg2sqClQ1j5PtURkDEqCII6jWQwGFRjVBTF4zYwkRHSlw02XuGcqqBG2tLSApfL1cYYZRdtQ1nETTJC70LpNHoqqPPoapBC7GoIggCn0wm73a7+DhShtg0KR1O4ZIyS8e3xeNDa2qoao+zpDaGmGSi0OpLuNEbfe/dtHDywHxdfchlMJhO2btmM3Nwc3H7n3cjIyDyuTbH/2brjn+k3awxp5Yn8su8DkQnyF0r7oPxQ2hQPmPqmvPCGXLCg+Hj+0H/2mcCWTQwbo30O1J6ojqh+WRkjY3TXrl1wu90YNWoUTj/9dIwcORJRUVGqjMjKum6B0yEkK+H6BXQPPPDAct6RBzUKr7JL3uPxoLm5GYIgwGw2qw2H/EncF3pfAgkklZGU4alIVH63262Omuv1eoBpaNTIqGGDG0Xk4+xtROVAN8k7pdkd/OOXpVAbb4/YPAUD1lhhlb2gKG9yo87AbDbDaDSqir2rITOGB/12u91obW2Fw+GAxWJBdHQ0oGEAdgY2bfoZZ5+7GDNmzERqahqmTZ+BLZs3oaK8HNOmz8D6dWtRVVmJ2tpaVFurEKOMHBcVFmLNmlUoLCxASmqaarxDyWde3hEkJiZCVkaerdYqREZGoaiwAFFR0RBFETU11SgsLEC/fv3h8bixfdtW7NixDY0NDUhLS4cgCGhtbcH2bVtxYP8+5ObmwGq1IiMzE7IsY9/ePdj080bU1dYiIzPzuI63ublZnV3jsXv3LmzZvAlujwcpKamQZRnbt23Fnt27cSQ3B6UlxYiKikJTYyNaW1sREREBURSRf/QoomNiIIoiCgsKsHbNaoUHqSoPnE4nft64AXt270JkZCRiY+Pa5IGe2frk86gl+zy8ymkCbrcber1eNURZmWfbDBsn6xZG94LnvZY8NDc3o6CgABUVFZBlGQkJCcjIyEBycjKMRmObcBSfyC0vYuM7lREeGQ0BYcHx8YAMFq2RUTJkyDhlR0a1FHZvR3eWqbvkj+orUAjMRysZb4GCNfIoXTK4qdOWJAmtra0AgIiIiG5dBqQ1qqE1MkodC1sePo+sG/8fAGy2Jny34ltcdPGleO/dt/Hb3/2hzdIMp9MJW1MT3vzvf1BZWYlHH38S9y29Gx7PsZuLLr9iCfr1S8Grr/wb0dExkGQJBr0Bt91xFyIjI9V07r9vKW67/S5kDhiAnzasx6pVP2Lpvffj/vvuwe//eAOGDh2GZ556HHV1dXjiqWfx8UcfYM/uXYiLi0ddXS0uvuQyzJp9Glav+hFr16xW0weAm26+DdnZWVi9aiX69euPxsYGDBs2HL/7w59UP+XlZfjnM0/htjvuQlpaOg5nH8L27dvw69/8Dit//AFrVq9EQkIiamqqcc6552HhojPx3LNPo7KyAlBG0S+86BKUlBRDFEVcetkVEEURd91xK2657Q44HA689spLiI6OhiTJMBj0uOW2OxEZGYlXXnoRJSXFMFssaLbZ8Kcb/oKY2FisX7sW5//qQny34htcdPGliIiIUHnPyjTJONWNzI2MkswGOzLK9p3kFkw7DKNzQPqH2jS5se27srISa9aswe7du+F2uzF06FDMnj0bY8aMQXR0tCojMjcySjqA3rNydaoiIAlnGx1PIrOzkXej6TZyY0nLrTNIK97OdKNyGQyGU5po44k/GWCJ5x8fV18g9oOM5UmobjzP2OfukD++btvLExHpCNpkRMcwBUJa/BOZ0VHSQz29c2aNykDBhnG5XHj15Zfgdrnx3YpvYFJmG4gHbrcb99x9Jx5+6AGUlZXC6/Xton/k0ScwZuw4AMBtt9+F0+fMw/r1a5GRkYl777sfd911D1paWrDxp/XHpWtTbjpqbrahtaUFra0tkCQJHrcbO7ZvQ01NDSRJQllpKXbt/AXXXHs97vrHUpx22hw1rubmZiQmJuGBBx/Bn//6d0Ax4Ddu/Amnz5mLu/6xFL/+ze+QlXUQR3Jz1XCJiUkQBEFdDmJ3OFBZUY7m5masW7saZ519Lu65dxkWLjoLa9esgsvlwq2334nT58wFAPzlrzdixsxZkJWRXUqXOvoN63w8WHrf/bjjrrvR0tKCnzduQFbWQeTlHcHv/3gDlt3/IDIyM/Hdd98iLi4eBw7ux4H9+5B18AC2bd2i5tUf/NW5P/eOQHkP4+RCqx60DEdyI6NTa/02gY2Pj/tUR8AaXVTOimOfWYOEJX9ufBjerTNIK97OdKOOkhXAU5VYOWDrmgwKvv7pmY+nLxDPC152gnVjiedfd8gfGXteP+dXarnRaHgooBFVdmSJZmPcbjdcLhccDgccDgecTmebUcC+hPyjeSgtLcH4iRPx88afcM7i89q8NxgMuOba67D4vPORkJCgupktFgwYMAAAEBcfD0EQUG21Yuq06TAYjYiKjsagwYNRUlKixhUVFQWdTofcnMNwOh2oqqwEAAjwdaBeSWoz2mmttiIyMlI1ei+8+BLMmn2a+j4iIgIWiwX9+vUDALg9bjgdDkyfPhMAMGLkKBiNRpSWHssDfYjYlNue6H9RYQE8Hg8O7N+H9959G/v27obH40F1tRWCIMBiiQAAxMTGAkqnfyjrIL768nO8/dZ/1firq6sxZepU6PUGREVFY9CgwSgtKUHekSMAgDWrVuK9d/6HqsoqVFRUwGg04owzFmD9+rU4+5zFWL9uLbwhbOIL49QA6UoiVo+1B9JxpG/DCMIYBWfls5XAdpBsxbC/tTo73q0zSCveznKjZ5lZT3eqEo0+UP0T8fLBywo4w6O3E6t4tGSfl51A3VgiNzLk2XS7gsiwZOuXLVtHFApYg1tQ9AzFR7/hZ1q7L6G2rhYAcGDfPgCATtRBkiR88tGHsNl8htrUadNx7uLzMWbsOMTFx6tLY4hP7LPZbFafTSYTvF6fES/LMnQ6PU6fMxc/bViPf9x1Bw4c2A8lAgDA9yu+hVfy4sKLLvG5M6disOmo9aXz1RUdO6UTffrApNzKJggC9Hr9ccbdgIGD8MH77+KJxx7BN19/CQBwupwAgNbWFjTU1yMmNhbTpk1HamoaoBi+YHSLAN/oas7hwygsLFDjliGr6QOAUbkwwaXE39TUhMbGRqSlp+HMM88GAERGRqK2pgaRkZFobrYhN+ewGj6MUwes3vEHtg0InG3Ag9dZNPLKu5+qCLjn4CuGmE+dBb1n3bT88347m7Ti7Sw3emb/n6rgecPySAs8D9vz25vgTx60yhqMG0ta/uh3V8Bf+oEQmPVvwRAU45M1Rvm4eeqLOP30uRg6bBjiE+LRv38KfvjhOwiCgH379uDdd95WDTmn04GDB/Zj6tRpgCofbWXFbDGjID8fUDq+8rIypKamten8Lr3sCvzuD3/CFUuuwuAhQ5Twvnc1NdU488yzEB8fr7j7TliotvpGJw9lHcRnn34MQTFAIyy+tZVul88YlZXlXUWKcdjQUI/W1lakKKcOEH7/hz/h/66+FlOmTsWgwYMBAHFxvjR/deHFuPHmW/G73/8JCYlJ0Cuzc2OV0VlRVPobUcDESZNx3/3L8Y+l96lxW8yWNjyoKC9HSmoq4uLiAAA3/Pmv+PtNt+Ciiy5FrOJWVFSIAQMGYvv2bUhITMTw4SPU+MI4dRCIkUi2Dv1vzxjVQl/WZcEiYGPUH7Sse/53XwN1mqc6iX6OM9ECKxN9kX/dqVC6i38Cd6lBoEQjq8GQP/khZU2jpCz1VZx/wYXYtXMnLrn0chzYvx92eyvmL1iEnMPZeOP1V/Hzxp/w3LPPQBR1OOfcxYDKJ194g7Izffz4idi+fSs+/eQjvPnf/6CurhaTp0xtk5YgCJg4cRJOO30OJk+mdz6exyckYOasY9Pww0eMRGpaGt555y2sWb0Kn3z8IYxGI4qLinDgwH7EJyS06VxNJhOGDB2Gr778HN9/9y3e+u8biI6OwYgRI9U4AcBoNGLylKk4+5zFmD37dADA4MFDkJKSgpUrf8DePbvx8r9fwJbNm9QwOr1v1JWV1ajIKAiCgIgI3wYtABg7bjx+2bEdn3/2Cf735huoq6vFlCnTMHXaDBgMBnz26cf4Zcd2vPrKS8g+lIXKigrs3bMb8xcsxJHcHCy58v+gV46nC+PUQUf6SMtN4I4+CyM4BHS0EwtB2SlNu1pNJlObCiLjhP1S6GtgBe5kUk/Ji8vlglc54J5GLugdGawys0aGjNe+RN0JPu2upmBBbT8U0gLFB2UNq07ZJOXPf1dADuJoJyh5DhUJCQmYv2AhkpOTcdbZ58BgMGLw4CHweNwoLChAQWE+kpP74Zprr1OPIxJFEcXFRYAyuioIAoYMHQq7vRUHDuyHJEm44FcXYfToMWpZWJ7LsgyL2YLWlhZMnTYd9fV1mD9/Afr16w+9Xo/GxkZMnzETI0eNxtEjR3Bg/z6kpafjssuX4OjRI2ior8fCM89CfHwCTGYz8vLyMHPWLEycOBmVFeXIPpSFhIQEXHnV1epaVy1UW61wOJ2YMHESRo0eg5zD2diyeRNMJjOWXHkVEhITAWUjV21NDWafdjpEUURVZSXiExIwaPBgSJKE3NwcTJ4yFWPHjYfd7kDWwQOQJAnnX3AhRo0eA4vFgtTUNOzdsxu7du1CZmYmLrviSkRGRiI1LQ0TJ03GmLHjMHjwEJVHWjJKvGf5yL6TlZGy8NFOvQ8Sc84oy3/22W63o6CgAFVVVZBlGVFRUejfvz/69++PqKgo1R8U3QXlA4rqm5WBUx0BHe3EQhAEuFwuVFdXQxRFxMXFqQ1LZBbw6piRs87GyW6goXbSXYGTyQtKk72Byaysz6JRMp2yjtSrnFErKsd/9RT+dRZ4hdWVkAKcAjoZEJjjj04UvGyT8ScIAqKiorpMv2jBG+DRTmDWukJDV9Czv/+hQGAMIlY22LhZIrAdIbVX1g/Pf5Jx+n0iefYH6jvApEdlYvNF74jXrG6hNasnArbMWv/B5IdGZsHwkeVRsEc7UVmo7OQWRvdB5m6EY+udfa6trcX69euxe/duuFwuJCUlYeLEiZgyZQr69++v+pOV9daCsm6a6puP+1RGUBLOV4gW8f5DIVKIgsYmDxISL7MuQ8sfS13hxk9pdkRa8XREYDoSgbnzm+0Q2Q5EVHZ0U3pdTZRH+s+DdWef+Xh6GvF1FwiJIdRvqMTntyeRwIzmsP9ZYt3YZ1aeeZAftt33dLBlYtspWz6tug3GTeQ2BfK8prS0ZEfg2qfIyD49s2mTP17mqZy05KK9euwIOuZDhuIl8GUnP17ldAeaoQkWfNmpbCyPWR4Q2DKzZad88/XAhg+FN2F0H7TqipUB1o3kw+12w263w+l0qu2SbYMkV2D6QJKhMIIwRvmG6A/kL1D/WmArEFycRKyC4NNk3bvCLVTi89yeG0sCtxaF9cMKOHUCOMGp0kCIjZ/lEQ9/bn2Rugt8uj2NwBmiPFi39vxpQeYMlJ4MPq/tlZHlnRY//bnRf0qL1RM8tOLw905Lf2j5JbDpdmf9UJqsMRgKWF3LEw9yI33LGt/0P4zeD6261wL1vzQq73a7NcNSu2J/h+XlGAI2RrsTVJFalSRy5zlqVXpXg5ROMERl0VJ0Wm7kTmWUJEk921FSpoFYPojKFJXT6eyWLy2tugkUJxI2jDBORpsPFd2Z185Ii9rmibTRzshHsOB1Z7AIprysLiewujyMUwdsvbOGpj954t3D8nIMPdYY5UcEJY0pEToQu7sPwSbFFwz5++puj2RZVo1LnTJFT/FA+TJ3uVxwu92qkW4wGCB241q6MMII49QC6WRWx5DOas9PT0cweQ3Gbxh9F3yfDaVf5uWDbRs82nt3KqFHGqPslAk0poBYw5QdLSSw/kkoOtuNF8KOKBTQaCiY9SYsX2hagEZCyWANNb0wQgfJRRhhnArwJ+9ausef354EXsd3RBQmjL6LQPpugVtvLCtLRng//tDeu1MNPdIYJVBjZyucpqVpFNBoNMJkMkEURfX6QK0R1M52C5a8zMJ+Ni7+N+tPEASYzWYYlHPu6FpEMrz1ej0sFot6zI1XMU7DSvLEwHc8gVAYYZwq4OWd//BmO3Heb08Em0e+XWsRHyaMvotADVIimVs3zIYNy0z76NHGKAu2wmmEkP0i0XXScTLdAV5h+1PiArNmlNz4OFiwDYF/F0YYYYRxouCNMmjoMxZa/nsigsljoP7C6N3QkmceJPf8yCg7U8siLDv+0WuM0Y4gMBt6eiKx0+yBEBmhbrdbFWw2DiiC7XQ64XK5VB4E0oDCCCOMMEKFloHJG6Ssn97SAfN57ojC6PvoqD8lmWf7ZY/H49cY1YpPy+1URI80Rqmx8woOGme78WtF2fCs0uhst+4ApcUanyzoi4z4o9Ppeu0GprLSUjz5xGNt3Ox2O5YuvRu1tbVt3MMII4yTAy0dyOppLZ3N+++J8KfrtYj1FzYkTj2w8swaoiJzbqg/Y7Q3tIWThR5pjNK6TL7iZGUamtZh8hVO73nl0Zl0IuDj8kcEMjZl5RaPyspKFBcXo7a2Fg6HA7Isw2AwwGQyAcyGpxPN58lASUkxDh/ObpP3+vp6lBQXo9pqbeO3q8HXRyAURhinEkjmWWPMnyGq5bcnItB2HKi/MPoetOqeNUjldqbp/YUNw4eA76ZnmeZV7qYXlA02InNskawYhOQWDMg/7RCnaWn+PZTRQoPB4FcZdiWFCj4ef8T7lyQJJSUl2LNnDw4fPozGxkaIoojo6GjolbvgAcBms6GxsREGg0Hd9NQdoE1VRqNRzQ81PHZUly8fi5LSEmzfvg2zZp+m3vFts9mwZvUqzJ03D8nJycjKOoj169fi4MEDSExMRHR0NHJzcrBt+1Zs37YVVmsV8vOPol9yP9iamlBXX4fc3FzU1taqV7PJsozNm3/GhvXrUVJSjPSMDBiNRlRUlGPDhnXIyjoIu92O/v1T1LyVl5dh3bo12LN7F7IOHoTL7UJKiu/qxy1bNmHNmtVwuVzIyMgEABzOzkZEZCQMBgM8Hg8OH85GcnI/HDmSi5iYGOh0OlRWViI3NwepqWkAgNzcHKz49huUlZViyOAhELk10Ha7HZ99+jG2bd2KPbt3IfdILkaNGg232w2rtQrl5eXIyzuCyMhIWCwWAEBtbQ2++eYr7N61C7FxsYiLiwcA7N27B/37p0AQBNiamlBcXIRE5c5vf/nYtWsnVq9eiZLiYqSmpsFkMqGurg5rVq/Ctm1bIUBASkqKX/4GA15O6FlSjjITFL3jT5a6AiS/rDzT9aQO7m56yj9riHU1uisdAquvWKJ8UNlZvnVnfXUHWJ3Gl411o42lHo8HeuZuen4/APFOi598/GF0PVie+6tjl8uF0tJSVFVVqccsxsXFYfjw4YiLi2vjP1y/7SPgu+lZZrlcLtTU1ED0czc9NTr6UggUVDkOhwOSJMFsNrdZFEy7yR0OBzwej2qQsn66AzT6yoIVLC0EK2yyLKvGeEtLCwoLC7Fz505UVFQgISEB6enpGDhwIBITE5GSkoL4+Hg4HA7Y7XZER0fDZDK1m5/OgizLbe6mZ0dpqQyy8oEiKJ2SVr62bNmMV17+Ny666BLMnTcPAHA0Lw+vvPISlt67DG63G08/9QSSkpPhdDoBWcbjTzyNTz/9GD9tWK/KHgA89PCjuH/ZvRAEAQMGDkRxUREuvPBiXH7FEnz88YdY8e03SEtLQ11dHQYMHIhly5bjweX3Iy/vCGJjY9HY2Iizzj4H1157PQDgsUcfQk5OjppXi8WCV197A19++Tm++forJCcno6qqCpddfgUuvvhS3HnHrbj8iisxc+YsZGcfwj+ffQYvv/Ia/vD73+Cuu/6BUaPH4O677kB1tRVvvvUODmcfwtNPP4nEpCTU1tRg1KjR+Mc996rpAcD333+HDz94r43bn//yNxzNy8Pq1SsRHRMDk9GI1tZWPPPMc5BkGffd+w+4XC5ER8egrq4W//jHvUhNTcVf/3oDnv/Xv5GYmIivvvoC361YgZdfeQ25OYc187Fx4wb85/XXkJiYhMbGBkydOg1//NOfcf+ye1FTU4PIyEg0NNTjscefxObNmzT52xFYmdBS1LJi/NlsNoiiiNjYWL+y1BXw+rmbvrq6Gg0NDWqbhJJfnU4HibnqL9j2HwzkdkbotfQS70a/yY39z4dl64QncLcSeZXrSQVlPT/VF/nl42Z5xL8LFFQWtox8ef35Cxak07SMSuKJzNxNb7fbYTKZEBMTo56SwvKNZEVU9gyQuxy+m/6kgK0bVsbBfIi0tLRgy5Yt2L9/PxobG9HS0oJBgwbhggsuwODBg5nYfDoESv2SbFCfFa7fHjYySqDGp1fOzJRlGXa7HfX19bBaraioqEB5eTkqKipQVVUFq9WKyspKlJeXo7KyssuprKwMpaWlaj4CoYqKClRWVqKioiIgYtOpq6uDzWZDfX09bDYbWlpaUFpairy8PGRnZ6O1tRVxcXFISEhAZGQk9Hp9yAo2FHTKyGhJCXb+sgM5OYexatVKrFq1Ejt3/gIAmDvvDIiiiNTUVNx00y2YMWMmvv32awweMgRWqxUJ8Ql48qlnkJiUhN27d2HOnHnYuHEDLr30cvztbzdCFEWsWbsa5513AcrKSrFo0Zm4/te/RWxsHFavWolFi87C99+vwMSJk7D8wYdhs9nwy44dWHze+QCA7777FhMnTsJ9yx6AxWzB4cPZmL9gAV74179w4YUX48abboHH48F3363A2Wefg3Xr1mLkiJEYMGAgysvLsH37VsyfvwDff/8dZsychcOHD2PTpo2QZRlnn30OXnvtVaSmpuKhhx/FsKHD8dVXX2DYsOFtRme3bd2Co0ePYvmDD2PBwkXYsX0bpk2bjvKKcjTU1+PxJ57GggWLsPGnDYiMikRBQT6ysg7iscefwoUXXYz9+/ch69BBTJ02HT/+8D0WLlqE6OhoHDxwAFlZB3DRxZfgpZde1MzHhx9+gDlz5+Huu+9BSkoqqqoq4fZ4sGXLJjzz7PO44IILkJOTg/HjJqC5pVmTv2azWS1LR+DlhO0UevrIKOWd9FZ3tsPOAOVXK++8G1tW3h8ZUeSvp3e2fFmDgRYPWDd+ZNRkMnU4MsrKGbmF0b1gec4+s3XidrtRUlICq9WqbiamkdH4eN9MlFY4tt7J7VRHwCOjYIxEl8uF6upqiKKI+Pj440ZG2Sn2UBo5fS1Qo5QVxX/06FFs3boVhYWF8Hq9MBgM6uipx+Nps6uc/vt75t2CAX35BxOWyhIMSKlHRERAr9ejoaEBtbW1aGlpQUtLC1wuF1wuF9LT0zF+/HiMGTMGgwcPRr9+/WA2m0PifbCQO2tkdPMmvPLKS1iwYCFmn3Y6AKC4uAjvvfsOlt67DKNGjcaR3FwcPHgAe/bsRmFhAX77uz8g/2geRJ0Ov/3t7+HxePC7316P+5Y9gEcefhDPPPs8kpKSUF9fj1tvuREvvPASIqOisHfvHuTlHcHWLZvR0NCAJ558Bk8/9TgkScLUqdOwa9dOpKWl4+5/LAUA3H3X7ZgyZRquvOr/8MsvO/D6a6/gL3/9O55/7llkZg5ARkYGjh7Ng9VqxYMPPYKXXnoRoiBi4sRJOJSdBWtVFZ56+p+4+aa/4eZbbsO77/wPdXV1AIDn//Uibr3lJsTFxWHkqNGotlpx9Ggervq/q3H++b9S+fP2/97EmjWr8e57HwIA7rrzdlx40UU4fPgwvB4vbvjzXwAA/33jdYg6HSSvFzabDbfcejsA4NtvvsZXX32Jp5/x5eORR5/AwIED8dmnn+Dbb7/Gq6+9gRv+9HvNfHz04Qd47PGnkJnpW4YAAG+//RYaGhpw8823qm5QOt49e3Yj78gRbN78MxoaGvD0M/9UlzV0BPZDlh818Hg8aGpqgiAI6hIVLVnqCniUyydo+YukjIzW1NSgvr4esiyrsq9jjnkJVk+Eis7kg1Zc5KZTznh2OBxwuVwwGo1qm6ZyS5KkGlutra1wuVzqWch0OojIXOssCIKqvyVJUtMIhX+yhhEdKIQgR0kpX7xel7mNTeysXnJyMtLT09Vyk6xr5Zt1Yw3XroRWPnoziLesTcH+Z/2RG19/9FuSJDgcDgiCoC6Fcjgc2LBhA/bv34+WlhbU19dj4MCBWLJkiaovWTmWlRlcVkeE4UPA1hEvpP6YyFZqqCBDVlKMPgAwGo2QJAlFRUXIyclBYWEhKioqUFNTo46MsqOKVVVV6qhpdXW1SrW1taitrUVdXR1qa2tRU1MTNDU0NKCpqQmNjY1BUX19fVBEw/5NTU1oampSlTW7REEQBNTW1iI7Oxu5ubmoqalRjfLeiEWLzsLo0WMwevQYjB8/UXX/8cfv8fDDy7F+/Vq1fG4qp9xWHunZYDCo8gMAkizhxRf/hRdfeB57du8G4JNTp9MJQIDNZsP+/fvQ1NQEnd6n/H2yfGwqzuVyMmGAlpZm1NbWIi4+HnPmzMOAzAEAgOpqK/bt24uK8nI1fQD4+KMP4PV6ce11viUA1JHb7Q7U1dZCp9NhypSpmDx5SptwfGvzej04evQoAMBoPLY+mDpGGYDFEqG6m8xmeL3HrsxVeQfAbDarG+L4fAwbNhxgjDGC2+2GV+MK3hf+9Rz+9fw/sXv3LlUPuF1u3ttx4JW/1jPVB+kifzqoK8CnJSjTs3Tpht1uR3l5OcrKytQZGtJB/MxKVxClFSxphbdarcdRdXU1rFYr6urq0NDQgKqqKhQXF6OsrAxFRUXIzc3F4cOHkZubi6NHj6KiogJNTU2oV2azrFbrcWmy+riqqkqdaaqsrERNTY2qs/m8dER8GTsiKl+wVFNTg9ra2uPS5/NcV1en6nJJktSlZbw80YCO2oa7Wcb7KmTm5kaJ2+BMYPVPe/aL2+1WP6igrOWXmY3EZGCSvpSY5Sqk610uV5vlO+2ldyohYGO0uyErXxBEkvK1nZSUhAEDBmDAgAFIT09Hv379kJycjJSUFGRkZCAzMxMZGRlIT08/jlj3jIwMpKWlISkpCYmJiQFTUlIS+vXrh9TUVKSkpARMycnJx8XVHsXHx6Nfv34YMGAAUlNTERUVpRhDvkXSABAZGYmUlBSMGDEC48ePx+TJkzFixAhERUXx7OzxILVgd9i5Nz5s+vlnjB07Ds//69+4SRmNc3vaN3LKy8ogCAKqq63KSISIvXt249JLL8fjTzyFiy66GFAMO1EUMH/BQjz51LP44x9vwP59+1BfXw8AcDodiIyM9D07fEZoorLh58qrrsay+5fj1lvvQL9+/aBXRs6uve7XePqZf+LPf/mbkhsfKisrcdHFlyApKRkA4PX6ljfMnj0by+5fjvuWPYAhQ4ciOjqmTTi+U7Lb7ZgyeSoAoKysTHW3Wq2Ii41DhCUCR47kquGKiwqRkZGh+lPscEAxYKOjojTzkZKSCr3BgPyjeQAAa1UVHn54OWKiY9QZCgC+EdZvvsbu3btw+eVL8NTTz+LiSy4DAqin3gAa6WNhNBoRGRmJmJgYJCQkICkpCcnJySoFq1u6iyhfcXFxiI6ORkxMDKKjowOiqKgoREZGIioqCtHR0TCbzZAkCU1NTaisrERpaSmsVitsNhs8Hg9MJhMiIyNhNBphNptVXsXHx6vuemVTT1RUFGJiYhATE6PyNS4uLiiKj49HQkJCwBQfH6+GOZGw7RH5SUxMREREhDoaSv+1IDIXurTnr7PBG8W9iciw0yJR4Sfrj57FDmYsifeiKCIyMhJmsxkulwu1tbWorKyEwWBAcnIyEhISkJycDIvFog4oNTQ0qMszwBjGpJd5o/hURsDT9MQ0nU4Hl8sFq9UKnU6H+Ph4dYROZI42oJGkUBhN4bzKpgGimpoa5OTkoKmpCSaTCQaDoc10Dg2FUxy80PHukiSpXzn0vj3IzLqxjgSYByuAgUCWZRiNRkRERKCpqQmFhYU4cuQIysvLIcsy+vXrh8GDByMhIQH9+vVDfHw8MjMzERPjM2KCSetEIAcxTU/1oJW33bt24rnnnsUTTz6N9HSf0WS1WnH7bTdj2bLl+PrrL1FeXoar/u8arF+3FllZB3HZZVegpqYaOp0Ov/7N7+D1evG7316Pe++7H48+8hAGDRqEhYvOxIpvv0FKSipuvuU2/PWvN2D4sOGYM3cePvv0Y9TU1GDp0mV4663/wmQyYe7cedjxy3bkHz2KV179DzZsWIf33n0HNyprVdeuWY0PP3wf/3njLdzzj7sgyxIuufRyfPP1l2hsbMRLL7+G22+/BVdcvgSzZp+GrIMH8Nxzz+Kll1/DH//wWyQmJeHpp/+Jffv24vnnnsXLL7+Gzz7/FJs3/Yzrrvs1Dh48gG3btuKJJ55GOmM8fvD+e/jhh+/Uafo//P43uPe++7F27Rr8tGE9LrnkMjidDvzww/d4YPnDcLtcePTRhzB58hQkJiVh7ZrVuPrqazFz1izcdOPfsGDhIsybdwa++26Fj/fPv4ivv/5SMx9r1q7G1i2bsXDRmdi7dw9kScYdd96Fu+68A6NHj0b/lBSsXrUSN950C15/7RUMHz4C8+adgY8/+Qg11dVYtmw5RowcqZZFCyQX1BZFZkMatTWv14umpiYAQFRUFAwGg6YsdQX86Qe32w2n0wmn0wmPxwNB2ayj4zYw9USQzgwU1J51Oh2cTqc6ml5WVoa8vDxUVVXB6/UiOjoaw4YNw4gRI2CxWNQBBRpJZnWCRzmij9fXrIERDEKVh2DTQZCjWpQvs9msGqSBgOqH0gq2fMH6D6ZMJ4pg89Ye2sszyRoL8q8VjneTmZFOg8EAt9uNyspKHDlyBFarFSaTCS6XC42NjXA4HNDr9Wq/nJiYiIEDByJO2Vnv8XjgdDphUK4y70we9HZ0ijGqZ9aMyooRyf4OFrwwENg1YxaLRf3SoTTZoW/6TwrNX5yh5C9YwxJKhxqoAiJQmLKyMuzfvx/79u1DRUUFYmJiMHbsWEyZMgVpaWmwWCxwOBwAc/A9KfyuhhyEMUr1oZUvm82GFd9+jSVX/h90ygiULMv47NNPcP4Fv0JdXS3++8Z/0NTUhKnTpsHW1IQz5i9AVWUlomNiMHnyFMiyjNtvuwX3LXsAt9z8d1gsFuj1emRkZOLPf/kbYmJisGPHdnz91RcwGIyYNGkyKiorcN2112P9+nXYvHkTZFlGZGQkzjl3MU4/fQ7+8/prqKmpxs233IaIiAjk5x/FV199gdtuuxOVlZV4/bVXUFRUiKSkJFx//W8wdtx4vPCv57D4vPMxfPgIlJWW4u2338LSe5fh9ddfxcyZszBx4iRUV1vx4Qfv48abboHb7cZ/Xn8V+/fvg8FgxPkXXIDFi32bpwgFBfn44P33cO999wMAHn5oOf50w5/x7bff4KcN6xEXFwdRFHHxxZdiwcJFAIANG9bjh++/g9frxfQZM7BkyVWQJAl33H4Lampq2sR/2eVX4LzzLtDMh8vlwtv/ews7d+5AbGwc/vSnP2PY8OHYv38fPnj/PTQ01GP69Bn43e//iB07tuOLzz+D0WjE5MlTUFFRjut//VtEK8ce+QN1tIEYo7IsIzo6uluNUfjRS7KiF73MznH6EGeNUa2wJxvttUd/YHUp6dzc3Fzs2bMHBQUFcLvdSExMxMSJEzFx4kTExcVBUjaeiaKorh0lvnk8Hni9XnX9KJsOQtTPfBhKLxC3QED1jCDCEKjcxEd/4ckf5dGfv/ZAMhkMRGYnf1eDLV8wYMOw9eCvf6V2yPKdBe/Gv5eUtaKyLCMqKgrNzc3Izc3Fjh07UFFRgf79+0Ov7OmguBwOBxISEjB8+HCMHz8eKSm+zaj0AUYfdYRQ+NDX0CONURYe5YB7VtiCPbewt8Nms6GkpARFRUVobm5GTEwMBg0ahCFDhqgbKrxeL1zKTuPeaIx2Jurq6nDzTX/DrbfdgYkTJwWVHuWRV0g9FW+88TqKiwrx0MNtb68KFC6XC48+8hAmTpqESy+9nH/dbRB6uDFK8sx2fnwndqoiOzsbW7ZsQU5ODjweD1JTUzFjxgxMmzZNXd5C9cTzi+qcN4AkZSalL4KVWZ4fLEKVbbYtBRsH9dvdgWDzBo0wLP/88VLuwOhl2zTbxgn0MQVlZLupqUk5EWUTioqKkJSUBJ1OB5vNpspxY2MjUlJSMGXKFEyaNAmpqcc2cGrJdnv5O1XQPVIXIuiLhnYiulwuyMwNBy6XC3a7HQ6HQ51u70jwWMjKLn1ahxkoUfrBkFe5VSoYorzp9XpkZmZi6tSpmDdvHmbOnHmcIep2uyEoU4TUqE51pKUdO/cxGOptSFXKGQqMRiNi42J7Zbm7E9SGiTzKiJ7W6FMwOuhkgnQp6TO2fDyRHiO9JDHTnm63G3a7HXa7Xe20+TW2pJMcylnITqezTRwsHz3KznoPt0GO3rP81frP696eRHIAo6IEXi8FShSWRjmDoY7y1Jng8x0s0aABkT+QX3/EhufjofqiaXUos49RUVHo37+/er53TU0NGhsbUVtbi8bGRgiCgNjYWCQkJKg77wmiMiDTG3REdyLgc0YJoijC6/WipaUFoijCYrEcV6FsgwsFrLCJyhEgOuW4D3omP+Su9aXBVrbg56snFIEItWxaaVG+eDcwilWvnE1nsVjUBdQ6ZipbUpQ68SeUvJ0IXJ1wzmhnwmw2IyY2FmPHjlPTDITAKK7egsSERGQOGICkpCT+VcBISUnDkCFDTurGN1bmqT5Ihth3dIoB7VztLpAhwT6z7ZZ+k9HhZQ64pvdsmfxBy09XuIGbvmTLpEX0ngxFqiO3242ysjLk5+ejtrYWoigiKSkJAwcORGpqKnTKsXtUV62trXA6nZCVNfFs30H5YkFpU/psPnk3r7LHgI+zJxGVif6z+QcnZ+x/9oMgUGJ56I/494GE6SyisgZDbBj2mfJMIF6Te0dp8byTmDvmJWUkk23Ler1ePa2lsbERdXV16keZXq9HSkoKJkyYgJEjRyI+Ph6iMtMjK3qABra6+wOgJ6NTpuk7ewMTVRorAOTmrwOidFlQJbOVzVc8lYt310Kg/tpDMHGwPBeUNWgSM41J/KU4Wb4FmsaJQg5imp7N84kgkDhY3nTkl4XAdBphdB+ovlj5lvxM0+MkbGCivIEzGHh5IX8y02F1Vx6DBVuOQCAo54F6lTOeRVGEx+PBvn37sHnzZhQWFsJsNmP48OGYOXMmxo4dCwBoaWmBwWBQj4Ryu92IjY1VTwnxB1YeggWrI7T0Bf++u6GVJx6UL1b2ggG1m2DRXfwIpUw8zyiv/H8eJOv+3vPx8m40yOLxeCArfazb7caRI0ewdu1aZGVlwePxoKWlBf3798fs2bNx+umnIzMzU9VlrG5zOp3wer3qYJ5W+qcaQpNWDlqM1HLrCCQobmWHKjsdRJVJ8fKKVCs9mfvqYZ9Z4dQpG6E6IvLnT6DbAwlhoGmRXxrp9Hq9aG5uRkNDA2w2mzodRvEKSkdht9vVEYKeBq06ChQCN7rA/tYif2E7ojB6Pk5EjkKFyBzSblBO8aAZGVZ2+Lzxv3sSSL8ESjqdTp2hoXXpdGQT7RKPiIiAxWKB0WiEoOit1tZWVFZW4ujRo+o5pOXl5eqxN/4gBKGbicD1H7TUiZ613OiZXybVEfFxdkQ0g0Sywusenng+BEt8fIFSd4Gvu0CILyO5d5R3CsvH5y9elvTMbJ9HOf1Bp9PBbDYjLS1NnYo3GAwwGAyIjo5GZmYm+vXrp+aJ7A0inbLRuL08n2rokdP04IRHYL4idcq0j9vtVt+xU2J8w2LJ3/tgwYcPlKDROQkaX8jkV2IWTusU5aJTOgBBGQll11bJzDWqYohfxaGgO6bpQwlHYfh66IjC6H4Q31k5IRli352saXpWLgRGl9B//h11ZP50Tk8g9qM8ECJDSmDKK8syrFYrSktL1ZNOIiIiEBMTo46GlpeXo7q6GqWlpaiqqoLT6YTZbEZ0dDSMymUmZOAJzAg5uXk11rD6IypPMBDa6Rvao2DBh9UaIGHrgwVfF4EQ8UQrDZ5Y3nUXnQgEbuZL1igjlQl+RokpD3w8FBfxTlZ0ktfrVZeYkCHpdrtRXV2N+vp6uN1umM1mDBkyBJMmTUL//v3VfErcVL/AfGiF4UOnTNOT8SN20m56trFS42WFyqVsZqIOyaUcG9Kdu+z5cpHQ8aCyEP8CBQk6nUlm5u729ijnlZECp6+y7uygoZQr0Gl6gVnKESyIj8EilLTC6H6wSpvkhO9IvCdxNz2lQ/qIBck6+5730xNBxkowIL3O6vqsrCxs3boVBQUF8Hg8SE5OxtChQ5Geno7m5mZYrVY4HA7U1dXBZrMhKioKAwYMwMCBA5GQkKDqRhptEpXpf5avgUJUPsYDhax8wJNhEEx6lO9gwOpAKh9fTlHjQ4fSClSuqG6ofjsKR+nTR1Sw5QoWfPmCAc+Tjkiv7LkgHUOg96RnyI3+e5k1yOTPo6x/Jlujvr4eJSUlOHDgAIqLi9G/f3/1JAmSbYpfx5w9HIq89XUEZYyCMQa72hiVlVEQUTEy6StFr9erI6M0QuhwOCAqZ9hpQSsPbHkCBeVLUr68gkGwjU5gzikUNUY7+a8+toEK3dgZyoox6nK5EB0drWmMQskv27CDRajlCSWtMNqCV+LBuAUKtm2RnFBHSjIkKTf9yMp5f91hjFK+XMpJHtRZU1tk9YHAnDFK6Or8hQIqExHr5g9UJlb36pULR7Kzs7Ft2zbk5OTAZrMhNjYWGRkZ6NevHxobG2G1WuF0OlU9ER8fj4yMDPTv3x9GoxEtLS1wK7fKmc1myMp0qI65oz5QUH10BFZfisrVysHqJpZ/gUBW+i8ylkluSFcSqO9k9TqFDwRUl7RUQQigP6C49coyFNYtEFCarBx15Ma2o0BBZSHey5xRT8/sO6PR2GZtJuWF9UO/CZJieFI+aflbdHQ09Ho9XC6XeoqPTqdDbm4uDh06hFmzZuH8889HRkYGjEYjWltbodfrVePV7XbD4XDAbDbDYDCod92TLcPm4VRDwMYoVbTBYIDT6UR1te/mG9rARA1H5oxRBCnUUATOq5ybKXLGKH21eZWDkmWloyB/YNJrr3LJPdjGgBAPEw5EIWiBTYeNQ2aMTnKjfBHvg81jMGAVQmtrK9xuNyIiIlRjlN6xfkMpPyHUsF3Jg1MBofAvVFkHNxvCyg+YSy9kZmS0q0H56MgYJflmDYhQeNfdCLaePMpueihhRVFETk4Otm/fjoKCAjQ3N0On06lXjdK1iIJylbHH40FMTAySkpIQFRUFWfmYFZTZHZPJBIfDgebmZrUTD4aPksatV2x4Pi65G0dGWflh3fg4qE7Yugmmnkhm3coxhMGAPgC6ElptpSNQGCJyC4TIwObbJfufngkysyFaEIQ2xqgoinA4HKrdERsbC6vVivLyclxyySW49NJLISozOw6HQ521hGKMulwu9WPO6XRCCBujAAI0RgVlc4zH44HRaITL5UJ1dTX0ej0SExPbVDQZrSdiELFfN4EIq8ztvO8rkAP8yucRTCM/UcjKF7jH44FBOYuN6oE6BlL2VJ6+Vk99FdSWg4GgMTrYGZCU9dE2mw0AEBMTo358htF9oHptbW2Fw+GA0WjE4cOHsXXrVtTW1qoGkMlkgtlsRkNDA5qbm2E2m+FWjr4xK3fUWywWCMrAQ0REBKKiomA0GmGz2dQbwgI1jKif4eWONzj43xSGDxcIqH0EE1brw4VPn/LGxt9dOpPPS6AgXgYDKmcw6QWSP628aLn5A5snqgcvs/6WQPWiU5YK6vV6XHzxxZgzZ44aVqt8Wm5hBGiMgqkUGqKura2F0WhUz9Di/RKz+QokCH6+AigcCZ2WHx7kLxC/PLrTcAsWVJ5gy8U2AvY//PA9UDcC21BlZdTI4/FAr6zN0ev1agMmZUpuZIxqxX8ibl0FrbQ6cmuP74G6sQjUrbMhhNguQgkndNDJ0EyJzWaDIAjdboyyeetqvvdkEB9out5isWDfvn1Yv349ampqYDQaERUVhcTERERHR6OxsRHV1dVwOByor69Hc3MzoqOjMXDgQHXNKHXoOmWHsdvtRmtra5sPofbaCu+mVVcyN1rGv2tP9vyBjStQ8AYma5ASZG7KGUHO4BE/KI5gwOclEFBaofCCrz8C70Z50kqno/yG+l5klh1SX0b2DFt/VIcWiwXjx4/HgAEDAEautPJLbpQ27+dURMDGKFthbrcb9fX1MBgMiIuLO47hbCVoCU9HYKfBAgUJSjAQumgU52SDGk53QOZGRk0mEwzKYcC0CYEaLMlDsHUbxskBq2gDacNsmw8WrFKmNNnOSpIkdd2hoBij/taIh9H1YHVmdnY2VqxYgaqqKsTGxmLAgAEYOXIkUlJS0NraipKSElitVhQXF6OxsRFxcXEYN24cpkyZgoyMDEDRWU6ns836Oih6ndLjO3d/buw7cEajlhshUDk/EbDpCorhR/LOvmeJ9RsoZG4Dkz/wZab8BMoHgdnbIAdp1IeiJ6hMgaYjayyNCBSUBpWP9BFbJyJ36o/FYoHJZAqYf2EcQ8DGKDFXVDYw0ZrRuLi4NhXtVa7KE5TRML2y8SaYyqGGF0gYvhEHi95gGFEjZxuBlhv5DYUPoYKMBK9yELbRaFTlgR0Z1Sk7CSnfgSqTME4eQq2nYOSPZJj9mKTOw62cMywq66/YkdHY2FiYzeaQ8hdGaBCY5VoG5uSOAwcO4Msvv0RFRQUSExMxYsQITJkyBUOGDIFbOfqmubkZRUVFKCsrg8lkwvDhwzFx4kTExsYCABwOh7q+jr9hLtQ6ZuWQ14v8b2gYZh0hlHyx8VP7YtsZmy/2OZS0Qm2/oYRBkO0+VGjVW0cIlQ8sKF2+TtgPCXILIzQEZIwKyroer9cLo9EIh8MBq9UKURTb3MBE/lhjlF1PGiiowgMNR34D9d9bwCqlQMp2MvggM9P0tFCbTZ+MUXILtCxhnFqQmClFGpFlP2ZkZUOGzWaDKIrdPk0fxjFj1KscTUPrOQ8ePIgVK1agoqICcXFxGDRoEKZPn47Ro0dDx+xErqmpgdVqBQAkJiYiMzMTRuWcUfqg1SnH5oQyksWCN1j43/7cgkGoeozXgVrxsLoffvx0hN4w0NLbQLYJ2uHvicrVqYqAjVFaI2Q0Gtvspk9ISFCVB2twULhQwFZ4oAjVCAs2ne5GKPkLlRehgjdGWZyoLIQRBhQ58ijX7QmCoO5qDaV9hHHikJXlFACQm5uLNWvWoKqqCmazGcnJyZgwYQLGjRuHiIgINYxH2YnvVTY10tmPHuUYJzJAw7qid0FWlgQE2xZD6efpQzVQCMwygmAgMKOeMrPckM8v+aE8dXff25cQkDEKRXAkZQOTw+FATU1Nm5FRvuLod09Hb8gj3wB6EmSNkVEyEoiogbLl6A18P9XB1h8vg1pu5B6KQia9AUbB8x0cGaOicpxK2BjtflC9sjMe+fn52LhxI6qqqqDX6xETE4MxY8Zg3Lhx6jS8R7nTmwYtaKaN6pg2PoLZrEYza8HWcUf+g5XN9tBZcXWFbqT22x0INZ1gw4XKm1DSISI++ouD1Xeh5i+MIIxRlskul0s1RmNjY9V1oaIytUbTLaF2FqEYsnIIGyeEbjwyoztBX3HdAVrLx25g0inHOFEHJChrRqmO2MYbRt8B1XUobUpmRldIn9AxQSQrXuUaYp1Oh9jYWFWmwuheCMpoE7VjMkatVisMBgNiYmIwevRojB07FrGxsZBlGXa7XR3MIKOTpvwF5ZxFcqf1o3Q8VDB13J7RQOgs3ROqHhO4Dzk+v2yc9Mz7CQSB8KIzEGqbDwXUhwSD7swfQqyrMIIwRonBIreBKT4+HkblwFZ/oE6qIwTqL4yO0R28JGVH6730en2ba0sljTNnKV9dnbcwQge19ZNdR6y8QDFGW1tbIYoioqKiVD9hdC/4NpyTk4O1a9fCarUiKioK/fv3x7hx4zB69GhVH9A0KWsYsB/NorJJzavsOZCUm3OMIR56z8su/dZyZ+U90LT8xRcI2HT4//Se/tNzoPliEUreuhOhlIl0QqAgWQ3FGPXHP1ZetBBM/sI4hoCNUShMFpXbByoqKiDLMmJiYtqMUJABQkKAdirNH4IVOHANN1DIIXxldTe0FBIpM1apsW70u6tB9cQbowblaCd2N3TYGO09IJliR7ECBbV/GjnrCCQP7Pm0FI5G1qkj8Xq9sNvt0Ol0iIqKgslkUuUqjO4FtWWdTocDBw5g/fr1qKurQ2xsLFJTUzFu3DiMGDFCNSZZHUb1xRoIrL4QlJkUml0LBpJypBw0DEZe7wQin50NNk3iBS+/lE/eb3ch2LT4vAYK1k7g0/TndiJg4/MXP7mxdcD700Kg/sLwj4CNUVYQWlpaUFJSApfLBYvFAkmZqvV6veo1WbIsq8d0UCfTEahCqTMLBmTwBCoUgjLVRB1eT0QojVxgDuPtjnLJ3DmjrDFK03Bsfsg4DbSewjh5oDV70OigtOqP2hRNtwcCWTE2o6OjYTKZVHkRlOsjacmPoKwztNvt0Ov16nWTNPIWaHphnBhIHzmdTjidThgMBmRlZWHbtm1obm5GTEwMEhISMGLECAwdOlQ9fotO2SCdAEBdXw7l7GoPdyRgKCD5I1B+WV3K/w8Vococmy4ZZGxcJP+sv1DSoriDAZ+XQEB1FiyC7ePRjUv44Ec+OqoTrTBhBIaQjFG73Y6ysjJ4lbtaZWW9lyAIcLvdcLvd0ClHf9D6L62K84dg/LIIVhBCFdLuRLAjAwiBDycC9kNEz9zAJCtrRiVmpIP4zSvaMHomROVA52AQbGcmMyOjorLmnD5e2ON+BMXQdTgc6ppR+tANJr2TCZJ5f/ltr034C9OdoPx5vV5UVlaitrYWERERKCwsxL59++ByuRAZGQm9Xo/MzEwMHToUkZGRMJvNiIuLg8lkamMgsYaFpHG0VyhgP4YobtI3rN5pj9eBIlhZB5MXApWbjYfKz/oLJa1QEEoaPG8DRU/ve1loyQ3LK/Y5WD6E4UPAxigYJtPRToIgIC4uDnq9Xp1WgSJkwXZiYfReOBwOeJlD71lI3I1LbCcRRhgsqFNmR0ZZXSJJUptpekFjdLanoqPOqr1yaPk/WaB6yc/PR2FhIbxeL+rq6tS75KHMnEVFRSEjIwMpKSlITU1FSkoKIiMj28QFDX1ABopW5x8IyBiFRhy8gQc/fOf9gPHHvgvFQBQYo43Cs8YovWfzGko6CHEgozsRSplC4QXL82DA14k/kD9elsMIDkEZo7LSUTidTtTX10OWZURFRcFisbSZiu/pjYCF1teZlkBpuYXhk4mWlha43W5ERkYed5UfyUK4oYbRHthOmZ2WJ50jK4fe09FO/Fr1ngiSdzKQJGaWgIwNiVljS35Zg4xGyfyNlrE6N9j2xaYVCKhT9ng8qKqqwqFDh7Bnzx4AwODBg6HT6VBfX4+qqio0NDTAbDZj6tSpmDp1KpKSkhAREdFmCh0aRh5bn3x5SIewYXi9IjNrWcmdj4f8kXwRH0RlJoANy/qj+iA+dJbsacWjlefuglbZ/PGd99cdCDbNk8nLMAJHyFYjNUpWGWgJCSmHnkaUN7YzoHesmxZ1Jvh88enz73oiSRrrBCnv/n7zcYTp1CZWPug/dfqsftGStd4Athw82HJqGZ88H/hwJwI+/vaI/Ot0OkRHRyMqKgoOhwN1dXWor69HbW2tSs3NzZAkSV1Dys+YEPgy8OmxYPPAPvN+WGOf3pPcsHLGpsXHw8Lfey23UCBw9d5Z8YYKrbbFuvHttLvB11tHFEbvQMgjow0NDZAkCZGRkYiIiIBer1e/etkp+pMlsIGAOkIEqViC8RsKWJ51dVonClmW0dzcDLfbre5wBmN80uiVpIwKiUGuHw7j1ABrJFCnzI+MulwuNDc3Q2TON+7JssS2Xb4Dp3dykKdL8OF592DBxxMo7HY7CgoKsH37duTk5KClpUXdnNTU1IT+/ftjypQpOOOMMzBo0CA+eLfCq5x9zeogMliDRah8DiOMMNpH8K2xD4EUk9YIRHtExlUw1J4Sk5kRIjAdRKgdRRhhhNGzwOsQ3p0FGU+szpCU0yncbrd6yQQLPv5AKRRIypR2XFwcRo8ejczMTHg8HjidTvXjISEhAQMHDkRMTAwfvFvB6lRW18vK9Dvt4g8UxLP29HkYYYQRPE7pkVFoGHyB5Jed7iktKUFdbS0aGxshMWu9TCYT+qekYOCgQaoSDPRLnM9TT4YcHhkNoxPAfrBRW+ntI6Ms2DbN5plv617l0HeRGb0jw4nVO3rl2C0yrPh4ugoSs0zC5XLB5XLhl19+wcaNG9HU1KT2AxMnTsT8+fORkpKi3srWHXnk5YF+8/ynQQKvcnoDe40xwV9+ZWXgwN/7MMIII3iEjdF2FIpW3mVZRkV5OdatWYNfduxAfV0d76UNomNiMH3GDMw+7TQMGzGizZe14Gd0Qsutp0IOG6NhdAL6mjEqKLvO6fxdvV5/nEHE550+ZkVm3SCrL8iAYnUHxeFPl3Q22HSobnbv3o01a9agoqICOp0OMTExmDVrFubOnaueQ82XtatAo51Q+iGdcsSgFm+oDti8sb8FZf2pv7BhhBFG5+GEjFFZlhEREdHnjVH6n3/0KFZ88w1279wJWTG0MgcMwPARIzBk6FAIogiXchh0XW0tiouLUVJUhKamJgBAaloazjrnHJw+d666oJ/vRNrLT0+EHIQxSp1sT5eJMLoffdUYlZT72HmjhjUq6Tedz0y6gUbuoHH2JJWb4vHXtk7ETQuixuxOdnY2tm/fjtzcXMiyjKFDh2LmzJkYP3686kfmjDw+LdaNnoNxI9DIMuuH5R1L0PgoIH5SvDzfCXz+wwgjjBPDCRmjUh8dGaU80//Wlha898472LJpE2RZRnpGBubNn4+Zs2bBbLFwoY9HZUUFNm7YgI0bNsDj8SAhIQE3/O1vGDFyJMDkgVWSvQVyEMYoKfeeLhNhdD/6mjFK4NszGTpe5ZIQah9erxculws6nQ5ms1ktr0u5zU6n06kXSvDxBfuhF6g/f2ANucbGRpSVlaGwsBAHDhyAy+XCxIkTMX78eKSmpsKi6EcqN8+PzgTJChR5opFp1qCn0VLiAfHOaDSqbuROYPVyV+Y/jDBOZYSNUT+dBVFtbS2efvxxVFVWYsiwYbjsiiswbPhwtTMJBLLSmdRUV+PjDz/E/r17Iep0WHLVVThn8WKAUXiBxtlTIIeN0TA6AX3RGNVqy15l7ScUPUnGE+kbMio9Hg+am5vR2toKl8sFQblS02g0qvwgA1aSJBgMBrWtBQqvsgY1WAjKmngAaG5uhtPphMvlQlZWFpqbmzFhwgSkpKTAq9zKpsWHrgIZnDRCyvLaYDCofAIzGm0wGFR5IlB9sJAZY7o7yxRGGKcCwsYoo1RIARFVVlTg6SeeQF1tLS648EJceMklAKPEg1FIgjIKAgD79uzB22++iebmZlx6+eW44KKL1E6IV3Y9nX9y2BgNoxPQF41RAqsnaLROz1yVzMLhcMBms8Fut8PhcMDhcMDtdqv6w2g0qkYTa4xqxdURWGNNCHC0lHQUrYP1eDywWCwwm80oLi5GU1OTegB+XV2dqgMorOznsHTWTctfoG408ikzOod4zRryLpcLDocDzc3NMJlMSE1NRWxsLERmMxMLVj6JB2GEEUbn4ZQ3RgmUT1kxREtLS/HM44+jqakJ11x/PeaecUab98GWS1AMMXqurKjAs08+icbGRlx6+eW48JJL2ig5+h9sOt0NOWyMhtEJ6IvGKI06UrtnjUeTyQSDwdDGv9frRUFBAY4cOQKHw6HuQjeZTDCZTDCbzbBYLOoIn6h8wHqVTTusYdmVoDSpfdNoY319PZxOJ5KSkgAANpsNemXXf3dAVk4ZIGNdZtZ9Ek+cTifsdjsaGhpQV1eH6upqmEwmDBs2DP369YPFYkF0dDQsFksbg5R0GLgLX8III4zOwQkZo3If2MAEDUO0sqICjz70EFpbW/HHG27AlGnT2nSWoYA3NEVRRGFBAZ567DG43W5cc/31OPvcc9v4Qy/gnxyEMRpW4mH4g6TsFKe20duNUUEQ4Ha7IcuyegQTa4zSCCe1h+bmZlitVuTl5aGsrAyiKCIpKQlxcXGIi4uD2WyG2WxWR0CJqH2RMRqMIRqMXwK1YboCmM4RtdvtbfJDdWc2m2EwGNpsKupKaOlO4hWUkenW1lb1xqj6+nrY7XYIgoDY2FikpaUhPT0dycnJbW6NYvOulUYYYYRxYjghY7QvjIxS/mTFEHU6nXhw2TJUlJfj8iuvxFnnnANZMabIbyhKnDUy6VkQBOzcsQOvvfwyRJ0ODz/2GDIHDFD9oJfwL1BjVAiPjIbhB33NGIUyDS4p6znJGPJ4PPB4PNAxZ4g2NTWhvLwcRUVF6p3uMTEx6N+/P/r164f4+HjolR35ErMxhx2p0/k5gqg9EM+DAeW7qakJHo8HycnJcLvdqKurQ2xsLCwWCxobG+H1emEymdQRRqfTGbSxHCwEZpSY1dc0est+FNjtdthsNni9XpSUlGDv3r2QJAnDhw/HwIEDkZmZiZiYGHWUFYqu4/Pfk+UvjDB6E3QPPPDAct6xPVBjdjgckGUZRqNRVbbUMEnx9hbIzA7Krz7/HHt27cLYceNw1TXXqO9YUGfJG5cs+DAsKE5ZlpGWno7amhqUFBWhrq4OM2bN4r33ePCjPeBGJei3Fp/CCAPcxxfftkRRhKTcQORwOCAIAsxmc5uP3p4Ikn2XywWvcrg6GY40wmm327F161Zs2bIFoihi4MCBGDx4MNLT05GQkICYmBiYzWY1LpYvOmV9JEuUBvGQfWaJ8scTG0YrLOtG5SDDj/oBKqvRaFTriAYq+Hyw8fPpBktsHMQPMuKJN+RHr9fDZDKpgymxsbHqmtGioiL1zNSoqCh1oIU+IiRl4xNbH2GEEcaJoXdZjV0A1jBsbGjAmlWroNPpcMVVV6kGKhlWWkqU/hNRnP7SIJKUMwS9Xi9+ddFF0Ol02LdnD8rLy9URCz6eMMLoq6C2BO5DhtzA3THeG0Bl8irT82SQUZlaWlpQXFyM7OxslJaWIjIyEiNHjsTIkSORkZGhjoi63W64lWtAaeqfDC0ytqDwjXQHS8Q3Mqho4xLPR15HacVH8eiVtaAOZYOV0WiE2+1GS0sLBGXTEBltTqdTTZMlio90Hf0/EQKg5s1oNKqDJYIgtMm/oJwIQJuXZs+ejVmzZiE5ORkNDQ04dOgQDh48iMrKSkAZRaalBvQsBbmJNYwwwvCPU94YZbF61Sq4XC7MPeMM9E9J4V+3ASm+YECGKzjDNiExEePGj4csy1i7enUbwzaMME5V8G2st7UJMnzMZjMiIiLaGKYejwclJSXYtWsXoqKisGDBAgwaNKjNcifeWGTLr2WEdRfYNElXsb95v90NnjdaeWDfeTwe2O12eDweREdHY9SoUcjMzERVVRXKysogM6P1gjIizM8GhhFGGCeGEzJGecXTG8GWYd+ePQCARWedxfgIHlp8YY1PGvFh3U6bOxcAsHPHjjb++xICLY/L5UJRYSH+v70zj4+jOPP+r0dzanSOLNmWLHwK29gYm8sYG2Pn4DJXvFlIspvdzYbD4d28IUAgLy8ESNhwhmMJ9xVzgwFj4QNjrmCbwzE2IIxsyZat07pHMyPN9Fzd+4f6aUrlHh2j0Wg0ru/nM5+Rqmu6u6qrnvp1HU8dPnyYPyQ4ihhseUlFJK0nTtHcLrHD2cFgEE1NTaiqqkJNTQ0KCwuxZMkSTJs2DVarVRdIsYRUPIxUXrLnZe3ZYBlK3ERDeato83ABIDc3F3PmzEFZWRlkWcahQ4fQ2NiIYDAIi8WCqDaPmaZZCASCxDCs2pQoQzmaUBp8Ph8ONzVhRlkZCouK+GgDwuaFUb6wQpQPkyQJJ8yfD6fTCa/Hg4M1NX16UdMFo3xhiUQieOP11/GrVVfi1lv+gBt/fwNeeuEFPtqQYHtABvsRpAZj+Vmw964yQ7uqJkZra2vR0NAAs9mMwsJCFBQUIC8vT18AmOi0j8T56GMkQgdblwYTJxlIWo+nw+HA+PHjUVJSgtzcXHR2dmLv3r3weDwwa35VqedaIBAkjmGJ0XSiat8+qKqKufPm8YeGBWtsyVizxps+FosFCxctAgDs/fZb/TdHE2+tfRMb1r+NlStX4opVq7DkjKXYsuVdvP/eFj7qoKC8ZxvOgT4CQaIwaQtlJG0Ym+ZHBgIBHDhwAIFAAAsWLMD06dMBRhClMrHqCWvbWGLFTxVUxhcpzTWVJAn5+fmYPXs2JEnCl19+qY/SUCdBKqdJIBiLCDGq0dTYCAAoKyvjDyUMXoDyhvt4TQjXHDjQJ/xooKenB5vfeQeLl5yBFedfgEWLTscvL7sMi5csQU1NDQCgo6MDa157FS88/zxqDx3SfxuUZWzcsAEvPP+cHhcAurq6cN211+CqVatw1aorcd0118Dr9cLv96O2thbQGqMvdu5EZ0cHmpqa9AULALBv715EIhEAQHt7O9a89hpee/UVdHW5AW1OYFNTkx6/ubkZ1VVVUFUVe/dW6uHV2nAs8eknn2D1s89ix47P9TBB+kGruAlJkiDLMtxuN9ra2pCZmYmFCxdiwoQJfZzWpzqxBCZvz8C9CKYyJm0FvslkQigUgtlsxrx581BUVITGxkbU19fD5/PponUspEkgGEsIMarh9XgAAK6CAv5Q0iguKQE0UXO0cfjwYUQiEczjeqYvu/wKXH7FlfB6PLj9j7fhow8/REXF1/jv2/+E6qoqAMCDD9yP8vJ12LVrF/58+59QqfUsHziwH50dHVj+ve9hwYIT4XZ3orOjA+9s2oiXXnwBqqpi+/ZteOThv+Ljjz/Glnc3Y8vmzVC1YdW77rwDjQ0N8Hq9+NNtt2L7tq34+0cf4dY//AE+nw9ffvklbrn5Jr1R2rB+PcrL1+HbPXtw9513IhKJoKWlGXfdeQdee+VlAMBba9fiqSefwLeV3+LRhx9G+bp1TGoF6QiJTLvdjp6eHrS3t0OSJOTl5SE7OxvRaBQej0eftziauN2d2PNNhf5/Z0cHPvrgfXR3d+thrMDkX67Zz1gRa6rWay1pPdPkISArKwsTJkyA0+lER0cHGhoa9JfTdJxGJRCMJsMSo+lQGSkN1BDk5ObGlS72N7H+Hsg4OxwOAIC7s5M/lBb0l68d7e0AgOycbP4QAGD79u0IBoP4459uxx133oXJU6ZgzZrX8OXu3aisrMRvf3sN/nLf/Zg6dSpef30NAKCttQ1WqxX/9OMf4/wLLgAAqAC8Xi/C4TAikQjK33oLANDd7et1RRPp9R/ILiDZuGE9otEo/vuOO3HXPfdClmW8s2kTQpojbxIbra0tcLvd8Pq8vQ1cJIK1b76JaDQKX3c3fD4fNqx/GxdedBHuuvserDj/fLxdvg6BgF9Pp+A7+isvYwF6qQHTS9rW1ob6+nrk5eVh0qRJejxamc2voE8Ug83Lzz7ZjqeffByBQADtbW144L57sP7tdWhsaOCj6vAilIXqUCz4+MlG0kQzuWpiXVIBQElJCebMmYPu7m5UVlYiEAjovxvtexcI0olhidH+jMxYgU+DxWI5ImwwsL/p7/dknGmlLf3P/iasvX2nG/3liyMzkw/qQ3NzM2YfdxwKxo2DyWTC/PnzUXvoECore4fDy8vX4bFHHkFjYxMa6usBbWi9tLQUYM6v57UKbNu6FR0dHQAAJdorAnZ98QWef241Hv7rQ9qVgb2VlQiFQvjbM8/gmaeeQjAYREND7zVUVcX9f/kLXnv1FdTX1fUKUy2ZjU1N2PF571C8oijYv78akUgEX+zciccefRQ7Pt+BSCRyVPaED4b+ystYQNH8WrKLFtvb29Hc3IyioiIUFxfD7+99EaEdpUZKjA42L3v8fqiqitaWZrz5xhpEolHceNMtmDlrFsDUH/58vBjlj8disPFGEpURo5I2f19VVXR1dSE/Px8nnXQSAKCmpkZ/XgKBILEMS4ymI8FgkA9KCOognDpTQ+RyuQwNfjozbtw4QNvjmqW1pQW7d+8CoMJh7+05BgCbzY5INIpgUAYAeLq64HZ34phjSnHBhRcCANpaW3R/sfx8vObmw3i7fB0u/tFKFBUVQdUUpN/vR0VFBfZXV+txZbm3B7TT3Ynubh+OmzMHy5Yt14/X1h7CZ59+ekTZeeKxxzBn7lwsOeMMQFURlHuPd/f0oLOjHXn5eVi8eAlKS3u3gBWkF0b11+PxwOPxwOVyweVywefzIRgMIkPbztPoN8lk6tRpAIDGhgZUfrsHEyZM7DN1qbOjA+vWvonXXnkJhw72zoPu6emB2/3daM4331Sgs7P3JU+WZbz37ma89urLOLC/t051ud1obPyup/Wbiq8hy731eDSQmM1LAMBqtcJkMqG7uxt2ux0lJSWQJAlutzslplIIBOmIEKMaZIi8Hs+IDb+wgpQN08WoFj5+/Pgj4qU7RUVFyMnNxbd79uhhHe3t+ONtt2Lj+vVwOByo3l+t50ldXS0mlZTA5eptKK+7/nrceNPN+OnP/gX5Lhd6enqwf/9+fdtaml8a0Ho2gsEgTCYTzjr7bNhsNv28J598Cu6+517ccdfd+n24ClwoLCzCzX+4BTfedDOWLj0TObk5+vHrrr8B9z3wIKZpq6KJ1tYWXHLpT+BwZEJRVbhcLgDAJZdcihtvuhm/ufq3KCwqhJnZ/1qQPpDAoSkfiraSXlEUOBwOZGq99fQSSqvtR5NmbdX4B+/3erCYOq1XnAKAz+vFQw/eh927dqKhvh6PPvwQqquqsGXzJrz84ncu2N5643Xs3vUFVFXFM089jr9/9AFqD9bgicceQeW3e/DhB+9h+7atgGb/Vj/7NP7+0Qf675OJqs17tdls+sIk1qk9PRNa4MT2/B5N9lkgGGmEGNWg+Zq0qr4/+CEpoj/jRI0RfdOHPR7UegeOmTy533OlI2azGT/4wQ/w0Ycf4p1NG9Hc3Iy1a99ET08P5h4/DwsWnIjWlhY8+MD9eOH557Bt61YsXrIEpy9eDKvVitV/+xu2bd2Ke+6+C19/+RW2bduKQCCAXV98gVVXXI4nn3gcALB71y5kZWUBAM6/4MLeBkib06eqgNPpBAA9DgAsW7YcLS3NeOP111G+bh0ef+xR1NXWAtrjd+XnAwDMGWZkmEzIyu797cLTTtOnCZjNZpQdeyyKS0pQvu4t7Pj8c9z55z/jg/ff168jSC9M2uYWwWAQHo8HnZ2diEQi+suPxWLBuHHj9LIW0bbqJIGUaMim9CekrDYroHmuAICzzzlPv5cvdv4D4XAEV1/7O1x97e8wecpUbFxf3rujVDisz3t1uzvh9XixZ883qDlwAL/45eW47oYbMXnKVGx+ZyMikQjCoZB+HwozRzPZkPi02+0wa7tfqaoKm82G3NxcRCIRHD58GIqi9PEDSzs2jcRzEgiORoYlRtOhIlIacvPyAAC1tbW6kTQy2BKzxzHbeykxOyuxQz7scVrEQMclbViOPjTXcfLUqWmRtzwDpenc81Zg/oIFePWVV/D/brge27dtw/TpM3Dueedh5qxZ+MV//ifaWltRUVGBc89bgR+edTbGjRuHVVddhebmZjy3+m+YVFqKS3/6UzQ1NmHSpEm45NKf4J8vuRSX/uSnmFRairr6OpwwfwFOXbgQZyxdqs8/nTfvBBSNL9I9GkiShBllZcjMzMSpCxfi4h+txLatH2PTxg04ffFiLD1zGWbNnIW5c+ciJzcXAHDaokVYdPpiTJs2HfNOOAH/9ON/BgDMnDULp566EJIk4f/+5jdwZmXh6aeeRDQawZWrftUnDwTfMVB5GQtQPSfBJWlzEqGJVbvdDkmSdDHG2o7hQteWONtEdojsDxg7lZPTW5bJJdX+6l5XZaqqorW1BTPKypCf70JGRgZmzz4OTYeboKoqDh06iGeffhIvPr8aAKAoUdTs3w8A2PzORqx+9mk0NTagtbUVktZbzKbVbuvNh0TApru/c7I2nvzByrKsj5o4nU5IkqS7dMrMzDzC5gsEgsQgKYpypOKKgaqt+gwGg+jq6oKiKHA6ncjMzNTfKsEYMvpNKkMG6euvvsJ9d9+NsmOPxTXXX9/H6IBrJOjtmRWeJmaRAp2T7QG12Wz6Vn+0Apu9hslkwhtr1uC9zZvxlwcfxLjCwjFh7FRVRXd3t+4KhXoOKG29PY69eUH51F+ZUFUVVfv2oaamBgUFBTjp5JP7lKfB8vJLL+KYYyZj8ZIletiOzz/H9u3b8Ntrru0TVzD6kDAikULlhupARNs/3Ov1wmw2w+Vyxb3YMFmw9iISiUCWZaxfvx41NTVYsWIFTjzxRN0+UI8o2ZRkwE8LUFUV+6ur8Mhf/wc33nwrHnnoQShKFL/7/f+H3W7HmldfhqIo+Jef/zsA4OOPPkT5urU46eRTsOPzz5DvcsEkSejo6MCi0xdDVYHPPt2OSaWlcDqzYDabMXPWbDQ1NsDtdmPVVf8FRVFw7dW/xo9W/hhLmXnY8cILUCofbDlhw1Rta0+Hw4FQKITu7m6YTCY4HA7YbDb09PTgwIED+OyzzxCNRnHWWWdh8uTJR9h8gUAwPI762kTGa86cOcjKysKB/fv7+NSjOGS4WNgw/puHN4A8iqJg986dmDBxIgrGjTvCqB4tSJKEmbNm4dzzzsOpCxfGJUQB4KKLf4TTtB2tiJNPPhmXX3FlnzCBYKRQmNX0NpsNDocDkUgEfr9fnyfsdrshyzIsFoveOzfSGIk1wqq9TObn5+OUUxfC6/Xi/S3vApqf1IMHa/Tf1NfXobi4dyTBZrPh9zfejOtuuFE/V15+72jTZVeswqqr/gvf/+FZoEvzyZRMiU33YPNRkiREo1F0d3cjEokgMzMTTqcTqqrqC5by8vL0ThiT5vSenT8qEAiGz1EvRqEZpAyzGYvPOAOKouDT7dv1Hk/ecLPGm45ROPUG8r2qJGapR5TvFQWAnTt2oKOjA2cuH37vgADIzMw8QsiaMjL6zAUVCEYS6vUkO2G1WiFJEkKhkO7nljww0PSdZMDbJhYTM7y9dNlyOJ1ObN/2MXw+H+bMnYfOjg48/ujDePnF5/HFzn/g1NMWQZIk5ObmQWKmA2SYzTjllIWwWq145aUXsX3rx3j8kYf1ndPq6+rw9VdfouLrr7X/e6coJQpeZMeCxKjP50MoFILdbofFYoGiKHoYjfZEo1F9ioVAIEgsybF+KQwZXkmScO7558NisWDzxo2QZfkIQw1m+BmMCGUFKP8/QWKUjUdEo1GsLy+Hy+XC8u9//wgRLBAIxh6sPSCsVivMZjO6u7shyzJyc3P7rKofrIhKBGRjWBuY7yrA3OPnQZIkOBwO/Pzff4GJxcXwdHVh2vTpuOQnP4PP50V9fR3OPe98nL54CY6fdwKOmzNXP9fiJUuxYMFJyHe58G//8Ut4PR5s3LAeM8rKcOHFK3HM5MmQ5SCeX/0sXnqhd47pzn+Mzta4kjafNxgMIqL5d6YebYfDAUmS4Nd8r5LLJ4FAkHiGNWdUVVVkZmaO6TmjrOhTFAXPPfss3t+yBeeuWIGLVq48Qnyy36wxZ7/ZBoi+qceAb5wkSUL52rV4Z+NGXHnVVVi0eLHeK8v+PlVRhzBnlNKV6mkSJB8qF+ycUZaxOGeUtR3kNui9997DV199hdLSUsyfPx/HHnusLniQ5B5S6rll4W0Xm78qN6eVjvMimh1VYu1rLCq/3YMnHnsE9//Pw/yhIcNfk02LUZhJ24uefIrm5uZClmVEIhE4nU60tLSguroaNTU1yM7OxtKlSzFx4sQjziUQCIbHsKxeulVESZJw8cqVyMrKwvtbtqCjo6OPMIxFLOMNTqDyRhsAqvbuxeZNm1A2cyZOPe20PsfSDT7tAkF/jPXyQqvWqectGAyiqKgIkyZNQltbGw4ePAhFW2Xv8/lGxVWQkWikv2OFD8RQn1tOTs6gz51oVO2F2el0IiMjA36/H93d3VAUBVarFR6PB/v27YPFYkFpaSkkzROAQCBILMMSo+mGJEnIzcvDz37+c4RCITz60EP6pHX2bd9IoJIQjSVI+fgA0NLSgmeefBKSJOFn//qvhg2DQCAYu0iSpC9MUhQFEyZMwOTJk+Hz+VBXVwe/3w+TtsDJYrEkte7Ttdjv/sJGionFJfjV//k1H5wUqHeU/IyGw2FkaE7vAaC1tRW1tbXIzs7G9OnTYbFYhBgVCEYAIUY5JEnCkqVLceppp6Ghvh733X03vB6PLkj5j5GxZkWlUXyTyYTW1lY8cO+98Hq9uOCiizB5yhRDkSsQCMYmNAxuMplgsViQkZEBl8uFCRMmwOFwoLOzE1VVVfD5fMjNzYXNZkt6/e9PfPJhRrYuEZhMJpQdO5MPTgrUcUC92NRLKkkSGhsbUVdXB0VRMG7cOIwfP16fhiQQCBKLEKMGSJKEy664AsUlJag9dAi333YbDuzfr8/nIkFpZLjZc/BxSZDu27sX9955J7weD85cvhwXrVzZR6wKBIKxTzQaRTgchqKtqLdarbBYLMjKykJxcTFCoRC2bt2K2tpa3T4kG9besLaMt2tsWDohMXOVJUnSXTvJsoxPPvkEtbW1GD9+vL6VL20bKhAIEsuwrF86GCejYXUAcGRm4vc33YRp06fD6/Hg3rvuwtrXX0ckEtFFKX3zYpMMNxsnIyMD7W1tePapp/DAvffC39OD8y+8EL+47LI+IjedSff0CRLLWC4vRiKOvp1OJ8rKylBYWIiGhgY0Njbq80pDoVCfuCMJf198GPvhj/fHYOKkGpFIRO/JjkajaGlpQVVV7+5Ts2fPRlFREQDoPdwCgSCxZNxyyy238oH9IWl+2WRZhqq5u7BYLDAxO+uMxht+vLCLingj6nA4cOby5cjNzUXtwYOo+PprfLp9OwCgqKgINm0rP77B4Xs5aw8dwptr1uD51avRUF8PV0EBfn311Vj2ve8dEXcsEgqF9An/1GvAl4VYeSwQgCkX1ItI9oQNJ7+cJm2HnFQXBawt4MPtdjvC4TC8Xi8yMzNht9sRCARgMpl0F0JGL8mJhD0/Wy9ZW8aGxaq7RvdJ8WP9ZqSI55rUIRGJRNDT04PW1lYcOnQIra2tKCkpwYknnojCwkLdttH5jdItEAjiI27XTm63G6qq9tkOlIY62EYilSusqvn+BON6yciQqaqKcDiM9959F+vLy+HzemHKyMCsWbMwecoU5LtcfYZuZFmGLMvoaG/HNxUV8HR1AVqPyIoLL8RZ55yjO8AeiFTOP2j3R86hs7OzYbfbgRiunahxHm6aJOEeKu2gZ8qOPEArX5K2gpl17VRQUKC7S0pVJG3RUnd3N1RVhd1u1+u9qqq626C9e/ciGAxi9uzZmDdvHgoLCwHGPvFpZO0Gfywe2HPQ3+y30TUonD6K5iKKFaGx7OlIwl6fTwOfNro3s9kMm80Gr9eL6upqVFRUoLOzExMmTMDxxx+PsrIy3a4RRnkiEAjiJ24x6vF4oKoqHA5HHz+jZITY36Qi1FCwvlHJiBlB6QgEAti8aRPe2bBB9w04ENk5Ofjh2Wfj7HPOQabTyR/ul1TNP0JRFPj9foTDYTidziP8jFJZUBLgZ5RtRAZzjljPUpB60DPlX2jpGYbDYQQCAXR3dyMjIwP5+fmwWq2DKgejBdkYt9uNaDSq1w/2xTUQCODtt9/G7t27MXv2bCxYsADFxcW6I3xaVAMDUUXXGC58HtL//DcLe4wfXeI/yYSuyecTHQOTjySgaW5va2srDh48iG+++QZWqxXLli3DnDlzYLVaAW0on325Hg2xLRCkK4MWo2xFDoVCCAQCUBQFFotFd0vCxhsrsEZ0KMiBAD779FNU7duH9rY2uN1ueLq6YLVaUVhUhOKSEpRMmoRp06ahbObMpA4pGhnikYCMMvXeUMPJ5qVRgxTP/bGNBzU2AyElcVFIsq4DTdinG9RjTnP3JM0lEuWrLMvw+/0IhUIwm81wOp0pvyMOlftIJKK/qFOZZO3Bvn37UFFRgba2NlgsFhQXF+urt4uKiuBwOPS4iqIgEAjowoimxrCCcChQXRqoTlEc9n/+OMHX/2TA2nFJm0pGdonym0QltHyUZRkmkwl1dXX45JNP0NXVhaKiImRlZWHixImYMmUKCgoKjjgfPUP6CASC4TNkMaooir63Mr0dWiyWIyZ2s8Ih3YmVRt5gJxujhsao0RlsGAsZaPK5xzdA9GH/ZzE6f6wwcHN7Bwt7H0P9LWH0W6OwZJPMezC61kiEKZoDeCpTdrtd74ny+/3w+/1QFEUfVmVfgvnzpQKqVveoDLOilBXaoVAIDQ0NqKys1F0JZWdnY+LEiRg/fjwKCgp0GytJEsLhMFRNZPF2dzBQ/pPAGgi6/1SGnj+9EJNtomdAgpTaL5/Ph66uLsiyjObmZlRXV8NsNmPmzJmYMWMGSktL9XnJCrOwiV6UTCaT/gxTsewJBGONIYvRaDSKUCikL1qhSklv6Kyho4orSB6SNsSZjHynskDPmW142W/2Xqg3IRn3l0yovI80yXy+ySYajep7hJu0hTzU6yfLsj4ak5GRAZvNBrvdDksKbwlKIobEoqItwoK2Rz3bqybLMrxeL6qqqnDgwAHIsgyHw6G7gsrKykJubq4+L5uG+qncmc1mXbgPBNloWZaTunp/JKF0k2hXmekD1B6Fw2F9h6WOjg60t7ejra0NNpsNM2bMwMSJE5GdnY2CggLk5eX1mddPz5KuI43SnFiBIF0ZshiNRCJ9ekYl7S2f3tBNJpNudEmskvETJI+Rzm9J68liBZiREDX6pgYinUh2o5RO+SdJki4gZG1fcF6MBoNB3YMHDbmOBTFK90v1hewi9eCxglTR5pe2tbXB6/UiEAjoabbb7cjJyUFOTg7sdjtM2p7qNHXBonk0GQqpmm/DgU2TxL0Iq9pC1GAwqPe0e71eZGVlYcaMGSgsLITFYtHLFV+nebvFHxcIBPEzZDFKvWE05ARtNSINWZDwZIdIRKVNLuy8u5HG6PnGCoNm0OPpNecbgsFgdB8jBS8sRgrKv6HmRapCNoJWKweDQUSjUZi0IWgSozQaAy2vLRYLrJpbuVTNCyqzbA8aCVIKp9EknkgkArfbDa/Xq7uzstlsyMzMhMVi0QW63+9HMBjUy99Q8mIovaljAYmZOiQxPZf8N5gRmmg0CpvNpu+ANRBUXtn/BQLB8BmyGCVjSj2jYObpUGOsMItaktFAC0YPKgNGDapR2FCRtJcbtheWwgaCGpzBxheMHiQ6w+FwHzFKQ9zhcFifK0liNJ7ewGRiJEapLJMgJdtJZVRiFuAEg0E9PyRtegYJdInxBtJfHewPOnc6wecnuBdgaPlELzL0f6yXAhgIUBZhVwSCxDBkMQqtd5St3GyjD25+DRlXwchD+c0+i5GEGlbeWPP/8+Hx3B9dZyjQtZIBlfmhpmsoDCf/xgKsXTExC0TYY9DsDXssVaEyS/YRjEBlX9ZNjCcBxHAzJ2niiupAIsoAe006f6IxOu9AYfR3vGFsfhNUfii+0TA8tWeUz3Rc4ubDUxyBQJA44hKj4MQBX1mFGB1dkpnnsYxyrHAM4/7i+U1/95FIqAFLBnxDmy7wdoNEGZj8VQ3EXapC6eHvl+6ZBKXKLLCBJkaNxHZUG4KmYWh2elQ85S/eepjK0JxQs7aols9Dyic27ZT/VPbYfKQRP/Y8RucQCATDI24xSlCl5MNiHROMPLxBHSmkfnoe+7t+PPcXj+GP5zrxEisfRoJkpitZ8I09H8aGs+UglfOBv19WaJMQJRRmAw4SP3x5V7npKmy8ePKBP386oGhTIGi43gjKP7IplK9G9Yryl/KKjcu+LAkEguExaDGKNDVe6QgNR400Erf162CJ5/7iLXtDvU68JLNhiif/UhkjcTYYUj0P2PSwIobvaRsIXtQmklTPw6HC5zn7N/vhBb9RPpBQJfhzJLPOCwTpzpDEKI+oiKmLysylYo0qb2CHEsYznOdvdG6jaxqFJROj68cKSyb89UeSWOlNdBgPG4c/zvZupSr8vfWXnliwUxdoyJg/DoNe5KMdlXHqTy9vNGWCFoIN9kWa8h/ciwF9BALB8Bm0GKXKDa4i8pWRGhoKp7+NGh8+LBEYnXe0wniM4gwUxubnUMOSgTRIYzzcexrsdXiGe92RxOiZGT0/o7B0g/KBfc78kDQdo3Apzp75ZCBJku7+jgQQLxhVbotbkzb3M6qtnqf/6cMPyfPlIt46km6weUZlhe2VJpdWfHzKcxaFmT5B5TOeXnyBQNA/gxKjZFjD4XCfykgfNh7/d7o3oqkIGdeRRhqEGKD7YL/jubd4GgBqjJIBXxdGkmSlKZmwDT2Yl19erIERCNTDFU95GkmoHPT09OiLaYwcqSuaKyswi5YikQhkWUaG5tifLfesuAI3ZzSeqRvJKq/JhoQlW2Z4qAyRSAVTxmKVQRKy/EuBQCAYPoMSo2AqJpiGw8iYUSVljxlV2pGqzEbnHa0wHqM4A4Wx+TlQGDjRFytef9frL4xHYspBf+dHjDIwFCh9Q6W/67LH+Hw0yjsiVlg898hfI9a5+Xh8nJGkv3tKZBj7DebFhdJOx9iwWGJjtJEkSd8chBbT0BxDundWWFJaVM3dksR4E+DTTXlndIwnVl7TPcSL0XmNGGy8RMKWl1hpVA0WLfG/McpvtiMm2elKFrHyLBbpmg+C5DJoMQqmkIrCJxgOQzV2RDzlrr9rsQ0Ne+54BE5/1+mPeNIkGB2RM1TYMjGUe01lO5uO5Xyg55TKzyPRpOPzFYwNhtTqso23QDBWoXLMfihcMDYYC88q3nKVynY2Ve9rOPB2gKe/Y+nG0ZJOQeoxJDEqEIwWyTKSybqO4Ogg3cpTvD1ngrGBeL6C0eJ/Af1hf+nva0w/AAAAAElFTkSuQmCC" + } + }, + "cell_type": "markdown", + "id": "89f2da3f", + "metadata": {}, + "source": [ + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "id": "b935639c", + "metadata": {}, + "source": [ + "#### Что такое язык программирования? \n", + "\n", + "Если мы хотим дать компьютеру какие-то указания, нужен язык программирования. Разных языков программирования существует очень много. Как и у разговорных языков, у всех языков программирования есть свои правила (синтаксис) и значения (семантика).\n", + "\n", + "Исходный код - это то, что пишут программисты на всех языках программирования.\n", + "\n", + "#### Как запустить исходный код? \n", + "\n", + "Существуют три основных способа перевода исходного кода в машинный код: \n", + "♦ компиляция; \n", + "♦ интерпретация; \n", + "♦ сочетание этих двух способов.\n", + "\n", + "Главное отличие:\n", + "\n", + "- Компилятор: переводит всю программу заранее → потом запускается быстро.\n", + "\n", + "- Интерпретатор: переводит «на ходу» → запуск проще, но работает медленнее.\n", + "\n", + "#### 1.5. Упражнения \n", + "1.5.1. Ответьте на вопросы \n", + "1 . Какие предметные области входят в Data Science? Что между ними общего и \n", + "в чем различие? Ответ: ИИ это сфера в которой основное внимание уделяется созданию интеллектуальных машин, способных работать и принимать решения как человек. Машинное обучения это инструмент для извлечения знаний из данных, Глубокое обучения это создание многослойных нейронных сетей в областях, \n", + "где требуется более продвинутый или быстрый анализ, а традиционное машинное обучение не справляется, Большие данные это работа с огромными объемами часто неструктурированных данных. Специфика этой сферы - инструменты и системы, способные выдерживать высокие нагрузки. Все они работают с данными: сбор, хранение, анализ, интерпретация. А главная отличия в масштабах и инструментах которыми мы пользуемся\n", + "2. Как вы понимаете термин «алгоритм» Ответ? Ответ: алгоритм это последовательная инструкция с помощью которой мы можем разделить на определённые шаги и этапы любую задачу\n", + "Как алгоритмы связаны с блок-схемами? Ответ: С помощью блок-схем можно визуализировать все шаги алгоритма \n", + "3. Какую программу можно назвать хорошей? Запишите все характеристики, какие \n", + "удастся придумать. Ответ: хорошая программа должна идеально решать свою задачу без ошибок и максимально правильно и быстро а ещё хорошая программа должна работать на разных устройствах с разными возможностями\n", + "4. Какой язык понимает компьютер? Ответ: Компьютер понимает машинный код состоящий из чисел двоичной системы счисления\n", + "5. Чем языки программирования отличаются от языков, на которых мы говорим? Ответ: естественный человеческий язык разнообразный и может быть двухсмысленным предназначен для коммуникации людей но язык программирования имеет строгий смысл и синтаксис предназначен для того чтобы давать компьютеру строгие инструкции\n", + "\n", + "1.5.2. Правда или ложь \n", + "1 . Машинное обучение -это инструмент для извлечения знаний из данных. *правда*\n", + "2. Глубокое обучение - это то же самое, что машинное обучение. *ложь*\n", + "3. Все инженеры-программисты также могут считаться специалистами по данным. *ложь*\n", + "4. Статистика- важный инструмент для специалистов по данным. *правда*\n", + "5. Компьютер может принимать решения, выходящие за рамки данных ему инструкций, подстраиваясь под изменения среды. *ложь*\n", + "6. Компьютеры понимают языки программирования «как есть». *ложь*\n", + "7. Некоторые языки программирования компилируются, некоторые интерпретируются, а некоторые используют и то и другое. *правда*\n", + "8. Все программы выполняются последовательно. *ложь*\n", + "9. В IDE есть встроенный текстовый редактор. *правда*\n", + "10. Компиляторы и интерпретаторы - это такие механизмы, наподобие привода \n", + "для компакт-дисков. *ложь*" + ] + }, + { + "attachments": { + "image-2.png": { + "image/png": "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" + }, + "image-3.png": { + "image/png": "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ytTnqKysxIEDB4CJRZg2mw15eXmwWCyoqanBG2+8MekfagAoLCzUTEHopYxSKGspYtdQlJWVoba2Vl04CkA9rv7+frjdbvj9fvz0pz9FXV2d5rHKGojq6mr1LJlly5ZhZGREfd02mw0HDhxAbm4umpqa0NjYqMZ27doFu92O9vZ2zfESZTuLEEKYfb/4bM83MjICAMjPz5dDKTH7+OZbPvaHMXrzWSwWCCHkZjLA4/Ggv78/bh1IOBzGo48+ipaWFlitVjz11FN48803pzWKkgo9faz386KX2fkOHToEAHjppZfkUErMPj5KjiMUREREZBgLCiKiFB04cCBudAITazSCwWDCRZxEc5VFCCGUIWcimruWLl065XA4zW4Wi0VumpXq6urirkRqFrOmVike11CYwOzjm2/52B/G6M2nZ359totdu6CMDvh8PrS3t6sjCb29vRlb05BpevpY7+dFr/mWj5LjlAcRzRmxUw3KTc3a29sxMjKi3jSstLQUly9fnnPFBNFMY0FBRHNG7J1RleICAP72t7/hn//8J6qqqtDb24vCwkLNXVCJyDgWFEQ0ZzmdThQXF6OlpQXbt29PeBErIjIHCwoimrNaW1tx4MABVFVVTevOpUQ0fSwoiIiIyDAWFERERGQYCwoiIiIyjAUFERERGcaCgoiIiAxjQUFEc4aee2jwwlZE6cGCgoiIiAxjQUFERESGsaAgIiIiw1hQEBERkWEsKIiIiMgwFhRERERkGAsKIiIiMowFBRERERlmEUKIYDAotxPRHLN69Wo0NDTIzTSHuFwuDA4Oys0Uw2azyU1kEosQQty6dQsAkJOTI8dTku35RkZGAAD5+flyKCVmH998y8f+MEZvPpfLJTclNDY2BgBYtGiRHErJ+Pg4AGDBggVyKCXzLd90+2OqolHv50Wv+ZaPkmNBYQKzj2++5WN/GGN2PvaHMWbnY38YY3Y+So5rKIiIiMgwFhRERERkGAsKIiIiMowFBRERERnGgoKIiIgMY0FBREREhrGgICIiIsNYUBAREZFhLCiIiIjIMBYUREREZBgLCiIiIjKMBQUREREZxoKCiIiIDLMIIYTcSERERDQdHKEgIiIiw1hQEBERkWEsKIiIiMgwFhRERERkGAsKIiIiMowFBRERERnGgoKIiIgMY0FBREREhrGgICIiIsNYUBAREZFhLCiIiIjIMBYUREREZBgLCiIiIjKMBQUREREZxoKCiIiIDPt/g6qDkjpG/WkAAAAASUVORK5CYII=" + }, + "image-4.png": { + "image/png": "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" + }, + "image-5.png": { + "image/png": "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" + }, + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "2eb08335", + "metadata": {}, + "source": [ + "1.5.3. Практические задания \n", + "1. Напишите алгоритм для расчета простых процентов от некоторой суммы.\n", + "// формула простых процентов: Interest = principal * rate * time / 100\n", + " INPUT principal — сумма денег\n", + " INPUT rate — процентная ставка (в процентах)\n", + " INPUT time — время (в годах)\n", + " \n", + " SET interest := principal * rate * time / 100\n", + " PRINT interest\n", + "END \n", + "\n", + "2. Напишите алгоритм для вычисления площади прямоугольника.\n", + "// формула площади прямоугольника area = width * height\n", + " INPUT width — ширина прямоугольника\n", + " INPUT height — высота прямоугольника\n", + " \n", + " SET area := width * height\n", + " PRINT area\n", + "END \n", + "\n", + "3. Напишите алгоритм вычисления периметра круга.\n", + "\n", + " INPUT radius — радиус круга\n", + " CONSTANT pi := 3.14159\n", + " \n", + " SET perimeter := 2 * pi * radius\n", + " PRINT perimeter\n", + "END \n", + "\n", + "4. Напишите алгоритм, который находит все простые числа меньше 100.\n", + "\n", + " SET limit := 100\n", + " CREATE list primes // пустой список, куда будем добавлять простые числа меньше 100\n", + "\n", + " FOR n FROM 2 TO limit - 1 DO\n", + " SET isPrime := TRUE\n", + " FOR d FROM 2 TO FLOOR(sqrt(n)) DO\n", + " IF n mod d = 0 THEN\n", + " SET isPrime := FALSE\n", + " BREAK inner loop\n", + " END IF\n", + " END FOR\n", + " IF isPrime THEN\n", + " APPEND n TO primes\n", + " END IF\n", + " END FOR\n", + "\n", + " PRINT primes\n", + "END \n", + "\n", + "5. Напишите алгоритм превращения предложения, написанного в верхнем регистре, в обычный для предложений регистр.\n", + "ALGORITHM NormalizeSentenceCase:\n", + " INPUT sentence — строка, все буквы в верхнем регистре\n", + "\n", + " // Привести всё в нижний регистр\n", + " SET lowerSentence := toLowerCase(sentence)\n", + "\n", + " // Сделать первую букву заглавной\n", + " IF lowerSentence NOT EMPTY THEN\n", + " SET firstChar := toUpperCase(first character of lowerSentence)\n", + " SET rest := substring of lowerSentence from position 2 to end\n", + " SET result := firstChar + rest\n", + " ELSE\n", + " SET result := lowerSentence\n", + " END IF\n", + "\n", + " PRINT result\n", + "END \n", + "\n", + "6. Составьте блок-схему приготовления льда из кипяченой воды с помощью холодильника.\n", + "\n", + "![image.png](attachment:image.png)\n", + "\n", + "7. Составьте блок-схему для нахождения суммы всех четных чисел меньше ста. \n", + "\n", + "![image-2.png](attachment:image-2.png)\n", + "\n", + "8. Составьте блок-схему для вычисления квадрата всех нечетных чисел от 1 до 15 \n", + "включительно.\n", + "\n", + "![image-3.png](attachment:image-3.png)\n", + "\n", + "9. Составьте блок-схему вывода таблицы умножения на 3. \n", + "\n", + "![image-4.png](attachment:image-4.png)\n", + "\n", + "10. Составьте блок-схему для расчета сложных процентов (с капитализацией).\n", + "\n", + "![image-5.png](attachment:image-5.png)" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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nlqmlqk3qTep/6T+k6pO4To75VdsuuPqxIkT6t133y02h04ikVDvvfdetbu7W5w1LSxZskQ9ceKE2KyqkseG6ZmfoihiExFlyVR+Jiie6fHyprW5c+finXfeEZtpmnn77beDedkzbA4ePDjp8uTGjRsntRGJZIogi55zc+fOxX//7/990jezw6a4uBgvvPCCrY+JvDYwMICioiLvip/2zUki8p6TIsiiJ6e6uhp79uwRm2ma2LNnD2KxmNg8JZTh4eGUSvf444/zlkY5rrm5GaOjo6aD+Y6Pj0NVVVe3CJGJlRmgViZvEGL35+3Hk/lPpgygDUAfcPoa9Ro8PGbv1kJO8oqCGJvpuDp58iQaGxvxu9/9TpxF08BNN92EXbt26V9kFMkcGzOUiSG1KFy011177e38W3tsp93scbp2sza7U67HPnTpIXR/3j3pVkrarYW6P+/GQ5cemhRnNjnJK065GFtdXY2rrrpK/30wTR8dHR246qqrUF1dPel1s/v6pp1U4Ronb2mU+3hLo8uCGHvLvi/Go3y74W1xVkYyeYMYa+e46uzsxJYtW7J23zhy56677sL27dvTXvaUOTZMP/PTKioRTT8X/+EiLv7DRbGZXIrFYsjLy8OTTz4pziKfPPnkk8jLy0tb+GSZFj8imp5GR0fxwQcf4IMPPsDo6Kg4m1x66qmn0NjYKDaTTxobG02vTE0l0+InXAklomni2LFjuHTpEi5duoRjx46Js8mluXPnYs+ePbjzzjvFWeSxO++8Ey+99FJWz/pgVfyIaHoqKirC3/zN3+Bv/uZvMHPmTHE2SXjggQdw9913p4zfS96qra3F3XffnfXCBxY/omCJxWKYM2cO5syZg2XLlomzSdK2bdvw9a9/Hffdd584i7Lsvvvuw5///GfPvmzJ4kdEZLBt2zbccsstWLhw4bQd7DmX9PT0oKqqCrfccot+px8vmBY/ftuTiMJs27Zt+MEPfoCqqio8/vjj4myaIo8//jiqqqrwf//v//XsjE9jWvyIiMLu7/7u7/CHP/wBo6OjuP7667F79+7A3QtvOvrss8+we/duXH/99RgdHcWZM2csR3DJJtPix297EhEB0WgU27Ztw6uvvorf/va3KC0txfe//30888wz4qKUwTPPPIPvf//7uOqqq/DLX/4Sr776KrZt24ZoNCou6gmO8BJCHOHlsiDGPvroowCAJ554QpyVkUzeIMZO9XF17tw5dHZ2oqurC52dnfjLX/6COXPmoLS01NX4krlsbGwMAwMDOH/+PK666irU1dUBE5eUjcz2s10ysSx+IcTid1kQY1n87PPiuDp37lzK/zExGIGqqrjiiisMS9rjV+zFixehqiqKi4vFWRlZ5bXzkwW7+9mMTCyLXwix+F0WxFgWP/t4XNkXtn2lJJPJlOK3c+dO5Ofnm74xUm5obm7G2NiY6S2NxsbGAMDVJRyZWO2LBG4OYpm8QYzV/jB18weqTN4gxvK4si9s+0r/wouqqlAnTgK3bds2+fYPnHJmEt80tddd5LSdiCgoJl32zCQXT40VRbF8Q88Um04u7qt0ZGK5r+zjZU/7eFzZF7Z9ZfpTByIiolzG4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKGjDA8Pm4/obEFmINHx8XGoqurq9hPZjJ01axaGh4fFZsBGbDq5uK/SkYnlvrIv3f0YM5HJG8RYHlf2hW1fzdBuc6MRb3+jzTNbzqpdnMyWFx8b483ajW1u4u22i4+tlnPaLj62Ws5IjBXb3DyvGGu2nNW/tcd22s0ep2s3a7M7hTHWbbzbOMY6mxhrf/Irlrc0mth5VrshU2w6ubiv0pGJ5b6yj7c0so/HlX1h21f8zI+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEKHxY+IiEJHGRgYMB/R2UIymQQAVwOJjo2NAYCr209kM7a0tBQDAwNiM2AjNp1c3FfpyMRyX9m3c+dOAMCmTZvEWRnJ5A1iLI8r+8K2r/QzP1VVoVrc2cBpuxtW+a3akSa/0/ZMzOKs1suqHRbPgzTtblg911Sul1U7EVFQ8JZGvKVRCr9iua/s4y2N7ONxZV/Y9hU/8yMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBh8SMiotBRhoeHzUd0tiAzkOj4+DhUVXV1+4lsxs6aNQuPPfaY2AwY7oYwY4bzvxPGx8cBAHl5eeKsjGTyBjGW+8q+rq4u3HHHHdi6das4K6NMfSGdIMbm4vtVOjKxYdtXSjKZVGG4TY2iKOIyUFVVb08mk1BVFbNmzUpptxMv3nvJKt6sXXtzNG6k2XJm8cY3VrPltfujmbl06RIAuHqTErfXCZm80z3W+PpouK/sGxsbQ1NTk6s3KZn9HMTYsN2jTiY2bPuKtzTKQCaW+8o+7iv7uK/s476yL2z7yvmfnURERAHH4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHD4kdERKHz/wOWIEtLxtbUZwAAAABJRU5ErkJggg==" + } + }, + "cell_type": "markdown", + "id": "8f398a1b", + "metadata": {}, + "source": [ + "#### 1.5.4. Изучите самостоятельно \n", + "1. Что думают ученые о будущем Data Science? Изучите материалы на эту тему \n", + "и поделитесь ими с друзьями. Ответ: Ученые предвидят, что будущее Data Science будет характеризоваться увеличением автоматизации, что позволит специалистам сосредоточиться на сложных проблемах, этические вызовы и вопросы регулирования станут центральными. \n", + "2. Составьте список разных IDE для языка Python. Узнайте, чем они похожи и чем \n", + "отличаются. Ответ: Visual Studio code, Pycharm. одни из самых популярных сред разработки вс код более всесторонний а pycharm удобен именно для фреймворка Django\n", + "3. Составьте список всех компилируемых и интерпретируемых языков. Найдите \n", + "ситуации, в которых каждый из них будет полезнее в использовании, чем \n", + "остальные. Ответ: Компилируемые языки С++, C Ситуации, в которых компилируемые языки полезнее: Компилируемые языки полезны в случаях, когда производительность и скорость имеют решающее значение. Интерпретируемые языки: Python, JavaScript\n", + "Ситуации, в которых интерпретируемые языки полезнее:\n", + "Интерпретируемые языки предпочтительны, когда скорость разработки, гибкость и кросс-платформенность важнее, чем чистая производительность.\n", + "4. Создайте алгоритмы для решения некоторых распространенных задач, с которыми вы сталкиваетесь в повседневной жизни. Составьте для них блок-схемы.\n", + "\n", + "![image.png](attachment:image.png)" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/made-easy/fundamentals_of_programming_and_intro_to_ds.py b/python/made-easy/fundamentals_of_programming_and_intro_to_ds.py new file mode 100644 index 00000000..a67f2911 --- /dev/null +++ b/python/made-easy/fundamentals_of_programming_and_intro_to_ds.py @@ -0,0 +1,215 @@ +"""Basics of programming and introducing DS note page 26-47.""" + +# #### Что такое Data Science? +# +# Data Science - это научная дисциплина, которая включает в себя извлечение ин формации из огромных объемов данных с использованием различных научных методов, алгоритмов и процессов. + +# ![image.png](attachment:image.png) + +# #### Зачем нам Data Science? +# +# Data Science как наука, занимающаяся изучением данных, помогает лучше прини мать решения, обнаруживать закономерности, составлять прогнозы, выполнять анализ и создавать визуальное представление из необработанных данных. Эта наука помогает нам: +# +# - задавать правильные вопросы; +# - находить основную причину проблемы; +# - находить закономерности среди, на первый взгляд, хаотичных необработанных +# данных; +# - создавать модели для предиктивного анализа; +# - визуализировать и отображать результаты с помощью графиков, информационных панелей и т. д.; +# - наделять машины интеллектом; +# - определять лояльность клиентов с помощью анализа настроений; +# - принимать более качественные и быстрые решения; +# - рекомендовать правильный продукт нужному клиенту для развития нашего бизнеса. +# +# #### Чем занимается специалист по Data Science? +# +# специалист по анализу данных решает бизнес задачи с помощью следующих шагов: +# +# ♦ задает правильные вопросы, чтобы понять проблему; +# ♦ собирает данные из нескольких источников - корпоративные данные, общедоступные данные и т. д.; +# ♦ обрабатывает сырые данные и преобразует их в формат, подходящий для анализа; +# ♦ загружает данные в аналитическую систему - алгоритм машинного обучения или статистическая модель; +# ♦ подготавливает результаты и идеи, которые можно изложить заинтересованным сторонам. +# Всё это позволяет решить немало проблем, некоторые из них приведены далее: +# ♦ обнаружение мошенничества и выявление аномалий, например изменений схемы снятия или расходования средств с кредитной карты клиента; +# ♦ целевой и персонализированный маркетинг - персональные рассылки по электронной почте, системы рекомендаций на сайтах магазинов; +# ♦ метрические прогнозы - показатели эффективности, качества рекламных кампаний и других мероприятий; +# ♦ оценка принятия решений - обработка больших объемов данных и помощь в принятии решения, например о выдаче кредита на основе кредитных оценок; +# ♦ прогнозирующее моделирование - прогнозирование столкновения метеорита с землей на основе астрономических данных. +# +# +# #### Профессии в области Data Science: +# +# - специалист по данным; +# - дата-инженер; +# - аналитик данных; +# - статистик; +# - архитектор данных; +# - администратор данных; +# - бизнес-аналитик; +# - менеджер данных/аналитики. +# +# +# #### Основы компьютерного программирования +# +# Что такое программирование? +# программирование - это то, как мы общаемся с компьютером. Программу определяют инструкции, которые являются конкретными и последовательными. +# И точно так же, как рецепт, когда программа составлена правильно, нас порадует конечный результат. +# Чтобы заставить компьютер сделать что-либо, инструкции должны быть записаны в виде компьютерной программы. В компьютерной программе вы должны последовательно указать, что именно вы от него хотите. Затем компьютер запускает программу и выполняет ее шаг за шагом, чтобы сделать требуемую задачу. +# +# +# #### Компьютерный алгоритм +# +# алгоритм - это конечная последовательность четко определенных, реализуемых компьютером инструкций для решения какой-то проблемы или для выполнения вычислений. Алгоритмы всегда однозначны и используются для вычислений, обработки данных, автоматизированных решений и других задач. +# +# Алгоритмы можно изображать в графической форме с использованием определенных обозначений. Полученное изображение называется блок-схемой. + +# ![image.png](attachment:image.png) + +# #### Что такое язык программирования? +# +# Если мы хотим дать компьютеру какие-то указания, нужен язык программирования. Разных языков программирования существует очень много. Как и у разговорных языков, у всех языков программирования есть свои правила (синтаксис) и значения (семантика). +# +# Исходный код - это то, что пишут программисты на всех языках программирования. +# +# #### Как запустить исходный код? +# +# Существуют три основных способа перевода исходного кода в машинный код: +# ♦ компиляция; +# ♦ интерпретация; +# ♦ сочетание этих двух способов. +# +# Главное отличие: +# +# - Компилятор: переводит всю программу заранее → потом запускается быстро. +# +# - Интерпретатор: переводит «на ходу» → запуск проще, но работает медленнее. +# +# #### 1.5. Упражнения +# 1.5.1. Ответьте на вопросы +# 1 . Какие предметные области входят в Data Science? Что между ними общего и +# в чем различие? Ответ: ИИ это сфера в которой основное внимание уделяется созданию интеллектуальных машин, способных работать и принимать решения как человек. Машинное обучения это инструмент для извлечения знаний из данных, Глубокое обучения это создание многослойных нейронных сетей в областях, +# где требуется более продвинутый или быстрый анализ, а традиционное машинное обучение не справляется, Большие данные это работа с огромными объемами часто неструктурированных данных. Специфика этой сферы - инструменты и системы, способные выдерживать высокие нагрузки. Все они работают с данными: сбор, хранение, анализ, интерпретация. А главная отличия в масштабах и инструментах которыми мы пользуемся +# 2. Как вы понимаете термин «алгоритм» Ответ? Ответ: алгоритм это последовательная инструкция с помощью которой мы можем разделить на определённые шаги и этапы любую задачу +# Как алгоритмы связаны с блок-схемами? Ответ: С помощью блок-схем можно визуализировать все шаги алгоритма +# 3. Какую программу можно назвать хорошей? Запишите все характеристики, какие +# удастся придумать. Ответ: хорошая программа должна идеально решать свою задачу без ошибок и максимально правильно и быстро а ещё хорошая программа должна работать на разных устройствах с разными возможностями +# 4. Какой язык понимает компьютер? Ответ: Компьютер понимает машинный код состоящий из чисел двоичной системы счисления +# 5. Чем языки программирования отличаются от языков, на которых мы говорим? Ответ: естественный человеческий язык разнообразный и может быть двухсмысленным предназначен для коммуникации людей но язык программирования имеет строгий смысл и синтаксис предназначен для того чтобы давать компьютеру строгие инструкции +# +# 1.5.2. Правда или ложь +# 1 . Машинное обучение -это инструмент для извлечения знаний из данных. *правда* +# 2. Глубокое обучение - это то же самое, что машинное обучение. *ложь* +# 3. Все инженеры-программисты также могут считаться специалистами по данным. *ложь* +# 4. Статистика- важный инструмент для специалистов по данным. *правда* +# 5. Компьютер может принимать решения, выходящие за рамки данных ему инструкций, подстраиваясь под изменения среды. *ложь* +# 6. Компьютеры понимают языки программирования «как есть». *ложь* +# 7. Некоторые языки программирования компилируются, некоторые интерпретируются, а некоторые используют и то и другое. *правда* +# 8. Все программы выполняются последовательно. *ложь* +# 9. В IDE есть встроенный текстовый редактор. *правда* +# 10. Компиляторы и интерпретаторы - это такие механизмы, наподобие привода +# для компакт-дисков. *ложь* + +# 1.5.3. Практические задания +# 1. Напишите алгоритм для расчета простых процентов от некоторой суммы. +# // формула простых процентов: Interest = principal * rate * time / 100 +# INPUT principal — сумма денег +# INPUT rate — процентная ставка (в процентах) +# INPUT time — время (в годах) +# +# SET interest := principal * rate * time / 100 +# PRINT interest +# END +# +# 2. Напишите алгоритм для вычисления площади прямоугольника. +# // формула площади прямоугольника area = width * height +# INPUT width — ширина прямоугольника +# INPUT height — высота прямоугольника +# +# SET area := width * height +# PRINT area +# END +# +# 3. Напишите алгоритм вычисления периметра круга. +# +# INPUT radius — радиус круга +# CONSTANT pi := 3.14159 +# +# SET perimeter := 2 * pi * radius +# PRINT perimeter +# END +# +# 4. Напишите алгоритм, который находит все простые числа меньше 100. +# +# SET limit := 100 +# CREATE list primes // пустой список, куда будем добавлять простые числа меньше 100 +# +# FOR n FROM 2 TO limit - 1 DO +# SET isPrime := TRUE +# FOR d FROM 2 TO FLOOR(sqrt(n)) DO +# IF n mod d = 0 THEN +# SET isPrime := FALSE +# BREAK inner loop +# END IF +# END FOR +# IF isPrime THEN +# APPEND n TO primes +# END IF +# END FOR +# +# PRINT primes +# END +# +# 5. Напишите алгоритм превращения предложения, написанного в верхнем регистре, в обычный для предложений регистр. +# ALGORITHM NormalizeSentenceCase: +# INPUT sentence — строка, все буквы в верхнем регистре +# +# // Привести всё в нижний регистр +# SET lowerSentence := toLowerCase(sentence) +# +# // Сделать первую букву заглавной +# IF lowerSentence NOT EMPTY THEN +# SET firstChar := toUpperCase(first character of lowerSentence) +# SET rest := substring of lowerSentence from position 2 to end +# SET result := firstChar + rest +# ELSE +# SET result := lowerSentence +# END IF +# +# PRINT result +# END +# +# 6. Составьте блок-схему приготовления льда из кипяченой воды с помощью холодильника. +# +# ![image.png](attachment:image.png) +# +# 7. Составьте блок-схему для нахождения суммы всех четных чисел меньше ста. +# +# ![image-2.png](attachment:image-2.png) +# +# 8. Составьте блок-схему для вычисления квадрата всех нечетных чисел от 1 до 15 +# включительно. +# +# ![image-3.png](attachment:image-3.png) +# +# 9. Составьте блок-схему вывода таблицы умножения на 3. +# +# ![image-4.png](attachment:image-4.png) +# +# 10. Составьте блок-схему для расчета сложных процентов (с капитализацией). +# +# ![image-5.png](attachment:image-5.png) + +# #### 1.5.4. Изучите самостоятельно +# 1. Что думают ученые о будущем Data Science? Изучите материалы на эту тему +# и поделитесь ими с друзьями. Ответ: Ученые предвидят, что будущее Data Science будет характеризоваться увеличением автоматизации, что позволит специалистам сосредоточиться на сложных проблемах, этические вызовы и вопросы регулирования станут центральными. +# 2. Составьте список разных IDE для языка Python. Узнайте, чем они похожи и чем +# отличаются. Ответ: Visual Studio code, Pycharm. одни из самых популярных сред разработки вс код более всесторонний а pycharm удобен именно для фреймворка Django +# 3. Составьте список всех компилируемых и интерпретируемых языков. Найдите +# ситуации, в которых каждый из них будет полезнее в использовании, чем +# остальные. Ответ: Компилируемые языки С++, C Ситуации, в которых компилируемые языки полезнее: Компилируемые языки полезны в случаях, когда производительность и скорость имеют решающее значение. Интерпретируемые языки: Python, JavaScript +# Ситуации, в которых интерпретируемые языки полезнее: +# Интерпретируемые языки предпочтительны, когда скорость разработки, гибкость и кросс-платформенность важнее, чем чистая производительность. +# 4. Создайте алгоритмы для решения некоторых распространенных задач, с которыми вы сталкиваетесь в повседневной жизни. Составьте для них блок-схемы. +# +# ![image.png](attachment:image.png) diff --git a/python/made-easy/introducing_to_python.ipynb b/python/made-easy/introducing_to_python.ipynb new file mode 100644 index 00000000..c6175b5c --- /dev/null +++ b/python/made-easy/introducing_to_python.ipynb @@ -0,0 +1,280 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "22fe06e5", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Summary of the Chapter 2 Introduction to Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "9ff40935", + "metadata": {}, + "source": [ + "\n", + "---\n", + "\n", + "# Конспект по Python\n", + "\n", + "## Глава 2. Введение в Python\n", + "\n", + "### 2.1. Что такое Python?\n", + "\n", + "* Python — это **интерпретируемый, высокоуровневый язык программирования**, созданный для простоты и удобства.\n", + "* Используется в разных областях: веб-разработка, анализ данных, машинное обучение, автоматизация, научные вычисления.\n", + "\n", + "#### 2.1.1. Почему именно Python?\n", + "\n", + "* Универсальный и гибкий язык.\n", + "* Богатая экосистема библиотек.\n", + "* Широкое сообщество и множество готовых решений.\n", + "* Подходит как для новичков, так и для профессионалов.\n", + "\n", + "#### 2.1.2. Появление Python\n", + "\n", + "* Создан Гвидо ван Россумом в конце 1980-х.\n", + "* Первый релиз — 1991 год.\n", + "* Название связано не со змеёй а с британским комедийным шоу *Monty Python*.\n", + "\n", + "#### 2.1.3. Python и другие языки программирования\n", + "\n", + "* Проще и короче по синтаксису, чем C, C++ или Java.\n", + "* Не требует компиляции, в отличие от C/Java.\n", + "* Сильнее ориентирован на читаемость кода.\n", + "\n", + "#### 2.1.4. Философия Python\n", + "\n", + "* Основана на **«The Zen of Python» (PEP 20)**:\n", + "\n", + " * Красивое лучше, чем уродливое.\n", + " * Простое лучше, чем сложное.\n", + " * Явное лучше, чем неявное.\n", + " * Читаемость имеет значение.\n", + "\n", + "---\n", + "\n", + "### 2.2. Преимущества Python\n", + "\n", + "#### 2.2.1. Простота\n", + "\n", + "* Синтаксис близок к естественному языку.\n", + "\n", + "#### 2.2.2. Лёгкость в изучении\n", + "\n", + "* Подходит для начинающих, не требует глубоких знаний программирования.\n", + "\n", + "#### 2.2.3. Свободный и открытый исходный код\n", + "\n", + "* Бесплатен и развивается сообществом.\n", + "\n", + "#### 2.2.4. Высокоуровневость\n", + "\n", + "* Меньше деталей низкоуровневой реализации.\n", + "\n", + "#### 2.2.5. Портативность\n", + "\n", + "* Работает на Windows, Linux, macOS, Android и других ОС.\n", + "\n", + "#### 2.2.6. Интерпретируемость\n", + "\n", + "* Код выполняется построчно без компиляции.\n", + "\n", + "#### 2.2.7. Интерпретаторы Python\n", + "\n", + "* **IPython** — расширенная интерактивная оболочка.\n", + "* **CPython** — основной и самый распространённый интерпретатор.\n", + "* **IronPython** — версия для .NET.\n", + "* **Jython** — для JVM (Java).\n", + "* **PyPy** — ускоренная версия Python с JIT-компиляцией.\n", + "* **PythonNet** — интеграция с .NET.\n", + "* **Stackless Python** — облегчённый интерпретатор с поддержкой многозадачности.\n", + "\n", + "#### 2.2.8. Объектно-ориентированность\n", + "\n", + "* Всё в Python — объект.\n", + "* Поддержка классов, наследования, полиморфизма.\n", + "\n", + "#### 2.2.9. Расширяемость\n", + "\n", + "* Можно подключать модули на C, C++, Java и других языках.\n", + "\n", + "#### 2.2.10. Встраиваемость\n", + "\n", + "* Python можно встраивать внутрь других программ (например, игр).\n", + "\n", + "#### 2.2.11. Внушительные библиотеки\n", + "\n", + "* Стандартная библиотека: работа с файлами, сетью, регулярными выражениями и др.\n", + "* Внешние библиотеки: NumPy, Pandas, TensorFlow, Flask, Django и тысячи других.\n", + "\n", + "---\n", + "\n", + "## Глава 3. Основы Python\n", + "\n", + "### 3.1. Запуск Python\n", + "\n", + "* Возможные способы:\n", + "\n", + " * В консоли (интерактивная оболочка).\n", + " * Через скрипты `.py`.\n", + " * Через IDE и Jupyter Notebook.\n", + "\n", + "### 3.1.1. Использование Spyder IDE\n", + "\n", + "* IDE из Anaconda.\n", + "* Поддержка отладки, работы с переменными, удобный редактор кода.\n", + "\n", + "### 3.1.2. Использование Jupyter Notebook\n", + "\n", + "* Интерактивная среда для кода и текста.\n", + "* Удобно для обучения, анализа данных, презентации результатов.\n", + "* Поддержка кода, Markdown, визуализаций.\n", + "\n", + "---\n", + "\n", + "**Итоговый вывод:**\n", + "Python ценят за простоту, мощь, огромную экосистему библиотек и универсальность. Его легко освоить и можно использовать почти в любой сфере IT.\n", + "\n", + "---\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "a0cc8df7", + "metadata": {}, + "source": [ + "### 2.12. Упражнения \n", + "#### 2.12.1. Ответьте на вопросы \n", + "* 1 . Python - это программное обеспечение с открытым исходным кодом. Это то же самое, что и бесплатное ПО?\n", + "\n", + "---\n", + "\n", + "Нет. Бесплатное ПО (freeware) может не давать доступ к исходному коду.\n", + "\n", + "Open Source (открытый исходный код) позволяет изучать, изменять и распространять программу.\n", + "\n", + "---\n", + "\n", + "* 2. У всех ли бесплатных программ открытый исходный код? А если нет, то в чем разница?\n", + "\n", + "---\n", + "\n", + "Не у всех. Бесплатные программы можно использовать без оплаты, но их код скрыт.\n", + "\n", + "Открытые программы (open source) дают право изменять код и делиться им.\n", + "\n", + "---\n", + "\n", + "* 3. Python поддерживает динамическую типизацию. Что это такое?\n", + "\n", + "---\n", + "\n", + "Тип переменной определяется во время выполнения программы, а не заранее.\n", + "\n", + "---\n", + "\n", + "* 4. Назовите 5 самых популярных языков программирования для специалистов по анализу данных.\n", + "\n", + "---\n", + "\n", + "python, R, SQL, C++, java, matlab\n", + "\n", + "---\n", + "\n", + "* 5. В чем заключается преимущество Python по сравнению с языком С?\n", + "\n", + "---\n", + "\n", + "* Более простой и читаемый синтаксис.\n", + "\n", + "* Быстрая разработка.\n", + "\n", + "* Огромные библиотеки для анализа данных и машинного обучения.\n", + "\n", + "* Не требует ручного управления памятью.\n", + "\n", + "---\n", + "\n", + "* 6. Python портативен. Что в этом контексте означает «портативность»?\n", + "\n", + "---\n", + "\n", + "Код Python можно запустить на разных операционных системах (Windows, Linux, macOS) без изменений или с минимальными изменениями.\n", + "\n", + "---\n", + "\n", + "* 7. В чем разница между «расширяемым» и «встраиваемым» языком?\n", + "\n", + "---\n", + "\n", + "Расширяемый → можно писать модули и расширять Python кодом на других языках (например, C/C++).\n", + "\n", + "Встраиваемый → Python можно встроить внутрь другой программы (например, в игру, чтобы писать скрипты).\n", + "\n", + "---\n", + "\n", + "* 8. В чем смысл IDE? Чем она отличается от командной строки?\n", + "\n", + "---\n", + "\n", + "IDE (интегрированная среда разработки): редактор кода, подсветка синтаксиса, отладка, запуск программ.\n", + "\n", + "Командная строка: минимальная среда, где вводятся команды для запуска кода.\n", + "\n", + "---\n", + "\n", + "* 9. Как открыть существующий документ Jupyter Notebook? Чем эта процедура отличается от открытия РDF-файла или текстового файла?\n", + "\n", + "---\n", + "\n", + "Открыть можно через команду jupyter notebook в терминале и выбор файла в браузере.\n", + "\n", + "PDF или TXT открываются просто как документ для чтения.\n", + "\n", + "Jupyter Notebook открывается как интерактивная среда, где можно запускать код\n", + "\n", + "---\n", + "\n", + "* 10. В чем разница между «ячейками разметки Markdown» и «ячейками кода» в Jupyter Notebook? Для чего они нужны?\n", + "\n", + "---\n", + "\n", + "Ячейки кода → содержат исполняемый Python-код.\n", + "\n", + "Markdown-ячейки → содержат текст с разметкой (заголовки, списки, формулы).\n", + "\n", + "Вместе они позволяют делать интерактивные учебные материалы, отчёты и проекты.\n", + "\n", + "---\n", + "\n", + "\n", + "\n", + "#### 2.12.2. Правда или ложь \n", + "* 1 . Язык программирования Python был назван в честь змеи питон. ложь\n", + "* 2. Python - это высокоуровневый язык общего назначения. правда\n", + "* 3. Python компилируется и не интерпретируется. ложь\n", + "* 4. В Python команда два + два вернет Четыре. ложь\n", + "* 5. Консоль IPython аналогична окну командной строки. правда\n", + "* 6. Графики, выводимые в документе Jupyter Notebook, отображаются внутри \n", + "самого документа. правда\n", + "* 7. В комплекте с пакетом Aлaconda идут браузеры Chrome и Firefox. ложь\n", + "* 8. «Простое лучше, чем сложное» - это одна из философий Python. правда\n", + "* 9. Аббревиатура FLOSS означает «Free/Libre and Open Source Software». правда\n", + "* 10. Python поддерживает ТОЛЬКО объектно-ориентированное программирование.ложь\n", + "\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/made-easy/introducing_to_python.py b/python/made-easy/introducing_to_python.py new file mode 100644 index 00000000..1a453658 --- /dev/null +++ b/python/made-easy/introducing_to_python.py @@ -0,0 +1,250 @@ +"""Summary of the Chapter 2 Introduction to Python.""" + +# +# --- +# +# # Конспект по Python +# +# ## Глава 2. Введение в Python +# +# ### 2.1. Что такое Python? +# +# * Python — это **интерпретируемый, высокоуровневый язык программирования**, созданный для простоты и удобства. +# * Используется в разных областях: веб-разработка, анализ данных, машинное обучение, автоматизация, научные вычисления. +# +# #### 2.1.1. Почему именно Python? +# +# * Универсальный и гибкий язык. +# * Богатая экосистема библиотек. +# * Широкое сообщество и множество готовых решений. +# * Подходит как для новичков, так и для профессионалов. +# +# #### 2.1.2. Появление Python +# +# * Создан Гвидо ван Россумом в конце 1980-х. +# * Первый релиз — 1991 год. +# * Название связано не со змеёй а с британским комедийным шоу *Monty Python*. +# +# #### 2.1.3. Python и другие языки программирования +# +# * Проще и короче по синтаксису, чем C, C++ или Java. +# * Не требует компиляции, в отличие от C/Java. +# * Сильнее ориентирован на читаемость кода. +# +# #### 2.1.4. Философия Python +# +# * Основана на **«The Zen of Python» (PEP 20)**: +# +# * Красивое лучше, чем уродливое. +# * Простое лучше, чем сложное. +# * Явное лучше, чем неявное. +# * Читаемость имеет значение. +# +# --- +# +# ### 2.2. Преимущества Python +# +# #### 2.2.1. Простота +# +# * Синтаксис близок к естественному языку. +# +# #### 2.2.2. Лёгкость в изучении +# +# * Подходит для начинающих, не требует глубоких знаний программирования. +# +# #### 2.2.3. Свободный и открытый исходный код +# +# * Бесплатен и развивается сообществом. +# +# #### 2.2.4. Высокоуровневость +# +# * Меньше деталей низкоуровневой реализации. +# +# #### 2.2.5. Портативность +# +# * Работает на Windows, Linux, macOS, Android и других ОС. +# +# #### 2.2.6. Интерпретируемость +# +# * Код выполняется построчно без компиляции. +# +# #### 2.2.7. Интерпретаторы Python +# +# * **IPython** — расширенная интерактивная оболочка. +# * **CPython** — основной и самый распространённый интерпретатор. +# * **IronPython** — версия для .NET. +# * **Jython** — для JVM (Java). +# * **PyPy** — ускоренная версия Python с JIT-компиляцией. +# * **PythonNet** — интеграция с .NET. +# * **Stackless Python** — облегчённый интерпретатор с поддержкой многозадачности. +# +# #### 2.2.8. Объектно-ориентированность +# +# * Всё в Python — объект. +# * Поддержка классов, наследования, полиморфизма. +# +# #### 2.2.9. Расширяемость +# +# * Можно подключать модули на C, C++, Java и других языках. +# +# #### 2.2.10. Встраиваемость +# +# * Python можно встраивать внутрь других программ (например, игр). +# +# #### 2.2.11. Внушительные библиотеки +# +# * Стандартная библиотека: работа с файлами, сетью, регулярными выражениями и др. +# * Внешние библиотеки: NumPy, Pandas, TensorFlow, Flask, Django и тысячи других. +# +# --- +# +# ## Глава 3. Основы Python +# +# ### 3.1. Запуск Python +# +# * Возможные способы: +# +# * В консоли (интерактивная оболочка). +# * Через скрипты `.py`. +# * Через IDE и Jupyter Notebook. +# +# ### 3.1.1. Использование Spyder IDE +# +# * IDE из Anaconda. +# * Поддержка отладки, работы с переменными, удобный редактор кода. +# +# ### 3.1.2. Использование Jupyter Notebook +# +# * Интерактивная среда для кода и текста. +# * Удобно для обучения, анализа данных, презентации результатов. +# * Поддержка кода, Markdown, визуализаций. +# +# --- +# +# **Итоговый вывод:** +# Python ценят за простоту, мощь, огромную экосистему библиотек и универсальность. Его легко освоить и можно использовать почти в любой сфере IT. +# +# --- +# +# + +# ### 2.12. Упражнения +# #### 2.12.1. Ответьте на вопросы +# * 1 . Python - это программное обеспечение с открытым исходным кодом. Это то же самое, что и бесплатное ПО? +# +# --- +# +# Нет. Бесплатное ПО (freeware) может не давать доступ к исходному коду. +# +# Open Source (открытый исходный код) позволяет изучать, изменять и распространять программу. +# +# --- +# +# * 2. У всех ли бесплатных программ открытый исходный код? А если нет, то в чем разница? +# +# --- +# +# Не у всех. Бесплатные программы можно использовать без оплаты, но их код скрыт. +# +# Открытые программы (open source) дают право изменять код и делиться им. +# +# --- +# +# * 3. Python поддерживает динамическую типизацию. Что это такое? +# +# --- +# +# Тип переменной определяется во время выполнения программы, а не заранее. +# +# --- +# +# * 4. Назовите 5 самых популярных языков программирования для специалистов по анализу данных. +# +# --- +# +# python, R, SQL, C++, java, matlab +# +# --- +# +# * 5. В чем заключается преимущество Python по сравнению с языком С? +# +# --- +# +# * Более простой и читаемый синтаксис. +# +# * Быстрая разработка. +# +# * Огромные библиотеки для анализа данных и машинного обучения. +# +# * Не требует ручного управления памятью. +# +# --- +# +# * 6. Python портативен. Что в этом контексте означает «портативность»? +# +# --- +# +# Код Python можно запустить на разных операционных системах (Windows, Linux, macOS) без изменений или с минимальными изменениями. +# +# --- +# +# * 7. В чем разница между «расширяемым» и «встраиваемым» языком? +# +# --- +# +# Расширяемый → можно писать модули и расширять Python кодом на других языках (например, C/C++). +# +# Встраиваемый → Python можно встроить внутрь другой программы (например, в игру, чтобы писать скрипты). +# +# --- +# +# * 8. В чем смысл IDE? Чем она отличается от командной строки? +# +# --- +# +# IDE (интегрированная среда разработки): редактор кода, подсветка синтаксиса, отладка, запуск программ. +# +# Командная строка: минимальная среда, где вводятся команды для запуска кода. +# +# --- +# +# * 9. Как открыть существующий документ Jupyter Notebook? Чем эта процедура отличается от открытия РDF-файла или текстового файла? +# +# --- +# +# Открыть можно через команду jupyter notebook в терминале и выбор файла в браузере. +# +# PDF или TXT открываются просто как документ для чтения. +# +# Jupyter Notebook открывается как интерактивная среда, где можно запускать код +# +# --- +# +# * 10. В чем разница между «ячейками разметки Markdown» и «ячейками кода» в Jupyter Notebook? Для чего они нужны? +# +# --- +# +# Ячейки кода → содержат исполняемый Python-код. +# +# Markdown-ячейки → содержат текст с разметкой (заголовки, списки, формулы). +# +# Вместе они позволяют делать интерактивные учебные материалы, отчёты и проекты. +# +# --- +# +# +# +# #### 2.12.2. Правда или ложь +# * 1 . Язык программирования Python был назван в честь змеи питон. ложь +# * 2. Python - это высокоуровневый язык общего назначения. правда +# * 3. Python компилируется и не интерпретируется. ложь +# * 4. В Python команда два + два вернет Четыре. ложь +# * 5. Консоль IPython аналогична окну командной строки. правда +# * 6. Графики, выводимые в документе Jupyter Notebook, отображаются внутри +# самого документа. правда +# * 7. В комплекте с пакетом Aлaconda идут браузеры Chrome и Firefox. ложь +# * 8. «Простое лучше, чем сложное» - это одна из философий Python. правда +# * 9. Аббревиатура FLOSS означает «Free/Libre and Open Source Software». правда +# * 10. Python поддерживает ТОЛЬКО объектно-ориентированное программирование.ложь +# +# diff --git a/python/makarov/chapter_01_variables.ipynb b/python/makarov/chapter_01_variables.ipynb new file mode 100644 index 00000000..ac07108c --- /dev/null +++ b/python/makarov/chapter_01_variables.ipynb @@ -0,0 +1,415 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "id": "5d34860b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Variables and basic operations with them.'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Variables and basic operations with them.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "489b1702", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, World!\n" + ] + } + ], + "source": [ + "# defining a variable\n", + "my_variable = \"Hello, World!\"\n", + "\n", + "# printing the variable\n", + "print(my_variable)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "62bfea0c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 2 3\n" + ] + } + ], + "source": [ + "# In Python, you can assign different values to several variables at once\n", + "x_axis, y_axis, z_axis = 1, 2, 3\n", + "print(x_axis, y_axis, z_axis)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6a86c546", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0 0\n" + ] + } + ], + "source": [ + "# as well as assign the same value to multiple variables\n", + "x_axis = y_axis = z_axis = 0\n", + "print(x_axis, y_axis, z_axis)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69de95a6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fruit vegetables dairy\n" + ] + } + ], + "source": [ + "# each item in the list can be \"unpacked\" into variables\n", + "\n", + "products_list = [\"fruit\", \"vegetables\", \"dairy\"]\n", + "category_1, category_2, category_3 = products_list\n", + "\n", + "print(category_1, category_2, category_3)" + ] + }, + { + "cell_type": "markdown", + "id": "4d45527c", + "metadata": {}, + "source": [ + "## Automatic data type detection (dynamic typing) " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "b09cd7f6", + "metadata": {}, + "outputs": [], + "source": [ + "customer_name = \"John Doe\" # string variable\n", + "loan_amount = 25000.75 # float variable\n", + "years = 5 # integer variable" + ] + }, + { + "cell_type": "markdown", + "id": "0c9087b2", + "metadata": {}, + "source": [ + "## How to find out the type of a variable in Python?" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "98b7f61a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# recognize the type of variables from the previous example\n", + "print(type(customer_name))\n", + "print(type(loan_amount))\n", + "print(type(years))" + ] + }, + { + "cell_type": "markdown", + "id": "29c57a21", + "metadata": {}, + "source": [ + "## Data type assignment and conversion" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c6932a8b", + "metadata": {}, + "outputs": [], + "source": [ + "string_var = \"25\"\n", + "int_var = int(42)\n", + "float_var = float(3.14)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "a915c83d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "print(type(string_var), type(int_var), type(float_var))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "7212c54e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 25\n" + ] + } + ], + "source": [ + "# Changing the data type of a variable\n", + "changing_variable_type = int(string_var) # converting string to integer\n", + "print(type(changing_variable_type), changing_variable_type) # now it's an integer" + ] + }, + { + "cell_type": "markdown", + "id": "fc6d2569", + "metadata": {}, + "source": [ + "## Variable naming\n", + "\n", + "\n", + "### Allowed variable names" + ] + }, + { + "cell_type": "markdown", + "id": "9e37d5c7", + "metadata": {}, + "source": [ + "```variable = \"Just a variable\"\n", + "_variable = \"Just a variable\"\n", + "variable_ = \"Just a variable\"\n", + "my_variable = \"Just a variable\"\n", + "My_variable_123 = \"Just a variable\"```" + ] + }, + { + "cell_type": "markdown", + "id": "76b46f61", + "metadata": {}, + "source": [ + "```\n", + "# The name of a variable consists of several words!\n", + "camelCaseVariable = \"camelCaseVariable\" # all words except the first begin with a capital letter and are capitalized and spelled consecutively\n", + "snake_case_variable = \"snake_case_variable\" # all words are in lowercase and separated by underscores\n", + "PascalCaseVariable = \"PascalCaseVariable\" # all words begin with a capital letter and are spelled consecutively\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "5da4c806", + "metadata": {}, + "source": [ + "### Invalid variable names" + ] + }, + { + "cell_type": "markdown", + "id": "7980bb53", + "metadata": {}, + "source": [ + "```\n", + "# You can't do that.\n", + "2variable = 'Invalid variable name' # starts with a digit\n", + "my-variable = 'Invalid variable name' # contains a hyphen\n", + "my variable = 'Invalid variable name' # contains a space\n", + "my.variable = 'Invalid variable name' # contains a dot\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "7f45d0c6", + "metadata": {}, + "source": [ + "## Question. How can I convert a list of numbers so that each element of the list becomes a separate string?" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f3356ae7", + "metadata": {}, + "outputs": [], + "source": [ + "# lets take a simple list\n", + "\n", + "list_ = [1, 2, 3]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "9f9dbf8d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'[1, 2, 3]'" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you cannot use only the str() function to convert a list to a string\n", + "# because it will convert the entire list to a single string\n", + "\n", + "str(list_)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f5516c2a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1', '2', '3']" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# option 1: declare a new list and put string values into it in the for loop\n", + "string_list = []\n", + "for item in list_:\n", + " string_list.append(str(item))\n", + "string_list" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f45c257d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1', '2', '3']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# # option 2: use list comprehension\n", + "string_list = [str(item) for item in list_]\n", + "string_list" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "c23487f1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1', '2', '3']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# option 3: map() and list() functions\n", + "string_list = list(map(str, list_))\n", + "string_list" + ] + } + ], + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_01_variables.py b/python/makarov/chapter_01_variables.py new file mode 100644 index 00000000..b1226092 --- /dev/null +++ b/python/makarov/chapter_01_variables.py @@ -0,0 +1,109 @@ +"""Variables and basic operations with them.""" + +# + +# defining a variable +my_variable = "Hello, World!" + +# printing the variable +print(my_variable) +# - + +# In Python, you can assign different values to several variables at once +x_axis, y_axis, z_axis = 1, 2, 3 +print(x_axis, y_axis, z_axis) + +# as well as assign the same value to multiple variables +x_axis = y_axis = z_axis = 0 +print(x_axis, y_axis, z_axis) + +# + +# each item in the list can be "unpacked" into variables + +products_list = ["fruit", "vegetables", "dairy"] +category_1, category_2, category_3 = products_list + +print(category_1, category_2, category_3) +# - + +# ## Automatic data type detection (dynamic typing) + +customer_name = "John Doe" # string variable +loan_amount = 25000.75 # float variable +years = 5 # integer variable + +# ## How to find out the type of a variable in Python? + +# recognize the type of variables from the previous example +print(type(customer_name)) +print(type(loan_amount)) +print(type(years)) + +# ## Data type assignment and conversion + +string_var = "25" +int_var = int(42) +float_var = float(3.14) + +print(type(string_var), type(int_var), type(float_var)) + +# Changing the data type of a variable +changing_variable_type = int(string_var) # converting string to integer +print(type(changing_variable_type), changing_variable_type) # now it's an integer + +# ## Variable naming +# +# +# ### Allowed variable names + +# ```variable = "Just a variable" +# _variable = "Just a variable" +# variable_ = "Just a variable" +# my_variable = "Just a variable" +# My_variable_123 = "Just a variable"``` + +# ``` +# # The name of a variable consists of several words! +# camelCaseVariable = "camelCaseVariable" # all words except the first begin with a capital letter and are capitalized and spelled consecutively +# snake_case_variable = "snake_case_variable" # all words are in lowercase and separated by underscores +# PascalCaseVariable = "PascalCaseVariable" # all words begin with a capital letter and are spelled consecutively +# +# ``` + +# ### Invalid variable names + +# ``` +# # You can't do that. +# 2variable = 'Invalid variable name' # starts with a digit +# my-variable = 'Invalid variable name' # contains a hyphen +# my variable = 'Invalid variable name' # contains a space +# my.variable = 'Invalid variable name' # contains a dot +# +# ``` + +# ## Question. How can I convert a list of numbers so that each element of the list becomes a separate string? + +# + +# lets take a simple list + +list_ = [1, 2, 3] + +# + +# you cannot use only the str() function to convert a list to a string +# because it will convert the entire list to a single string + +str(list_) +# - + +# option 1: declare a new list and put string values into it in the for loop +string_list = [] +for item in list_: + string_list.append(str(item)) +string_list + +# # option 2: use list comprehension +string_list = [str(item) for item in list_] +string_list + +# option 3: map() and list() functions +string_list = list(map(str, list_)) +string_list diff --git a/python/makarov/chapter_02_data_types.ipynb b/python/makarov/chapter_02_data_types.ipynb new file mode 100644 index 00000000..dc44db48 --- /dev/null +++ b/python/makarov/chapter_02_data_types.ipynb @@ -0,0 +1,1061 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "1GRQZRRMUhNV" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Data types in Python.'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Data types in Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xVFt9DcGSfUI" + }, + "source": [ + "### Working with numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "ltvcAbzLSfFp" + }, + "outputs": [], + "source": [ + "int_var = 25 # integer (int)\n", + "float_var = 2.5 # floating point number (float)\n", + "complex_number = 3 + 25j # complex number (complex)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 82, + "status": "ok", + "timestamp": 1741614397562, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "kpljlPxmUdR5", + "outputId": "ba97e614-4316-4762-c3c2-b38613b75234" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2000.0\n", + "\n" + ] + } + ], + "source": [ + "# exponential entry, 2 times 10 to the power of 3\n", + "exponential_number = 2e3\n", + "print(exponential_number)\n", + "print(type(exponential_number))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0ybsQNkWWgLB" + }, + "source": [ + "Arithmetic operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614397572, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "rdedKxrFWiO8", + "outputId": "57c5ebb5-5847-48b4-b2cd-56697a8def77" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4 2 4 2.0 8\n" + ] + } + ], + "source": [ + "# addition, subtraction, multiplication, division, raising to a degree\n", + "example_digit = 2\n", + "example_digit_2 = 4\n", + "print(\n", + " example_digit + example_digit_2,\n", + " example_digit_2 - example_digit,\n", + " example_digit * example_digit,\n", + " example_digit_2 / example_digit,\n", + " example_digit**3,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741614397578, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "5fqcD1AGagad", + "outputId": "9cf95ea4-9d1b-419e-d4d1-00753f81a1ad" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "2\n" + ] + } + ], + "source": [ + "# new operation for us: divide 7 by 2, and find the whole part and the remainder\n", + "example_digit = 7\n", + "example_digit_2 = 2\n", + "\n", + "# whole part of the division\n", + "print(example_digit_2 // example_digit)\n", + "\n", + "# remainder of the division\n", + "print(example_digit_2 % example_digit)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kl1h7PY4u518" + }, + "source": [ + "Comparison operators" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 49, + "status": "ok", + "timestamp": 1741614397629, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "wsMv0ssQuyVQ", + "outputId": "95ff82a4-754a-4d34-cfaa-e20724ab5e4b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True False True False\n" + ] + } + ], + "source": [ + "# greater than, less than, greater than or equal to, and less than or equal to\n", + "example_digit = 2\n", + "example_digit_2 = 4\n", + "print(\n", + " example_digit_2 > example_digit,\n", + " example_digit_2 < example_digit,\n", + " example_digit_2 >= example_digit,\n", + " example_digit_2 <= example_digit,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741614397640, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "RU5Qy8Cjvd8Y", + "outputId": "954465b0-d5f3-4f2c-cdb3-52a8a559ef31" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "True\n" + ] + } + ], + "source": [ + "# the usual equality operator\n", + "example_digit = 2\n", + "example_digit_2 = 4\n", + "print(example_digit == example_digit_2)\n", + "\n", + "# not equal operator\n", + "print(example_digit != example_digit_2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "UjKVC1j_xQAm" + }, + "source": [ + "Logical operations" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 28, + "status": "ok", + "timestamp": 1741614397670, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Vnne0pLlxSs8", + "outputId": "125788c3-1d6b-42d9-c375-c471179a1fca" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n", + "True\n" + ] + } + ], + "source": [ + "# logical AND, both operations must be true\n", + "example_digit = 2\n", + "example_digit_2 = 4\n", + "print(example_digit_2 > example_digit and example_digit_2 != example_digit)\n", + "\n", + "# logical OR, at least one of the operations must be true\n", + "print(example_digit_2 < example_digit or example_digit == example_digit_2)\n", + "\n", + "# logical NOT, negation of the operation\n", + "print(example_digit != example_digit_2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "v6CkmudbVfRm" + }, + "source": [ + "Converting numbers to another number system" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741614397726, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "VyooghwrT1Ak", + "outputId": "922ad58a-684a-4fe4-c8ed-2789bbefd3ae" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0b11001\n", + "25\n" + ] + } + ], + "source": [ + "# create a decimal number\n", + "decimal_num = 25\n", + "\n", + "# convert to binary\n", + "bin_dec = bin(decimal_num)\n", + "print(bin_dec)\n", + "\n", + "# convert back to decimal\n", + "print(int(bin_dec, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614397736, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "yflOiI0SWCYt", + "outputId": "80cb7b54-9e0c-4432-d7c0-170d88c8adc0" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0o31\n", + "25\n" + ] + } + ], + "source": [ + "# create a decimal number\n", + "decimal_num = 25\n", + "\n", + "# convert to octal\n", + "oct_d = oct(decimal_num)\n", + "print(oct_d)\n", + "\n", + "# convert back to decimal\n", + "print(int(oct_d, 8))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 25, + "status": "ok", + "timestamp": 1741614397763, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "8h2UB8UgXh_U", + "outputId": "905b1600-620d-433b-8c9e-a57cfe38fafa" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x19\n", + "25\n" + ] + } + ], + "source": [ + "# convert to hexadecimal\n", + "decimal_num = 25\n", + "hex_d = hex(decimal_num)\n", + "print(hex_d)\n", + "\n", + "# convert back to decimal\n", + "print(int(hex_d, 16))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nwD7zwn7cJ6w" + }, + "source": [ + "### String data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "huuYgDFWYARX" + }, + "outputs": [], + "source": [ + "string_1 = \"this string\"\n", + "string_2 = \"this string too\"" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "id": "vHSc9dlqdDiB" + }, + "outputs": [], + "source": [ + "multi_string = \"\"\"We've all learned a little bit\n", + "Somehow and some other way,\n", + "♪ So, thank goodness for our upbringing ♪\n", + "It's not hard for us to shine.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cVbPttEL1EV-" + }, + "source": [ + "Line length" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 19, + "status": "ok", + "timestamp": 1741614397793, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "KcUZOvBg1GIv", + "outputId": "fb268850-07a5-4fef-b76e-df1450a939ba" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "131" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# use the len() function to find the length of a string\n", + "len(multi_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EvqrYLrKaflu" + }, + "source": [ + "String merge" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741614397799, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "oi3I2oQ7ahUA", + "outputId": "347f00e1-7876-4b1d-e61e-4b46d0601aae" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Programming on Python'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets merge strings\n", + "first_sen_part, second_sen_part, third_sen_part = \"Programming\", \"on\", \"Python\"\n", + "\n", + "first_sen_part + \" \" + second_sen_part + \" \" + third_sen_part" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8yuChtkZzAsv" + }, + "source": [ + "Character index in the string" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 12, + "status": "ok", + "timestamp": 1741614397812, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "6cG3PEPDdyVK", + "outputId": "eebc2370-326a-41c8-c894-eeb144dc22f1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "М\n", + ".\n" + ] + } + ], + "source": [ + "# first element of the multi_string\n", + "print(multi_string[0])\n", + "\n", + "# now output the last element\n", + "print(multi_string[-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "6G8gnYfOQf7K" + }, + "source": [ + "slicing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 15, + "status": "ok", + "timestamp": 1741614397828, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "BjDd8-4nz_8j", + "outputId": "179c02b0-2569-4af8-b216-611278fa5969" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "все\n" + ] + } + ], + "source": [ + "# select elements four through six\n", + "print(multi_string[3:6])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614397839, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "IOl7IswZQtsD", + "outputId": "29283cd4-f801-4be1-8dab-c0ad02a4f347" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We\n", + "ve all learned a little bit\n", + "Somehow and some other way,\n", + "♪ So, thank goodness for our upbringing ♪\n", + "It's not hard for us to shine.\n" + ] + } + ], + "source": [ + "# output all elements up to the second one\n", + "print(multi_string[:2])\n", + "\n", + "# as well as all elements starting from the fourth\n", + "print(multi_string[3:])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Y2mpyCwPTd2w" + }, + "source": [ + "Cycles in strings" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741614397846, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "VAwdI6KoSWOp", + "outputId": "bb6fd38c-ed8e-4fa6-f140-35fd84ef3a1f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "P\n", + "y\n", + "t\n", + "h\n", + "o\n", + "n\n" + ] + } + ], + "source": [ + "# Cycles in strings\n", + "for i in \"Python\":\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "B-_cckdsT364" + }, + "source": [ + "Methods .strip() и .split()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 33, + "status": "ok", + "timestamp": 1741614397881, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "nrgI904PTo4s", + "outputId": "aeba88e0-25df-4e4c-bdb9-0490e72d1368" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 849 302\n", + "15 849 302\n" + ] + } + ], + "source": [ + "# removing unwanted characters from the beginning and end of a string\n", + "print(\"***15 849 302*****\".strip(\"*\"))\n", + "\n", + "# if no argument is specified, spaces at the edges of the string are removed\n", + "print(\" 15 849 302 \".strip())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 43, + "status": "ok", + "timestamp": 1741614397926, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "YbyPzzWtW-I8", + "outputId": "3f2e9650-81e9-4623-db58-aa4669df4aad" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\"We've\", 'all', 'learned', 'a', 'little', 'bit', 'Somehow', 'and', 'some', 'other', 'way,', '♪', 'So,', 'thank', 'goodness', 'for', 'our', 'upbringing', '♪', \"It's\", 'not', 'hard', 'for', 'us', 'to', 'shine.']\n" + ] + } + ], + "source": [ + "# split the string into a list of words\n", + "print(multi_string.split())" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741614397933, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "eVgqVyWAX8ks", + "outputId": "a702189a-0dfe-45a8-c836-069b6c9f5a47" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "26" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# count the number of words in the text (the length of the list)\n", + "len(multi_string.split())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "da7PAlJSem_e" + }, + "source": [ + "Replace a character in a string" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614397942, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "zUPjDpc9eogI", + "outputId": "48967de1-04fe-4767-d9c1-6b3c819a2cf8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20.25\n", + "\n" + ] + } + ], + "source": [ + "# let's assume the data is in this format\n", + "data = \"20,25\"\n", + "\n", + "# now replace ',' with '.'\n", + "data = data.replace(\",\", \".\")\n", + "\n", + "# and convert to a number\n", + "data_converter = float(data)\n", + "print(data_converter)\n", + "print(type(data_converter))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kBxByInXf3xv" + }, + "source": [ + "### Logical values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614397953, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "jnMQ3TTYfMDS", + "outputId": "09c91c15-c4b8-4087-8348-2bd2d1658eb9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "bool" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a variable and write the logical value True into it\n", + "# (capitalization required)\n", + "boll_var = False\n", + "type(boll_var)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741614397959, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "2faKLkNYfQWh", + "outputId": "499e99c5-671d-45cc-ce3e-c9a9a91537a6" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The value of the variable is false\n" + ] + } + ], + "source": [ + "# we'll write a little program that will show you\n", + "# what value is contained in the variable var\n", + "\n", + "if boll_var:\n", + " print(\"The value of the variable is true\")\n", + "else:\n", + " print(\"The value of the variable is false\")\n", + "\n", + "\n", + "# output return always a boolean value False because var is set to False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "provenance": [ + { + "file_id": "1Qp_RLNJzTJEAeo-A9bnbrC0VJEfucv3q", + "timestamp": 1759953080410 + } + ], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_02_data_types.py b/python/makarov/chapter_02_data_types.py new file mode 100644 index 00000000..fa8230bd --- /dev/null +++ b/python/makarov/chapter_02_data_types.py @@ -0,0 +1,209 @@ +"""Data types in Python.""" + +# ### Working with numbers + +int_var = 25 # integer (int) +float_var = 2.5 # floating point number (float) +complex_number = 3 + 25j # complex number (complex) + +# exponential entry, 2 times 10 to the power of 3 +exponential_number = 2e3 +print(exponential_number) +print(type(exponential_number)) + +# Arithmetic operations + +# addition, subtraction, multiplication, division, raising to a degree +example_digit = 2 +example_digit_2 = 4 +print( + example_digit + example_digit_2, + example_digit_2 - example_digit, + example_digit * example_digit, + example_digit_2 / example_digit, + example_digit**3, +) + +example_digit = 7 +example_digit_2 = 2 + +# whole part of the division +print(example_digit_2 // example_digit) + +# remainder of the division +print(example_digit_2 % example_digit) +# - + +# Comparison operators + +# greater than, less than, greater than or equal to, and less than or equal to +example_digit = 2 +example_digit_2 = 4 +print( + example_digit_2 > example_digit, + example_digit_2 < example_digit, + example_digit_2 >= example_digit, + example_digit_2 <= example_digit, +) + +# + +# the usual equality operator +example_digit = 2 +example_digit_2 = 4 +print(example_digit == example_digit_2) + +# not equal operator +print(example_digit != example_digit_2) +# - + +# Logical operations + +# + +# logical AND, both operations must be true +example_digit = 2 +example_digit_2 = 4 +print(example_digit_2 > example_digit and example_digit_2 != example_digit) + +# logical OR, at least one of the operations must be true +print(example_digit_2 < example_digit or example_digit == example_digit_2) + +# logical NOT, negation of the operation +print(example_digit != example_digit_2) +# - + +# Converting numbers to another number system + +# + +# create a decimal number +decimal_num = 25 + +# convert to binary +bin_dec = bin(decimal_num) +print(bin_dec) + +# convert back to decimal +print(int(bin_dec, 2)) + +# + +# create a decimal number +decimal_num = 25 + +# convert to octal +oct_d = oct(decimal_num) +print(oct_d) + +# convert back to decimal +print(int(oct_d, 8)) + +# + +# convert to hexadecimal +decimal_num = 25 +hex_d = hex(decimal_num) +print(hex_d) + +# convert back to decimal +print(int(hex_d, 16)) +# - + +# ### String data + +string_1 = "this string" +string_2 = "this string too" + +multi_string = """We've all learned a little bit +Somehow and some other way, +♪ So, thank goodness for our upbringing ♪ +It's not hard for us to shine.""" + +# Line length + +# use the len() function to find the length of a string +len(multi_string) + +# String merge + +# + +# lets merge strings +first_sen_part, second_sen_part, third_sen_part = "Programming", "on", "Python" + +first_sen_part + " " + second_sen_part + " " + third_sen_part +# - + +# Character index in the string + +# + +# first element of the multi_string +print(multi_string[0]) + +# now output the last element +print(multi_string[-1]) +# - + +# slicing + +# select elements four through six +print(multi_string[3:6]) + +# + +# output all elements up to the second one +print(multi_string[:2]) + +# as well as all elements starting from the fourth +print(multi_string[3:]) +# - + +# Cycles in strings + +# Cycles in strings +for i in "Python": + print(i) + +# Methods .strip() и .split() + +# + +# removing unwanted characters from the beginning and end of a string +print("***15 849 302*****".strip("*")) + +# if no argument is specified, spaces at the edges of the string are removed +print(" 15 849 302 ".strip()) +# - + +# split the string into a list of words +print(multi_string.split()) + +# count the number of words in the text (the length of the list) +len(multi_string.split()) + +# Replace a character in a string + +# + +# let's assume the data is in this format +data = "20,25" + +# now replace ',' with '.' +data = data.replace(",", ".") + +# and convert to a number +data_converter = float(data) +print(data_converter) +print(type(data_converter)) +# - + +# ### Logical values + +# create a variable and write the logical value True into it +# (capitalization required) +boll_var = False +type(boll_var) + +# + +# we'll write a little program that will show you +# what value is contained in the variable var + +if boll_var: + print("The value of the variable is true") +else: + print("The value of the variable is false") + + +# output return always a boolean value False because var is set to False diff --git a/python/makarov/chapter_03_if_loops.ipynb b/python/makarov/chapter_03_if_loops.ipynb new file mode 100644 index 00000000..574648ab --- /dev/null +++ b/python/makarov/chapter_03_if_loops.ipynb @@ -0,0 +1,1743 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "id": "D4hEPtRhhMqh" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Examples of using conditions (if/elif/else) and loops in Python.'" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Examples of using conditions (if/elif/else) and loops in Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## === CONDITIONS (IF / ELIF / ELSE) ===" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 114, + "status": "ok", + "timestamp": 1741614466876, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "KCMYjV0Cg3Zx", + "outputId": "2d3c5d62-2e77-4b09-c5fc-8a1a7471198a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "# === CONDITIONS (IF / ELIF / ELSE) ===\n", + "\n", + "\n", + "# Example 1. Classification of a number by magnitude\n", + "number_example = 42\n", + "\n", + "if number_example < 10:\n", + " print(\"Small\")\n", + "elif number_example < 100:\n", + " print(\"Medium\")\n", + "else:\n", + " print(\"Large\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 13526, + "status": "ok", + "timestamp": 1741614480413, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Jik8GB36UWgh", + "outputId": "abb6e9a2-7d04-4a63-d59b-1312b36144e3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "# request a number from the user\n", + "\n", + "\n", + "user_input = input(\"Enter a number: \")\n", + "\n", + "# convert to int\n", + "user_number = int(user_input)\n", + "\n", + "# classify the number\n", + "if user_number < 10:\n", + " print(\"Small\")\n", + "elif user_number < 100:\n", + " print(\"Medium\")\n", + "else:\n", + " print(\"Large\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7i-2ADtRCv-Z" + }, + "source": [ + "## Nested decisions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6177, + "status": "ok", + "timestamp": 1741614486586, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "G45V7GOfUoKw", + "outputId": "51061495-88b6-499c-b263-95edd749b950" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "# Example 3. Nested conditions\n", + "entered_text = input(\"Enter a number: \")\n", + "\n", + "if len(entered_text) != 0:\n", + "\n", + " entered_number = int(entered_text)\n", + "\n", + " if entered_number < 10:\n", + " print(\"Small\")\n", + " elif entered_number < 100:\n", + " print(\"Medium\")\n", + " else:\n", + " print(\"Large\")\n", + "\n", + "else:\n", + " print(\"Empty input\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "M72PQIj48Igc" + }, + "source": [ + "Example 4. Logical operators and / or\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 30, + "status": "ok", + "timestamp": 1741614486621, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "ktlZYzKDE8Vr", + "outputId": "5b8ff016-c384-4023-a6c6-70202508f021" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Medium\n" + ] + } + ], + "source": [ + "check_number = 42\n", + "\n", + "\n", + "if 10 < check_number < 100:\n", + "\n", + " print(\"Medium\")\n", + "\n", + "\n", + "else:\n", + " print(\"Small or Large\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614486688, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "BfUvmSq5E3m9", + "outputId": "1113ad79-e15d-4187-b635-3e091b070a59" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Small or Large\n" + ] + } + ], + "source": [ + "another_number = 2\n", + "\n", + "if another_number < 10 or another_number > 100:\n", + "\n", + " print(\"Small or Large\")\n", + "\n", + "else:\n", + " print(\"Medium\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EGZZNNr-9Fn-" + }, + "source": [ + "Example 5. Checking occurrences with in / not in" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 155, + "status": "ok", + "timestamp": 1741614486845, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "LOpo6gje9Q-C", + "outputId": "a5c228ea-5f37-4907-dcdf-0eb6ee1140f3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Word found\n" + ] + } + ], + "source": [ + "sentence = \"To be, or not to be, that is the question\"\n", + "target_word = \"question\"\n", + "\n", + "if target_word in sentence:\n", + " print(\"Word found\")" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 221, + "status": "ok", + "timestamp": 1741614487068, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "mHq-uEI4K2AI", + "outputId": "196d6df3-3d03-4edb-83af-7576dc68e844" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "That number is not on the list\n" + ] + } + ], + "source": [ + "numbers = [2, 3, 4, 6, 7]\n", + "target_number = 5\n", + "\n", + "if target_number not in numbers:\n", + " print(\"That number is not on the list\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gWjobfPGNzwg" + }, + "outputs": [], + "source": [ + "fruits = {\"apple\": 3, \"tomato\": 6, \"carrot\": 2}" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 12, + "status": "ok", + "timestamp": 1741614487192, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Z92L7WSTPF-P", + "outputId": "5306ceb6-18a2-4af0-aeb8-317444a088de" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "were found apples\n" + ] + } + ], + "source": [ + "if \"apple\" in fruits:\n", + " print(\"were found apples\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1741614487205, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "YhUXxjsUPTl2", + "outputId": "4c62a3e8-6b70-48c5-d79d-9df71d26809c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Есть\n" + ] + } + ], + "source": [ + "if 6 in fruits.values():\n", + " print(\"Got it\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fsCZohlkYH7k" + }, + "source": [ + "### Cycles in Python" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "z7-hyiTDYOv8" + }, + "source": [ + "#### For loop" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SOp17Yl-fWhG" + }, + "source": [ + "##### Basic operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1741614487216, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "A3GWvb12a6Ra", + "outputId": "c07c70f8-82e6-41b8-db48-1b5980e8ef35" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "numbers = [1, 2, 3]\n", + "\n", + "for number in numbers:\n", + " print(number)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "nIrD5ArAb8ih" + }, + "outputs": [], + "source": [ + "# let's create a dictionary whose values will be lists of two elements\n", + "fruits_info = {\"apple\": [3, \"kg\"], \"tomato\": [6, \"pcs\"], \"carrot\": [2, \"kg\"]}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 12, + "status": "ok", + "timestamp": 1741614487236, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "QD9h9pplgDVI", + "outputId": "f20d59a5-5ab5-4af9-c7ae-ebd1b3549141" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "apple [3, 'kg']\n", + "tomato [6, 'pcs']\n", + "carrot [2, 'kg']\n" + ] + } + ], + "source": [ + "# and then create two container variables and apply the .items() method.\n", + "for fruit_name, fruit_data in fruits_info.items():\n", + " print(fruit_name, fruit_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 87, + "status": "ok", + "timestamp": 1741614487326, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "QV1uyoe0gFLh", + "outputId": "126701f4-c8c6-4ba5-bbcd-778c837dc5fd" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "6\n", + "2\n" + ] + } + ], + "source": [ + "# Let's take only one variable and apply the .values() method\n", + "for fruit_data in fruits_info.values():\n", + " # value is a list, output its first element with индексом [0]\n", + " print(fruit_data[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614487336, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "4L5ktimCcbbJ", + "outputId": "7c17e543-7ff5-4eaf-d8a4-1cf3ca8372b2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "# create an array and put it into the number_array variable\n", + "number_array = np.array([1, 2, 3])\n", + "\n", + "# Let's go through it with a for loop\n", + "for number in number_array:\n", + " print(number)" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": { + "id": "8WzO673x-n7b" + }, + "outputs": [], + "source": [ + "# suppose we have the following customer database\n", + "clients = {\n", + " 1: {\"name\": \"Anna\", \"age\": 24, \"sex\": \"male\", \"revenue\": 12000},\n", + " 2: {\"name\": \"Ilya\", \"age\": 18, \"sex\": \"female\", \"revenue\": 8000},\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741614487353, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "zYoothSRM7T9", + "outputId": "9485789d-3e10-4ffe-a990-63eb8249826d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Client ID: 1\n", + "name: Anna\n", + "age: 24\n", + "sex: male\n", + "revenue: 12000\n", + "\n", + "Client ID: 2\n", + "name: Ilya\n", + "age: 18\n", + "sex: female\n", + "revenue: 8000\n", + "\n" + ] + } + ], + "source": [ + "for client_id, client_info in clients.items():\n", + "\n", + " # output the client id\n", + " print(f\"Client ID: {client_id}\")\n", + "\n", + " # on the second loop we take information about this client (this is also a dictionary)\n", + " for field, value in client_info.items():\n", + "\n", + " # and output each key (field name) and value (the information itself)\n", + " print(f\"{field}: {value}\")\n", + "\n", + " # we will add an empty line after we output the information about one client.\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Q3CB7PzqYZ_L" + }, + "source": [ + "##### Function range()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487361, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "HtJWgzs2OEG_", + "outputId": "c82a607f-6477-4361-d7d7-a607a4ba6bdf" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n" + ] + } + ], + "source": [ + "# Let's create a sequence from 0 to 4.\n", + "for i in range(5):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487370, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "UI24as2nYzR1", + "outputId": "07ac7689-d18c-4267-8b47-986c10086d33" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "4\n", + "5\n" + ] + } + ], + "source": [ + "for number in range(1, 6):\n", + " print(number)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487378, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "qN0SAaPXdILc", + "outputId": "b72a44c1-3c52-4f67-b635-4619ffae5366" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "2\n", + "4\n" + ] + } + ], + "source": [ + "for number in range(0, 6, 2):\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Exercise 6 enumerate()" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487386, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "8dUjujIG3cph", + "outputId": "e1ea261c-c714-4b25-a1c9-1b4a119fa550" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "January 47\n", + "February 75\n", + "March 79\n", + "April 94\n", + "May 123\n", + "June 209\n", + "July 233\n", + "August 214\n", + "September 197\n", + "October 130\n", + "November 87\n", + "December 55\n" + ] + } + ], + "source": [ + "months = [\n", + " \"January\",\n", + " \"February\",\n", + " \"March\",\n", + " \"April\",\n", + " \"May\",\n", + " \"June\",\n", + " \"July\",\n", + " \"August\",\n", + " \"September\",\n", + " \"October\",\n", + " \"November\",\n", + " \"December\",\n", + "]\n", + "\n", + "sales = [47, 75, 79, 94, 123, 209, 233, 214, 197, 130, 87, 55]\n", + "\n", + "length = len(months)\n", + "\n", + "# setting the sequence via range(len()),\n", + "for index in range(length):\n", + " print(months[index], sales[index])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0CFgV73qgUSd" + }, + "source": [ + "Sequence in reverse order" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Jw0cFT6tgiPX" + }, + "source": [ + "**Method 1**. Function reversed()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 12, + "status": "ok", + "timestamp": 1741614487400, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "l51JXd5Egk8o", + "outputId": "ea9e0431-0789-4716-a272-479a95293e7d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# lets create a list\n", + "my_list = [0, 1, 2, 3, 4]\n", + "\n", + "# pass it to the reversed() function and\n", + "# output each of the items in the list using the for loop\n", + "for element in reversed(my_list):\n", + " print(element)" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487408, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Dj4vHmXnhGZ1", + "outputId": "56b9b18b-a7fe-4242-a2e4-232aa351e880" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "for element in reversed(range(5)):\n", + " print(element)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "p_p9pohzgnXz" + }, + "source": [ + "**Method 2**. Specify $-1$ as a step parameter" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487416, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "cgL29MGlgzaa", + "outputId": "44596ce6-aef4-4625-88e3-8d5249d1f07a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n" + ] + } + ], + "source": [ + "# the first parameter is the final element of the list,\n", + "# and the second parameter is the initial element of the list\n", + "for element in range(4, 0, -1):\n", + " print(element)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 35, + "status": "ok", + "timestamp": 1741614487453, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "IZ6veVNThxIV", + "outputId": "7ecce7ec-e249-4f43-8960-edd4cb746fe6" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# to output 0, the second parameter should be -1\n", + "for element in range(4, -1, -1):\n", + " print(element)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pKTDUkY3gz7-" + }, + "source": [ + "**See Method 3**. Function sorted()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741614487461, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "l_FnBDBEg7dG", + "outputId": "cd1f0812-2641-450a-ef31-8282076a4c3c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n", + "2\n", + "1\n", + "0\n" + ] + } + ], + "source": [ + "# lets create a sequence from 0 to 4\n", + "range_values = range(5)\n", + "\n", + "# sort it in descending order\n", + "sorted_desc = sorted(range_values, reverse=True)\n", + "\n", + "# print elements of the sorted sequence\n", + "for element in sorted_desc:\n", + " print(element)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "c4X4Nw2Yf2IH" + }, + "source": [ + "##### Function enumerate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741614487472, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "5a3gqF7-foJY", + "outputId": "358e0f57-cffa-434d-ef50-e811b2c822a2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 Monday\n", + "1 Tuesday\n", + "2 Wednesday\n", + "3 Thursday\n", + "4 Friday\n", + "5 Saturday\n", + "6 Sunday\n" + ] + } + ], + "source": [ + "# let's have a list with the days of the week\n", + "days = [\n", + " \"Monday\",\n", + " \"Tuesday\",\n", + " \"Wednesday\",\n", + " \"Thursday\",\n", + " \"Friday\",\n", + " \"Saturday\",\n", + " \"Sunday\",\n", + "]\n", + "\n", + "# print index and the elements of the list (day)\n", + "for index, day in enumerate(days):\n", + " print(index, day)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Nw5Km-XapZni" + }, + "source": [ + "#### While loop" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741614487496, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "7dWKX2p8pZCl", + "outputId": "b20690f5-36ff-464c-e3b2-ab185409b74a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The current value of the counter: 0\n", + "New counter value: 1\n", + "\n", + "The current value of the counter: 1\n", + "New counter value: 2\n", + "\n", + "The current value of the counter: 2\n", + "New counter value: 3\n", + "\n" + ] + } + ], + "source": [ + "# set the initial value of the counter\n", + "counter = 0\n", + "\n", + "# while the count is less than three\n", + "while counter < 3:\n", + "\n", + " # in each cycle we will output its current value\n", + " print(f\"The current value of the counter: {counter}\")\n", + "\n", + " # inside the loop, do not forget to \"increment\" the counter\n", + " counter = counter + 1\n", + "\n", + " # and print the new value\n", + " print(f\"New counter value: {counter}\")\n", + "\n", + " # add an empty string\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741614487503, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "AsLYv9o-mpy2", + "outputId": "ca5a8611-81a4-45e1-f242-c1e6243b2a50" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n" + ] + } + ], + "source": [ + "# the same code can be simplified using the += operator\n", + "counter_2 = 0\n", + "\n", + "while counter_2 < 3:\n", + " print(counter_2)\n", + " # the += operator immediately increments and assigns a new value\n", + " counter_2 += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "N6Djl9Shdkxh" + }, + "source": [ + "#### Break, continue" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZCW-rwAFggXA" + }, + "source": [ + "Operator break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741614487509, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "RBHU-9AMtfWx", + "outputId": "8fb98266-36f9-417b-df63-956053999ae7" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 {'name': 'Anna', 'age': 24, 'sex': 'male', 'revenue': 12000}\n" + ] + } + ], + "source": [ + "clients_data = {\n", + " 1: {\"name\": \"Anna\", \"age\": 24, \"sex\": \"male\", \"revenue\": 12000},\n", + " 2: {\"name\": \"Ilya\", \"age\": 18, \"sex\": \"female\", \"revenue\": 8000},\n", + "}\n", + "\n", + "# loop through the keys and values of the dictionary\n", + "for client_id, client_info in clients_data.items():\n", + "\n", + " # and print them\n", + " print(client_id, client_info)\n", + "\n", + " # however already after the first execution of the loop, we will interrupt\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741614487519, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "SFqkq_3lfqrn", + "outputId": "8a818f11-8359-4c0f-ad96-41b15f5f168c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n", + "5\n", + "4\n" + ] + } + ], + "source": [ + "counter_3 = 6\n", + "\n", + "# execute the loop until x is zero\n", + "while counter_3 != 0:\n", + "\n", + " # output the current counter value\n", + " print(counter_3)\n", + "\n", + " # and reduce (!) it by 1\n", + " counter_3 -= 1\n", + "\n", + " # if the counter value becomes equal to 3, break the loop\n", + " if counter_3 == 3:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "L3Mf_VrMjX_9" + }, + "source": [ + "Operator continue" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 12, + "status": "ok", + "timestamp": 1741614487532, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "fQOiiMyTjdic", + "outputId": "3eaceef2-657a-4bfc-bcdf-d0585ebbf851" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "4\n", + "6\n", + "8\n", + "10\n" + ] + } + ], + "source": [ + "# output all even numbers in the range from 1 to 10 inclusive.\n", + "\n", + "for number in range(1, 11):\n", + " if number % 2 != 0:\n", + " continue\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9mv5pBDHX3zT" + }, + "source": [ + "#### f strings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "executionInfo": { + "elapsed": 43, + "status": "ok", + "timestamp": 1741614487576, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "T3-9SwA5oyBw", + "outputId": "975ffcc1-101d-4849-bbab-f1819d3d2c3c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Monday'" + ] + }, + "execution_count": 150, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "days = [\n", + " \"Monday\",\n", + " \"Tuesday\",\n", + " \"Wednesday\",\n", + " \"Thursday\",\n", + " \"Friday\",\n", + " \"Saturday\",\n", + " \"Sunday\",\n", + "]\n", + "\n", + "Monday = days[0]\n", + "Monday" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 21, + "status": "ok", + "timestamp": 1741614487601, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "sDm0FLLzYyqM", + "outputId": "0af15dd1-b565-485a-9010-8813efd8dfec" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monday - hard day\n" + ] + } + ], + "source": [ + "print(f\"{Monday} - hard day\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EYzsssCDwI5u" + }, + "source": [ + "### Answers to the questions for the session" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "O8weTrT8w7qh" + }, + "source": [ + "**Question**. Can I use a while loop with the range() function?" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741614487627, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "SZXmOJa7hI6K", + "outputId": "67589a76-8a23-419e-d30a-d2de8a2e393d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Counter value 1\n", + "Counter value 2\n", + "Counter value 3\n", + "Counter value 4\n", + "Counter value 5\n", + "Counter value 6\n", + "Counter value 7\n", + "Counter value 8\n", + "Counter value 9\n", + "Counter value 10\n" + ] + } + ], + "source": [ + "# You can use a while loop with the range() function, but this solution is not optimal\n", + "\n", + "\n", + "counter_4 = 1\n", + "\n", + "while counter_4 in range(1, 11): # while counter is between 1 and 10\n", + " print(\"Counter value \", counter_4) # print its value and\n", + " counter_4 += 1 # increment the counter by 1" + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 14, + "status": "ok", + "timestamp": 1741614487643, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "T-7jFKw9wp0o", + "outputId": "6696e461-f0c5-451e-bcc3-8cdbd7f50f8e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Counter value 1\n", + "Counter value 2\n", + "Counter value 3\n", + "Counter value 4\n", + "Counter value 5\n", + "Counter value 6\n", + "Counter value 7\n", + "Counter value 8\n", + "Counter value 9\n", + "Counter value 10\n" + ] + } + ], + "source": [ + "# better code\n", + "for number in range(1, 11):\n", + " print(f\"Counter value {number}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yrouXtHk2BiB" + }, + "source": [ + "**Question**. Is it possible to do without the continue operator in the example given in the lesson?" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 47, + "status": "ok", + "timestamp": 1741614487699, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "g-0ophfr2QXH", + "outputId": "f220b20b-6480-4bb5-978a-99c3c388821e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "4\n", + "6\n", + "8\n", + "10\n" + ] + } + ], + "source": [ + "for number in range(1, 11):\n", + " # if the number is even, output it\n", + " if number % 2 == 0:\n", + " print(number)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [ + { + "file_id": "18GcMjfYWUJzyAEvH2CQ2ykZ5ghlm38pc", + "timestamp": 1759952985996 + } + ], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_03_if_loops.py b/python/makarov/chapter_03_if_loops.py new file mode 100644 index 00000000..0f71b60d --- /dev/null +++ b/python/makarov/chapter_03_if_loops.py @@ -0,0 +1,386 @@ +"""Examples of using conditions (if/elif/else) and loops in Python.""" + +# ## === CONDITIONS (IF / ELIF / ELSE) === + +# + +import numpy as np + +# === CONDITIONS (IF / ELIF / ELSE) === + + +# Example 1. Classification of a number by magnitude +number_example = 42 + +if number_example < 10: + print("Small") +elif number_example < 100: + print("Medium") +else: + print("Large") + +# + +# request a number from the user + + +user_input = input("Enter a number: ") + +# convert to int +user_number = int(user_input) + +# classify the number +if user_number < 10: + print("Small") +elif user_number < 100: + print("Medium") +else: + print("Large") +# - + +# ## Nested decisions + +# + +# Example 3. Nested conditions +entered_text = input("Enter a number: ") + +if len(entered_text) != 0: + + entered_number = int(entered_text) + + if entered_number < 10: + print("Small") + elif entered_number < 100: + print("Medium") + else: + print("Large") + +else: + print("Empty input") +# - + +# Example 4. Logical operators and / or +# + +# + +check_number = 42 + + +if 10 < check_number < 100: + + print("Medium") + + +else: + print("Small or Large") + +# + +another_number = 2 + +if another_number < 10 or another_number > 100: + + print("Small or Large") + +else: + print("Medium") +# - + +# Example 5. Checking occurrences with in / not in + +# + +sentence = "To be, or not to be, that is the question" +target_word = "question" + +if target_word in sentence: + print("Word found") + +# + +numbers = [2, 3, 4, 6, 7] +target_number = 5 + +if target_number not in numbers: + print("That number is not on the list") +# - + +fruits = {"apple": 3, "tomato": 6, "carrot": 2} + +if "apple" in fruits: + print("were found apples") + +if 6 in fruits.values(): + print("Got it") + +# ### Cycles in Python + +# #### For loop + +# ##### Basic operations + +# + +numbers = [1, 2, 3] + +for number in numbers: + print(number) +# - + +# let's create a dictionary whose values will be lists of two elements +fruits_info = {"apple": [3, "kg"], "tomato": [6, "pcs"], "carrot": [2, "kg"]} + +# and then create two container variables and apply the .items() method. +for fruit_name, fruit_data in fruits_info.items(): + print(fruit_name, fruit_data) + +# Let's take only one variable and apply the .values() method +for fruit_data in fruits_info.values(): + # value is a list, output its first element with индексом [0] + print(fruit_data[0]) + +# + +# create an array and put it into the number_array variable +number_array = np.array([1, 2, 3]) + +# Let's go through it with a for loop +for number in number_array: + print(number) +# - + +# suppose we have the following customer database +clients = { + 1: {"name": "Anna", "age": 24, "sex": "male", "revenue": 12000}, + 2: {"name": "Ilya", "age": 18, "sex": "female", "revenue": 8000}, +} + +for client_id, client_info in clients.items(): + + # output the client id + print(f"Client ID: {client_id}") + + # on the second loop we take information about this client (this is also a dictionary) + for field, value in client_info.items(): + + # and output each key (field name) and value (the information itself) + print(f"{field}: {value}") + + # we will add an empty line after we output the information about one client. + print() + +# ##### Function range() + +# Let's create a sequence from 0 to 4. +for i in range(5): + print(i) + +for number in range(1, 6): + print(number) + +for number in range(0, 6, 2): + print(number) + +# Exercise 6 enumerate() + +# + +months = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +] + +sales = [47, 75, 79, 94, 123, 209, 233, 214, 197, 130, 87, 55] + +length = len(months) + +# setting the sequence via range(len()), +for index in range(length): + print(months[index], sales[index]) +# - + +# Sequence in reverse order + +# **Method 1**. Function reversed() + +# + +# lets create a list +my_list = [0, 1, 2, 3, 4] + +# pass it to the reversed() function and +# output each of the items in the list using the for loop +for element in reversed(my_list): + print(element) +# - + +for element in reversed(range(5)): + print(element) + +# **Method 2**. Specify $-1$ as a step parameter + +# the first parameter is the final element of the list, +# and the second parameter is the initial element of the list +for element in range(4, 0, -1): + print(element) + +# to output 0, the second parameter should be -1 +for element in range(4, -1, -1): + print(element) + +# **See Method 3**. Function sorted() + +# + +# lets create a sequence from 0 to 4 +range_values = range(5) + +# sort it in descending order +sorted_desc = sorted(range_values, reverse=True) + +# print elements of the sorted sequence +for element in sorted_desc: + print(element) +# - + +# ##### Function enumerate() + +# + +# let's have a list with the days of the week +days = [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +] + +# print index and the elements of the list (day) +for index, day in enumerate(days): + print(index, day) +# - + +# #### While loop + +# + +# set the initial value of the counter +counter = 0 + +# while the count is less than three +while counter < 3: + + # in each cycle we will output its current value + print(f"The current value of the counter: {counter}") + + # inside the loop, do not forget to "increment" the counter + counter = counter + 1 + + # and print the new value + print(f"New counter value: {counter}") + + # add an empty string + print() + +# + +# the same code can be simplified using the += operator +counter_2 = 0 + +while counter_2 < 3: + print(counter_2) + # the += operator immediately increments and assigns a new value + counter_2 += 1 +# - + +# #### Break, continue + +# Operator break + +# + +clients_data = { + 1: {"name": "Anna", "age": 24, "sex": "male", "revenue": 12000}, + 2: {"name": "Ilya", "age": 18, "sex": "female", "revenue": 8000}, +} + +# loop through the keys and values of the dictionary +for client_id, client_info in clients_data.items(): + + # and print them + print(client_id, client_info) + + # however already after the first execution of the loop, we will interrupt + break + +# + +counter_3 = 6 + +# execute the loop until x is zero +while counter_3 != 0: + + # output the current counter value + print(counter_3) + + # and reduce (!) it by 1 + counter_3 -= 1 + + # if the counter value becomes equal to 3, break the loop + if counter_3 == 3: + break +# - + +# Operator continue + +# + +# output all even numbers in the range from 1 to 10 inclusive. + +for number in range(1, 11): + if number % 2 != 0: + continue + print(number) +# - + +# #### f strings + +# + +days = [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +] + +Monday = days[0] +Monday +# - + +print(f"{Monday} - hard day") + +# ### Answers to the questions for the session + +# **Question**. Can I use a while loop with the range() function? + +# + +# You can use a while loop with the range() function, but this solution is not optimal + + +counter_4 = 1 + +while counter_4 in range(1, 11): # while counter is between 1 and 10 + print("Counter value ", counter_4) # print its value and + counter_4 += 1 # increment the counter by 1 +# - + +# better code +for number in range(1, 11): + print(f"Counter value {number}") + +# **Question**. Is it possible to do without the continue operator in the example given in the lesson? + +for number in range(1, 11): + # if the number is even, output it + if number % 2 == 0: + print(number) diff --git a/python/makarov/chapter_04_files.ipynb b/python/makarov/chapter_04_files.ipynb new file mode 100644 index 00000000..705177d7 --- /dev/null +++ b/python/makarov/chapter_04_files.ipynb @@ -0,0 +1,457 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "57094fc2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Intro to Google Colab.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Intro to Google Colab.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "507812b4", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import pandas as pd\n", + "\n", + "# from google.colab import files" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7a0c5294", + "metadata": {}, + "outputs": [], + "source": [ + "# create a object of that class and call method.upload()\n", + "# uploaded: dict[str, bytes] = files.upload()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a39181a4", + "metadata": {}, + "outputs": [], + "source": [ + "# display paths to folders (dirpath)\n", + "# and file names (filenames) and then\n", + "for dirpath, _, filenames in os.walk(\"/content/\"):\n", + "\n", + " # in the nested loop, we go through the file names\n", + " for filename in filenames:\n", + "\n", + " # and join the path to the folders and\n", + " # the files contained in these folders\n", + " # using the path.join() method\n", + " print(os.path.join(dirpath, filename))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ac6a2144", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "'ls' is not recognized as an internal or external command,\n", + "operable program or batch file.\n" + ] + } + ], + "source": [ + "# Let's look the contents of the content folder.\n", + "!ls" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c8eb94dc", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "'ls' is not recognized as an internal or external command,\n", + "operable program or batch file.\n" + ] + } + ], + "source": [ + "# Let's take a look inside sample_data\n", + "!ls /content/sample_data/" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f5a02856", + "metadata": {}, + "outputs": [], + "source": [ + "# lets look type of uploaded\n", + "# type(uploaded[\"test.csv\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "1d227a0b", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's turn to the dictionary key uploaded and apply the .decode() method.\n", + "# uploaded_str: str = uploaded[\"test.csv\"].decode()\n", + "\n", + "# the output is a regular string\n", + "# print(type(uploaded_str))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d5675eba", + "metadata": {}, + "outputs": [], + "source": [ + "# print the first 35 characters of the string\n", + "# print(uploaded_str[:35])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f647f3e8", + "metadata": {}, + "outputs": [], + "source": [ + "# if we split the string using the .split() method by the characters \\r\n", + "# (return to the beginning of the string) and \\n (new line)\n", + "# uploaded_list: list[str] = uploaded_str.split(\"\\r\\n\")\n", + "\n", + "# the output will be a list\n", + "# type(uploaded_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e0386e67", + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'file.txt'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[12], line 15\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# pass the file address to the open() function\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# the 'r' parameter means that we want to read the file\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# f1: TextIO = open(\"/content/train.csv\")\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;66;03m# Taking into account the requirements of the reviewers,\u001b[39;00m\n\u001b[0;32m 14\u001b[0m \u001b[38;5;66;03m# the code has been corrected as follows:\u001b[39;00m\n\u001b[1;32m---> 15\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfile.txt\u001b[39m\u001b[38;5;124m\"\u001b[39m, encoding\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f1:\n\u001b[0;32m 16\u001b[0m data \u001b[38;5;241m=\u001b[39m f1\u001b[38;5;241m.\u001b[39mread()\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:324\u001b[0m, in \u001b[0;36m_modified_open\u001b[1;34m(file, *args, **kwargs)\u001b[0m\n\u001b[0;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[0;32m 318\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 319\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 320\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 321\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 322\u001b[0m )\n\u001b[1;32m--> 324\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m io_open(file, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'file.txt'" + ] + } + ], + "source": [ + "# pass the file address to the open() function\n", + "# the 'r' parameter means that we want to read the file\n", + "# f1: TextIO = open(\"/content/train.csv\")\n", + "\n", + "# The .read() method places the entire file in a single line.\n", + "# Let's display the first 142 characters (if no parameter is specified,\n", + "# the entire content will be displayed).\n", + "# print(f1.read(142))\n", + "\n", + "# At the end, the file must be closed.\n", + "# f1.close()\n", + "\n", + "# Taking into account the requirements of the reviewers,\n", + "# the code has been corrected as follows:\n", + "with open(\"file.txt\", encoding=\"utf-8\") as f1:\n", + " data = f1.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "043cf2dc", + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/content/train.csv'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[13], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# f2: TextIO = open(\"/content/train.csv\")\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/content/train.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m, encoding\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f2:\n\u001b[0;32m 3\u001b[0m \n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# Let's go through our object in a \u001b[39;00m\n\u001b[0;32m 5\u001b[0m \u001b[38;5;66;03m# for loop and create an index in parallel.\u001b[39;00m\n\u001b[0;32m 6\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, line \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(f2):\n\u001b[0;32m 7\u001b[0m \n\u001b[0;32m 8\u001b[0m \u001b[38;5;66;03m# display lines without service characters at the edges\u001b[39;00m\n\u001b[0;32m 9\u001b[0m \u001b[38;5;28mprint\u001b[39m(line\u001b[38;5;241m.\u001b[39mstrip())\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:324\u001b[0m, in \u001b[0;36m_modified_open\u001b[1;34m(file, *args, **kwargs)\u001b[0m\n\u001b[0;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[0;32m 318\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 319\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 320\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 321\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 322\u001b[0m )\n\u001b[1;32m--> 324\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m io_open(file, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/content/train.csv'" + ] + } + ], + "source": [ + "# f2: TextIO = open(\"/content/train.csv\")\n", + "with open(\"/content/train.csv\", encoding=\"utf-8\") as f2:\n", + "\n", + " # Let's go through our object in a\n", + " # for loop and create an index in parallel.\n", + " for i, line in enumerate(f2):\n", + "\n", + " # display lines without service characters at the edges\n", + " print(line.strip())\n", + "\n", + " # When we reach the fourth line, we will pause.\n", + " if i == 3:\n", + " break\n", + "\n", + "# Let's not forget to close the file.\n", + "# f2.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "995e527b", + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/content/test.csv'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[14], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Let's tell Python: \"Open the file and name it f3.\"\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/content/test.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m, encoding\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f3:\n\u001b[0;32m 3\u001b[0m \n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# \"go through the lines without service characters\"\u001b[39;00m\n\u001b[0;32m 5\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, line \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(f3):\n\u001b[0;32m 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(line\u001b[38;5;241m.\u001b[39mstrip())\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:324\u001b[0m, in \u001b[0;36m_modified_open\u001b[1;34m(file, *args, **kwargs)\u001b[0m\n\u001b[0;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[0;32m 318\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 319\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 320\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 321\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 322\u001b[0m )\n\u001b[1;32m--> 324\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m io_open(file, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/content/test.csv'" + ] + } + ], + "source": [ + "# Let's tell Python: \"Open the file and name it f3.\"\n", + "with open(\"/content/test.csv\", encoding=\"utf-8\") as f3:\n", + "\n", + " # \"go through the lines without service characters\"\n", + " for i, line in enumerate(f3):\n", + " print(line.strip())\n", + "\n", + " # and \"break on the fourth line\"\n", + " if i == 3:\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "829ee2c8", + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/content/train.csv'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[15], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Apply the read_csv() function and examine\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# the first three records of the train.csv file.\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m train: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mread_csv(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/content/train.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 4\u001b[0m train\u001b[38;5;241m.\u001b[39mhead(\u001b[38;5;241m3\u001b[39m)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1026\u001b[0m, in \u001b[0;36mread_csv\u001b[1;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[0;32m 1013\u001b[0m kwds_defaults \u001b[38;5;241m=\u001b[39m _refine_defaults_read(\n\u001b[0;32m 1014\u001b[0m dialect,\n\u001b[0;32m 1015\u001b[0m delimiter,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1022\u001b[0m dtype_backend\u001b[38;5;241m=\u001b[39mdtype_backend,\n\u001b[0;32m 1023\u001b[0m )\n\u001b[0;32m 1024\u001b[0m kwds\u001b[38;5;241m.\u001b[39mupdate(kwds_defaults)\n\u001b[1;32m-> 1026\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:620\u001b[0m, in \u001b[0;36m_read\u001b[1;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[0;32m 617\u001b[0m _validate_names(kwds\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnames\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m))\n\u001b[0;32m 619\u001b[0m \u001b[38;5;66;03m# Create the parser.\u001b[39;00m\n\u001b[1;32m--> 620\u001b[0m parser \u001b[38;5;241m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[0;32m 622\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m chunksize \u001b[38;5;129;01mor\u001b[39;00m iterator:\n\u001b[0;32m 623\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m parser\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1620\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[1;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[0;32m 1617\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhas_index_names\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m kwds[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhas_index_names\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m 1619\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles: IOHandles \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m-> 1620\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_engine \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_engine(f, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mengine)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1880\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[1;34m(self, f, engine)\u001b[0m\n\u001b[0;32m 1878\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m mode:\n\u001b[0;32m 1879\u001b[0m mode \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m-> 1880\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles \u001b[38;5;241m=\u001b[39m get_handle(\n\u001b[0;32m 1881\u001b[0m f,\n\u001b[0;32m 1882\u001b[0m mode,\n\u001b[0;32m 1883\u001b[0m encoding\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mencoding\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1884\u001b[0m compression\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcompression\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1885\u001b[0m memory_map\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmemory_map\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m),\n\u001b[0;32m 1886\u001b[0m is_text\u001b[38;5;241m=\u001b[39mis_text,\n\u001b[0;32m 1887\u001b[0m errors\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mencoding_errors\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstrict\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m 1888\u001b[0m storage_options\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstorage_options\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1889\u001b[0m )\n\u001b[0;32m 1890\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 1891\u001b[0m f \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles\u001b[38;5;241m.\u001b[39mhandle\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\common.py:873\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m 868\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(handle, \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m 869\u001b[0m \u001b[38;5;66;03m# Check whether the filename is to be opened in binary mode.\u001b[39;00m\n\u001b[0;32m 870\u001b[0m \u001b[38;5;66;03m# Binary mode does not support 'encoding' and 'newline'.\u001b[39;00m\n\u001b[0;32m 871\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ioargs\u001b[38;5;241m.\u001b[39mencoding \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m ioargs\u001b[38;5;241m.\u001b[39mmode:\n\u001b[0;32m 872\u001b[0m \u001b[38;5;66;03m# Encoding\u001b[39;00m\n\u001b[1;32m--> 873\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m 874\u001b[0m handle,\n\u001b[0;32m 875\u001b[0m ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[0;32m 876\u001b[0m encoding\u001b[38;5;241m=\u001b[39mioargs\u001b[38;5;241m.\u001b[39mencoding,\n\u001b[0;32m 877\u001b[0m errors\u001b[38;5;241m=\u001b[39merrors,\n\u001b[0;32m 878\u001b[0m newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 879\u001b[0m )\n\u001b[0;32m 880\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 881\u001b[0m \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[0;32m 882\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(handle, ioargs\u001b[38;5;241m.\u001b[39mmode)\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/content/train.csv'" + ] + } + ], + "source": [ + "# Apply the read_csv() function and examine\n", + "# the first three records of the train.csv file.\n", + "train: pd.DataFrame = pd.read_csv(\"/content/train.csv\")\n", + "train.head(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "0c45df61", + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/content/test.csv'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[16], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Let's do the same with the test.csv file.\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m test: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mread_csv(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/content/test.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 3\u001b[0m test\u001b[38;5;241m.\u001b[39mhead(\u001b[38;5;241m3\u001b[39m)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1026\u001b[0m, in \u001b[0;36mread_csv\u001b[1;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[0;32m 1013\u001b[0m kwds_defaults \u001b[38;5;241m=\u001b[39m _refine_defaults_read(\n\u001b[0;32m 1014\u001b[0m dialect,\n\u001b[0;32m 1015\u001b[0m delimiter,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1022\u001b[0m dtype_backend\u001b[38;5;241m=\u001b[39mdtype_backend,\n\u001b[0;32m 1023\u001b[0m )\n\u001b[0;32m 1024\u001b[0m kwds\u001b[38;5;241m.\u001b[39mupdate(kwds_defaults)\n\u001b[1;32m-> 1026\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:620\u001b[0m, in \u001b[0;36m_read\u001b[1;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[0;32m 617\u001b[0m _validate_names(kwds\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnames\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m))\n\u001b[0;32m 619\u001b[0m \u001b[38;5;66;03m# Create the parser.\u001b[39;00m\n\u001b[1;32m--> 620\u001b[0m parser \u001b[38;5;241m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[0;32m 622\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m chunksize \u001b[38;5;129;01mor\u001b[39;00m iterator:\n\u001b[0;32m 623\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m parser\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1620\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[1;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[0;32m 1617\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhas_index_names\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m kwds[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhas_index_names\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m 1619\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles: IOHandles \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m-> 1620\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_engine \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_engine(f, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mengine)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1880\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[1;34m(self, f, engine)\u001b[0m\n\u001b[0;32m 1878\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m mode:\n\u001b[0;32m 1879\u001b[0m mode \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m-> 1880\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles \u001b[38;5;241m=\u001b[39m get_handle(\n\u001b[0;32m 1881\u001b[0m f,\n\u001b[0;32m 1882\u001b[0m mode,\n\u001b[0;32m 1883\u001b[0m encoding\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mencoding\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1884\u001b[0m compression\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcompression\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1885\u001b[0m memory_map\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmemory_map\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m),\n\u001b[0;32m 1886\u001b[0m is_text\u001b[38;5;241m=\u001b[39mis_text,\n\u001b[0;32m 1887\u001b[0m errors\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mencoding_errors\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstrict\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m 1888\u001b[0m storage_options\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moptions\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstorage_options\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[0;32m 1889\u001b[0m )\n\u001b[0;32m 1890\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 1891\u001b[0m f \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandles\u001b[38;5;241m.\u001b[39mhandle\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\pandas\\io\\common.py:873\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m 868\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(handle, \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m 869\u001b[0m \u001b[38;5;66;03m# Check whether the filename is to be opened in binary mode.\u001b[39;00m\n\u001b[0;32m 870\u001b[0m \u001b[38;5;66;03m# Binary mode does not support 'encoding' and 'newline'.\u001b[39;00m\n\u001b[0;32m 871\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ioargs\u001b[38;5;241m.\u001b[39mencoding \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m ioargs\u001b[38;5;241m.\u001b[39mmode:\n\u001b[0;32m 872\u001b[0m \u001b[38;5;66;03m# Encoding\u001b[39;00m\n\u001b[1;32m--> 873\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m 874\u001b[0m handle,\n\u001b[0;32m 875\u001b[0m ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[0;32m 876\u001b[0m encoding\u001b[38;5;241m=\u001b[39mioargs\u001b[38;5;241m.\u001b[39mencoding,\n\u001b[0;32m 877\u001b[0m errors\u001b[38;5;241m=\u001b[39merrors,\n\u001b[0;32m 878\u001b[0m newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 879\u001b[0m )\n\u001b[0;32m 880\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 881\u001b[0m \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[0;32m 882\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(handle, ioargs\u001b[38;5;241m.\u001b[39mmode)\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/content/test.csv'" + ] + } + ], + "source": [ + "# Let's do the same with the test.csv file.\n", + "test: pd.DataFrame = pd.read_csv(\"/content/test.csv\")\n", + "test.head(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "16144f85", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
PassengerIdSurvived
08920
18931
28940
\n", + "
" + ], + "text/plain": [ + " PassengerId Survived\n", + "0 892 0\n", + "1 893 1\n", + "2 894 0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The sample file can be downloaded from the\n", + "# Internet rather than from a local computer.\n", + "host = \"https://www.dmitrymakarov.ru/\"\n", + "url = host + \"wp-content/uploads/2021/11/titanic_example.csv\"\n", + "\n", + "# just put its URL into the read_csv() function\n", + "example = pd.read_csv(url)\n", + "example.head(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d5e69b5b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The file has been successfully saved to session storage!\n" + ] + } + ], + "source": [ + "# Create a new file result.csv using to_csv(),\n", + "# removing the index in the process.\n", + "# result.to_csv('result.csv', index = False)\n", + "# The file will be saved, and if everything goes well\n", + "# we will display the following text:\n", + "print(\"The file has been successfully saved to session storage!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d460e734", + "metadata": {}, + "outputs": [], + "source": [ + "# apply the .download() method of the files object\n", + "# files.download(\"/content/result.csv\")" + ] + } + ], + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_04_files.py b/python/makarov/chapter_04_files.py new file mode 100644 index 00000000..558e8d57 --- /dev/null +++ b/python/makarov/chapter_04_files.py @@ -0,0 +1,133 @@ +"""Intro to Google Colab.""" + +# + +import os + +import pandas as pd + +# from google.colab import files + +# + +# create a object of that class and call method.upload() +# uploaded: dict[str, bytes] = files.upload() +# - + +# display paths to folders (dirpath) +# and file names (filenames) and then +for dirpath, _, filenames in os.walk("/content/"): + + # in the nested loop, we go through the file names + for filename in filenames: + + # and join the path to the folders and + # the files contained in these folders + # using the path.join() method + print(os.path.join(dirpath, filename)) + +# Let's look the contents of the content folder. +# !ls + +# Let's take a look inside sample_data +# !ls /content/sample_data/ + +# + +# lets look type of uploaded +# type(uploaded["test.csv"]) + +# + +# Let's turn to the dictionary key uploaded and apply the .decode() method. +# uploaded_str: str = uploaded["test.csv"].decode() + +# the output is a regular string +# print(type(uploaded_str)) + +# + +# print the first 35 characters of the string +# print(uploaded_str[:35]) + +# + +# if we split the string using the .split() method by the characters \r +# (return to the beginning of the string) and \n (new line) +# uploaded_list: list[str] = uploaded_str.split("\r\n") + +# the output will be a list +# type(uploaded_list) + +# + +# pass the file address to the open() function +# the 'r' parameter means that we want to read the file +# f1: TextIO = open("/content/train.csv") + +# The .read() method places the entire file in a single line. +# Let's display the first 142 characters (if no parameter is specified, +# the entire content will be displayed). +# print(f1.read(142)) + +# At the end, the file must be closed. +# f1.close() + +# Taking into account the requirements of the reviewers, +# the code has been corrected as follows: +with open("file.txt", encoding="utf-8") as f1: + data = f1.read() + +# + +# f2: TextIO = open("/content/train.csv") +with open("/content/train.csv", encoding="utf-8") as f2: + + # Let's go through our object in a + # for loop and create an index in parallel. + for i, line in enumerate(f2): + + # display lines without service characters at the edges + print(line.strip()) + + # When we reach the fourth line, we will pause. + if i == 3: + break + +# Let's not forget to close the file. +# f2.close() +# - + +# Let's tell Python: "Open the file and name it f3." +with open("/content/test.csv", encoding="utf-8") as f3: + + # "go through the lines without service characters" + for i, line in enumerate(f3): + print(line.strip()) + + # and "break on the fourth line" + if i == 3: + break + +# Apply the read_csv() function and examine +# the first three records of the train.csv file. +train: pd.DataFrame = pd.read_csv("/content/train.csv") +train.head(3) + +# Let's do the same with the test.csv file. +test: pd.DataFrame = pd.read_csv("/content/test.csv") +test.head(3) + +# + +# The sample file can be downloaded from the +# Internet rather than from a local computer. +host = "https://www.dmitrymakarov.ru/" +url = host + "wp-content/uploads/2021/11/titanic_example.csv" + +# just put its URL into the read_csv() function +example = pd.read_csv(url) +example.head(3) +# - + +# Create a new file result.csv using to_csv(), +# removing the index in the process. +# result.to_csv('result.csv', index = False) +# The file will be saved, and if everything goes well +# we will display the following text: +print("The file has been successfully saved to session storage!") + +# + +# apply the .download() method of the files object +# files.download("/content/result.csv") diff --git a/python/makarov/chapter_05_datetime.ipynb b/python/makarov/chapter_05_datetime.ipynb new file mode 100644 index 00000000..d0bee109 --- /dev/null +++ b/python/makarov/chapter_05_datetime.ipynb @@ -0,0 +1,1596 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Datetime module in Python.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Datetime module in Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gQkolpFlve1y" + }, + "source": [ + "## Date and time in Python" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FYsC5TYTyazW" + }, + "source": [ + "### Datetime module" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TSeEV1bV2vnj" + }, + "source": [ + "Import module and datetime class" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 26, + "status": "ok", + "timestamp": 1741696847865, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "nxtEc-BavPKZ", + "outputId": "bb9075d5-baa2-41d2-92ba-8895fce037b0" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-23 22:18:50.014730\n" + ] + } + ], + "source": [ + "# It is often more convenient to import\n", + "# only the datetime class from the datetime module\n", + "from datetime import datetime, timedelta\n", + "\n", + "# to change the time zone you need to import the pytz module\n", + "import pytz\n", + "\n", + "# to get access to the now() function, we first refer to the module,\n", + "# then to the class\n", + "print(datetime.now())" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1741696847877, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "du3H87ntzAw9", + "outputId": "ca6ceb3c-68a1-4907-9114-fa67525e47ad" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-23 22:18:52.556284\n" + ] + } + ], + "source": [ + "# and call him directly\n", + "print(datetime.now())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Z1xtQ8AV2y-B" + }, + "source": [ + "The datetime object and function `now()`" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 58, + "status": "ok", + "timestamp": 1741696847936, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "98cvjJ8zzZnl", + "outputId": "bd99406a-1c6d-4675-cfbe-c930787a3703" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-23 22:18:58.571863\n" + ] + } + ], + "source": [ + "# put the datetime object created with the now() function into the variable\n", + "current_date = datetime.now()\n", + "print(current_date)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741696847974, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "SdIrLFCP3BRS", + "outputId": "d224fe02-1a6c-4a3b-a997-9ce35d08e461" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025 11 23 22 18 58 571863\n" + ] + } + ], + "source": [ + "# Using the appropriate attributes, we will display each component of the\n", + "# object separately.\n", + "print(\n", + " current_date.year,\n", + " current_date.month,\n", + " current_date.day,\n", + " current_date.hour,\n", + " current_date.minute,\n", + " current_date.second,\n", + " current_date.microsecond,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741696847983, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "x-FZ6xl_Tn9a", + "outputId": "c9a3d44f-fd53-453e-f419-67e0b9e53b08" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 3\n" + ] + } + ], + "source": [ + "# you can also look at the day of the week\n", + "# .weekday() method starts the week index at zero,\n", + "# .isoweekday() starts the week index at one\n", + "print(current_date.weekday(), current_date.isoweekday())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 50, + "status": "ok", + "timestamp": 1741696848034, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "YiTIBHFGjdvR", + "outputId": "e1ec254e-660c-4108-e510-cee43e10996e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "# let's look at the time zone using the tzinfo attribute\n", + "print(current_date.tzinfo)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 18, + "status": "ok", + "timestamp": 1741696848037, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Kf7Dp1Vr4_DB", + "outputId": "a6e42ef6-feec-4caa-a7b4-0b2501f826ac" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-10-15 19:29:02.559213+03:00\n" + ] + } + ], + "source": [ + "# lets print the current time in Moscow\n", + "dt_moscow = datetime.now(pytz.timezone(\"Europe/Moscow\"))\n", + "print(dt_moscow)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 112, + "status": "ok", + "timestamp": 1741696848136, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "317feKJE3bq7", + "outputId": "70c99656-b3bc-4ed4-e397-769ee8785cff" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Europe/Moscow\n" + ] + } + ], + "source": [ + "# let's look at the time zone attribute again\n", + "print(dt_moscow.tzinfo)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Y-V3a7ZUoVnR" + }, + "source": [ + "Timestamp" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "id": "2TNSk7hEoU-D" + }, + "outputs": [], + "source": [ + "# get the timestamp of the current time using the .timestamp() method\n", + "timestamp = datetime.now().timestamp()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 100, + "status": "ok", + "timestamp": 1741696848139, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "ZCeooK3Tv7GH", + "outputId": "4342bd68-e605-428c-964c-d1c2e2d64c87" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1760545863.78179\n" + ] + } + ], + "source": [ + "# output the number of seconds elapsed from 01.01.1970 to the code execution\n", + "print(timestamp)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 55, + "status": "ok", + "timestamp": 1741696848140, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "dmkfZp7Evj3W", + "outputId": "8c5155da-7415-4dc3-a521-71c95b546eb2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-10-15 19:31:03.781790\n" + ] + } + ], + "source": [ + "# return timestamp to the previous format using the .fromtimestamp() method\n", + "print(datetime.fromtimestamp(timestamp))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "bpYReaGi6iQD" + }, + "source": [ + "Creating a datetime object manually" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1741696848151, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "6XVGJFxV5Nws", + "outputId": "628dfbb9-ea00-44b9-f0d1-8351a0013ea0" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1991-02-20 00:00:00\n" + ] + } + ], + "source": [ + "# pass datetime object February 20, 1991 to the hb variable\n", + "hb = datetime(1991, 2, 20)\n", + "print(hb)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741696848159, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "oHPz-UYb7GzX", + "outputId": "2788e7c7-c4d1-475a-b0a4-ec2b389e7d31" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1991\n" + ] + } + ], + "source": [ + "# extract the year using the year attribute\n", + "print(hb.year)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 21, + "status": "ok", + "timestamp": 1741696848179, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "fbtdZpi6wKrP", + "outputId": "17d9465f-9cba-47b5-bf22-b4f76a8e05b0" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "666997200.0\n" + ] + } + ], + "source": [ + "# create a timestamp from the hb variable using the .timestamp() method\n", + "print(datetime.timestamp(hb))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dTkMHBejzz3r" + }, + "source": [ + "### Converting strings to a datetime object and vice versa" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "L0tp_c2bc_Ma" + }, + "source": [ + "String ➞ datetime via `.strptime()`" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741696848181, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "hRuMEZe4wXi5", + "outputId": "721f628e-30ac-4d48-b138-922036f80097" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "str" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "str_to_dt = \"2007-12-02 12:30:45\"\n", + "type(str_to_dt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741696848188, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "sfM4trm008IJ", + "outputId": "43933acf-18d7-41e6-bd17-6741c4b6325a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2007-12-02 12:30:45\n", + "\n" + ] + } + ], + "source": [ + "# convert it to datetime using the .strptime() method\n", + "res_dt = datetime.strptime(str_to_dt, \"%Y-%m-%d %H:%M:%S\")\n", + "\n", + "print(res_dt)\n", + "print(type(res_dt))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FE1YFP-ydtaG" + }, + "source": [ + "Datetime ➞ string via `.strftime()`" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741696848197, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "EuA4wuLbds4k", + "outputId": "40eb394b-c837-429a-b2ff-6b80f8bf8abe" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dt_to_str = datetime(2002, 11, 19)\n", + "type(dt_to_str)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741696848204, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "r7WXYXRmc17Z", + "outputId": "9a996781-9e1f-40c0-b9ca-14c93db8f9d2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tuesday, November 19, 2002\n", + "\n" + ] + } + ], + "source": [ + "# convert the object to a string in the format \"day of week,\n", + "# month number, year\"\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": 22, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "executionInfo": { + "elapsed": 40, + "status": "ok", + "timestamp": 1741696848245, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "shboqnqE2qNH", + "outputId": "bc5c5981-a7a9-43ef-8002-b92e02b7e713" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Tuesday, November 19, 2002'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# .strftime() can be applied directly to a datetime object\n", + "dt_to_str.strftime(\"%A, %B %d, %Y\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "executionInfo": { + "elapsed": 13, + "status": "ok", + "timestamp": 1741696848248, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "gzLSq5M14BLJ", + "outputId": "391f050e-ffe2-4520-f63d-2389950cb9ce" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'2025-10-15'" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# also you can format the current date\n", + "datetime.now().strftime(\"%Y-%m-%d\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1741696848250, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "h0NiDIWKEU8B", + "outputId": "22a503bc-76b3-4c5c-9479-b68bbdc2e5ac" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wed Oct 15 21:31:06 2025'" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and yet so\n", + "datetime.now().strftime(\"%c\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KbxUl-Xe7To-" + }, + "source": [ + "Formatting the date and time via `.strptime()` and `.strftime()`" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tSi--Po_82L2" + }, + "source": [ + "|Code | Description | Example |\n", + "| --- | --- | --- |\n", + "| `%a` | Abbreviated name of the day of the week | Sun, Mon, … |\n", + "| `%A` | Full name of the day of the week | Sunday, Monday, … |\n", + "| `%w` | The day of the week as a number, Sun - 0, Mon - 1, ... Sat - 6 | 0, 1, …, 6 |\n", + "| `%d` | Day of the month as a number with zeros | 01, 02, …, 31 |\n", + "| `%-d` | Day of the month as a number without zeros | 1, 2, …, 31 |\n", + "| `%b` | Abbreviated name of the month | Jan, Feb, …, Dec |\n", + "| `%B` | Full name of the month | January, February, … |\n", + "| `%m` | Month as a number with zeros | 01, 02, …, 12 |\n", + "| `%-m` | Month as a number without zeros | 1, 2, …, 12 |\n", + "| `%y` | A year without a century is like a number with zeros | 00, 01, …, 99 |\n", + "| `%-y` | A year without a century is like a number without zeros | 0, 1, …, 99 |\n", + "| `%Y` | A year and a century | 1999, 2019, ... |\n", + "| `%H` | Hour (in 24-hour format) as a number with zeros | 00, 01, …, 23 |\n", + "| `%-H` | Hour (in 24-hour format) as a number without zeros | 0, 1, …, 23 |\n", + "| `%I` | Hour (12-hour format) as a number with zeros | 01, 02, …, 12 |\n", + "| `%-I` | Hour (12-hour format) as a number without zeros | 1, 2, …, 12 |\n", + "| `%p` | AM or PM | AM, PM |\n", + "| `%M` | Minutes as a number with zeros | 00, 01, …, 59 |\n", + "| `%-M` | Minutes as a number without zeros | 0, 1, …, 59 |\n", + "| `%S` | seconds as a number with zeros | 00, 01, …, 59 |\n", + "| `%-S` | Seconds as a number without zeros | 0, 1, …, 59 |\n", + "| `%j` | Day of the year as a number with zeros | 001, 002, …, 366 |\n", + "| `%-j` | Day of the year as a number without zeros | 1, 2, …, 366 |\n", + "| `%c` | full date and time | Sun Nov 21 10:38:12 2021 |\n", + "| `%x` | Date | 11/21/21 |\n", + "| `%X` | Time | 10:43:51 |" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "P3Mq8tzhgS7S" + }, + "source": [ + "### Comparison and arithmetic of dates" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "O49Iw50ggiet" + }, + "source": [ + "Date comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "id": "Ge_6VJYEfvM4" + }, + "outputs": [], + "source": [ + "# let's compare the two publication dates of Einstein's work\n", + "date1 = datetime(1905, 6, 30) # \"To the electrodynamics of moving bodies\"\n", + "date2 = datetime(1916, 5, 11) # General theory of relativity" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 14, + "status": "ok", + "timestamp": 1741696848272, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "k1k7OhWJrVTu", + "outputId": "d8db0667-3908-4cd7-af89-a1b81dd8f493" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# the later date is considered the longer date\n", + "print(date1 < date2)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 11, + "status": "ok", + "timestamp": 1741696848287, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "FXZTPJ_Nrebd", + "outputId": "d0307f84-ea01-4729-e8c1-d34fc72d670f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "# the contrary will be proven false\n", + "print(date1 > date2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9xI-dfch12iX" + }, + "source": [ + "Calendar and alphabetical order of dates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 7, + "status": "ok", + "timestamp": 1741696848295, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "Qdv9abZq1qs4", + "outputId": "87c2a586-b3f1-4b19-ea5a-7313eb81049f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# if the dates are recorded as a string in the format YYYY.MM.DD,\n", + "# then we can compare them as if we were comparing datetime objects\n", + "date_1 = \"2007-12-02\"\n", + "date_2 = \"2002-11-19\"\n", + "\n", + "# first write the dates as a string and compare them\n", + "print(date_1 > date_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741696848303, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "tsldkuKj11Pj", + "outputId": "011d1d88-5ed2-4276-ea88-3ba7a2cc942e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# now as a datetime object\n", + "print(datetime(2007, 12, 2) > datetime(2002, 11, 19))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "eBCy30h6sGlR" + }, + "source": [ + "Time interval and timedelta class" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 71, + "status": "ok", + "timestamp": 1741696848375, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "C5TvKlGwrhBi", + "outputId": "2218b9c3-f9cc-4560-da95-a8043fef5763" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3968 days, 0:00:00\n" + ] + } + ], + "source": [ + "# if we subtract the smaller date from the larger date,\n", + "# we get the time interval between the dates\n", + "diff = date2 - date1\n", + "print(diff)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 11, + "status": "ok", + "timestamp": 1741696848388, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "J-NTeeEhup9m", + "outputId": "a14a600b-1fd7-4a22-d982-2ccf4a96433c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.timedelta" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the result will be stored in a special timedelta object\n", + "type(diff)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741696848398, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "aFNEGOxcsMF3", + "outputId": "59d0a6da-8dc1-4bda-e833-7c2b371367fd" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3968\n" + ] + } + ], + "source": [ + "# the days attribute allows you to view only days\n", + "print(diff.days)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741696848420, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "EiefdopEvouW", + "outputId": "f6150ba8-aacf-4caf-a7b1-083e56d559a0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.timedelta(days=60)" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# a timedelta object can also be created manually\n", + "timedelta(days=60)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pyI8hHfnvg3N" + }, + "source": [ + "The arithmetic of dates" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741696848426, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "nkffSQKXuGCU", + "outputId": "ec5d4ccc-9379-4218-b4eb-052b7428db8e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime(2070, 1, 1, 0, 0)" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# By combining datetime and timedelta objects, we can \"time travel\"\n", + "\n", + "# let's assume it's January 1, 2070.\n", + "future = datetime(2070, 1, 1)\n", + "future" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 8, + "status": "ok", + "timestamp": 1741696848435, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "u33VnF9FwdOK", + "outputId": "db91b0e6-2d95-4005-e741-2d37cf5fb018" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime(1900, 2, 12, 0, 0)" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and we want to go back to January 1, 1900, which is 170 years ago.\n", + "\n", + "# first we just multiply 365 days by 170.\n", + "time_travel = timedelta(days=365) * 170\n", + "\n", + "# and then we go from the future to the past\n", + "past = future - time_travel\n", + "\n", + "# Unfortunately, we're a little \"off\" because we left out leap years, which have 366 days.\n", + "past" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741696848441, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "IWpNXDwu9x3W", + "outputId": "c37fff62-1418-45ea-901f-6c1d2b594580" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "62050" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# we've traveled 62050 days, but actually there are\n", + "# 62 leap years in this period\n", + "365 * 170" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1741696848447, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "sHiGMhj77tgo", + "outputId": "c33a8fd2-1e9f-4c0d-9a5d-c0ef0b406d9c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "62092 days, 0:00:00\n" + ] + } + ], + "source": [ + "# but we already know how to calculate\n", + "# the exact number of days (taking leap years into account).\n", + "print(datetime(2070, 1, 1) - datetime(1900, 1, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1741696848459, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "nkSTbuvexi9g", + "outputId": "d3489414-84f5-4ca6-fb73-8707dd0dc2ec" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Jan 01, 2021\n", + "Jan 02, 2021\n", + "Jan 03, 2021\n", + "Jan 04, 2021\n", + "Jan 05, 2021\n", + "Jan 06, 2021\n", + "Jan 07, 2021\n", + "Jan 08, 2021\n", + "Jan 09, 2021\n", + "Jan 10, 2021\n" + ] + } + ], + "source": [ + "# sometimes it is convenient to use a while loop to create a list of dates\n", + "# for example, a list of New Year's Eve holidays in 2021\n", + "\n", + "cur_date = datetime(2021, 1, 1) # that's the date we'll be outputting\n", + "end_date = datetime(2021, 1, 10) # is the boundary (condition in the while)\n", + "\n", + "\n", + "while cur_date <= end_date:\n", + " print(cur_date.strftime(\"%b %d, %Y\"))\n", + " cur_date += timedelta(days=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3cOKyoFdBtZm" + }, + "source": [ + "### Date and error handling" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lrt4HeBBB29k" + }, + "source": [ + "Try/except construct and pass operator" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 24, + "status": "ok", + "timestamp": 1741696848481, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "FKxevIYyB84_", + "outputId": "bec690e7-0d3d-4809-839c-477ccadd68f1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let a list of numbers in string format be given,\n", + "# and we want to calculate their sum, assume that the 'a' accidentally there\n", + "numbers = [\"5\", \"10\", \"a\", \"15\", \"10\"]\n", + "total = 0\n", + "\n", + "# Let's go over the numbers\n", + "for number in numbers:\n", + "\n", + " # let's try to add a number to the total variable\n", + " try:\n", + " total += int(number)\n", + "\n", + " # if it can't be done, an exception will be raised\n", + " except ValueError:\n", + " pass\n", + "\n", + "# output the sum\n", + "total" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1741696848490, + "user": { + "displayName": "Dmitry Makarov", + "userId": "04264546955677533331" + }, + "user_tz": -180 + }, + "id": "uTWdPszlOnft", + "outputId": "690633b3-11f3-45b8-dc40-8ac507710aab" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Element 'a' could not be processed\n" + ] + }, + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# same code, but with a for loop and a warning message\n", + "total = 0\n", + "\n", + "for number in numbers:\n", + " try:\n", + " total += int(number)\n", + " except ValueError:\n", + " print(f\"Element '{number}' could not be processed\")\n", + "\n", + "total" + ] + } + ], + "metadata": { + "colab": { + "provenance": [ + { + "file_id": "16t9LLPNfbbG3i7HNaGWBNnnUCltZ-7Zi", + "timestamp": 1760481880564 + } + ], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_05_datetime.py b/python/makarov/chapter_05_datetime.py new file mode 100644 index 00000000..10047407 --- /dev/null +++ b/python/makarov/chapter_05_datetime.py @@ -0,0 +1,272 @@ +"""Datetime module in Python.""" + +# ## Date and time in Python + +# ### Datetime module + +# Import module and datetime class + +# + +# It is often more convenient to import +# only the datetime class from the datetime module +from datetime import datetime, timedelta + +# to change the time zone you need to import the pytz module +import pytz + +# to get access to the now() function, we first refer to the module, +# then to the class +print(datetime.now()) +# - + +# and call him directly +print(datetime.now()) + +# The datetime object and function `now()` + +# put the datetime object created with the now() function into the variable +current_date = datetime.now() +print(current_date) + +# Using the appropriate attributes, we will display each component of the +# object separately. +print( + current_date.year, + current_date.month, + current_date.day, + current_date.hour, + current_date.minute, + current_date.second, + current_date.microsecond, +) + +# you can also look at the day of the week +# .weekday() method starts the week index at zero, +# .isoweekday() starts the week index at one +print(current_date.weekday(), current_date.isoweekday()) + +# let's look at the time zone using the tzinfo attribute +print(current_date.tzinfo) + +# lets print the current time in Moscow +dt_moscow = datetime.now(pytz.timezone("Europe/Moscow")) +print(dt_moscow) + +# let's look at the time zone attribute again +print(dt_moscow.tzinfo) + +# Timestamp + +# get the timestamp of the current time using the .timestamp() method +timestamp = datetime.now().timestamp() + +# output the number of seconds elapsed from 01.01.1970 to the code execution +print(timestamp) + +# return timestamp to the previous format using the .fromtimestamp() method +print(datetime.fromtimestamp(timestamp)) + +# Creating a datetime object manually + +# pass datetime object February 20, 1991 to the hb variable +hb = datetime(1991, 2, 20) +print(hb) + +# extract the year using the year attribute +print(hb.year) + +# create a timestamp from the hb variable using the .timestamp() method +print(datetime.timestamp(hb)) + +# ### Converting strings to a datetime object and vice versa + +# String ➞ datetime via `.strptime()` + +str_to_dt = "2007-12-02 12:30:45" +type(str_to_dt) + +# + +# convert it to datetime using the .strptime() method +res_dt = datetime.strptime(str_to_dt, "%Y-%m-%d %H:%M:%S") + +print(res_dt) +print(type(res_dt)) +# - + +# Datetime ➞ string via `.strftime()` + +dt_to_str = datetime(2002, 11, 19) +type(dt_to_str) + +# + +# convert the object to a string in the format "day of week, +# month number, year" +res_str = datetime.strftime(dt_to_str, "%A, %B %d, %Y") + +print(res_str) +print(type(res_str)) +# - + +# .strftime() can be applied directly to a datetime object +dt_to_str.strftime("%A, %B %d, %Y") + +# also you can format the current date +datetime.now().strftime("%Y-%m-%d") + +# and yet so +datetime.now().strftime("%c") + +# Formatting the date and time via `.strptime()` and `.strftime()` + +# |Code | Description | Example | +# | --- | --- | --- | +# | `%a` | Abbreviated name of the day of the week | Sun, Mon, … | +# | `%A` | Full name of the day of the week | Sunday, Monday, … | +# | `%w` | The day of the week as a number, Sun - 0, Mon - 1, ... Sat - 6 | 0, 1, …, 6 | +# | `%d` | Day of the month as a number with zeros | 01, 02, …, 31 | +# | `%-d` | Day of the month as a number without zeros | 1, 2, …, 31 | +# | `%b` | Abbreviated name of the month | Jan, Feb, …, Dec | +# | `%B` | Full name of the month | January, February, … | +# | `%m` | Month as a number with zeros | 01, 02, …, 12 | +# | `%-m` | Month as a number without zeros | 1, 2, …, 12 | +# | `%y` | A year without a century is like a number with zeros | 00, 01, …, 99 | +# | `%-y` | A year without a century is like a number without zeros | 0, 1, …, 99 | +# | `%Y` | A year and a century | 1999, 2019, ... | +# | `%H` | Hour (in 24-hour format) as a number with zeros | 00, 01, …, 23 | +# | `%-H` | Hour (in 24-hour format) as a number without zeros | 0, 1, …, 23 | +# | `%I` | Hour (12-hour format) as a number with zeros | 01, 02, …, 12 | +# | `%-I` | Hour (12-hour format) as a number without zeros | 1, 2, …, 12 | +# | `%p` | AM or PM | AM, PM | +# | `%M` | Minutes as a number with zeros | 00, 01, …, 59 | +# | `%-M` | Minutes as a number without zeros | 0, 1, …, 59 | +# | `%S` | seconds as a number with zeros | 00, 01, …, 59 | +# | `%-S` | Seconds as a number without zeros | 0, 1, …, 59 | +# | `%j` | Day of the year as a number with zeros | 001, 002, …, 366 | +# | `%-j` | Day of the year as a number without zeros | 1, 2, …, 366 | +# | `%c` | full date and time | Sun Nov 21 10:38:12 2021 | +# | `%x` | Date | 11/21/21 | +# | `%X` | Time | 10:43:51 | + +# ### Comparison and arithmetic of dates + +# Date comparison + +# let's compare the two publication dates of Einstein's work +date1 = datetime(1905, 6, 30) # "To the electrodynamics of moving bodies" +date2 = datetime(1916, 5, 11) # General theory of relativity + +# the later date is considered the longer date +print(date1 < date2) + +# the contrary will be proven false +print(date1 > date2) + +# Calendar and alphabetical order of dates + +# + +# if the dates are recorded as a string in the format YYYY.MM.DD, +# then we can compare them as if we were comparing datetime objects +date_1 = "2007-12-02" +date_2 = "2002-11-19" + +# first write the dates as a string and compare them +print(date_1 > date_2) +# - + +# now as a datetime object +print(datetime(2007, 12, 2) > datetime(2002, 11, 19)) + +# Time interval and timedelta class + +# if we subtract the smaller date from the larger date, +# we get the time interval between the dates +diff = date2 - date1 +print(diff) + +# the result will be stored in a special timedelta object +type(diff) + +# the days attribute allows you to view only days +print(diff.days) + +# a timedelta object can also be created manually +timedelta(days=60) + +# The arithmetic of dates + +# + +# By combining datetime and timedelta objects, we can "time travel" + +# let's assume it's January 1, 2070. +future = datetime(2070, 1, 1) +future + +# + +# and we want to go back to January 1, 1900, which is 170 years ago. + +# first we just multiply 365 days by 170. +time_travel = timedelta(days=365) * 170 + +# and then we go from the future to the past +past = future - time_travel + +# Unfortunately, we're a little "off" because we left out leap years, which have 366 days. +past +# - + +# we've traveled 62050 days, but actually there are +# 62 leap years in this period +365 * 170 + +# but we already know how to calculate +# the exact number of days (taking leap years into account). +print(datetime(2070, 1, 1) - datetime(1900, 1, 1)) + +# + +# sometimes it is convenient to use a while loop to create a list of dates +# for example, a list of New Year's Eve holidays in 2021 + +cur_date = datetime(2021, 1, 1) # that's the date we'll be outputting +end_date = datetime(2021, 1, 10) # is the boundary (condition in the while) + + +while cur_date <= end_date: + print(cur_date.strftime("%b %d, %Y")) + cur_date += timedelta(days=1) +# - + +# ### Date and error handling + +# Try/except construct and pass operator + +# + +# Let a list of numbers in string format be given, +# and we want to calculate their sum, assume that the 'a' accidentally there +numbers = ["5", "10", "a", "15", "10"] +total = 0 + +# Let's go over the numbers +for number in numbers: + + # let's try to add a number to the total variable + try: + total += int(number) + + # if it can't be done, an exception will be raised + except ValueError: + pass + +# output the sum +total + +# + +# same code, but with a for loop and a warning message +total = 0 + +for number in numbers: + try: + total += int(number) + except ValueError: + print(f"Element '{number}' could not be processed") + +total diff --git a/python/makarov/chapter_06_functions.ipynb b/python/makarov/chapter_06_functions.ipynb new file mode 100644 index 00000000..48745ad7 --- /dev/null +++ b/python/makarov/chapter_06_functions.ipynb @@ -0,0 +1,1979 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'chapter 6 functions.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"chapter 6 functions.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0AoPSXyUTTLc" + }, + "source": [ + "## Functions in Python" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W3QeADnwrI_g" + }, + "source": [ + "### Built-in functions" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "mmuSaN9wrMpL" + }, + "outputs": [], + "source": [ + "from collections.abc import ItemsView\n", + "from typing import Callable\n", + "\n", + "# import libraries for data visualization\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Before calling the function, you must remember to import\n", + "# the appropriate library\n", + "import numpy as np\n", + "\n", + "# set the reference point for random number generation\n", + "np.random.seed(42)\n", + "# and generate the growth data for 1000 people\n", + "height = list(np.round(np.random.normal(180, 10, 1000)))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "4R42tP5dJflr" + }, + "source": [ + "#### Function parameters and arguments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A parameter is what a function requests when called (for example, bins, the number of intervals).\n", + "An argument is the value of this parameter (in our case, 10)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + }, + "id": "GZzCE-GXsD8H", + "outputId": "0a6e6454-e150-48b1-bc92-e54be971a738" + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# now build a histogram by passing it two parameters,\n", + "# growth data and the number of intervals\n", + "# the first parameter is positional, the second is named.\n", + "plt.hist(height, bins=10)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + }, + "id": "If9utZiWZYeq", + "outputId": "47fde034-9efb-4986-ce67-ae2bf202e257" + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# the first parameter can also be named (the data is denoted by x)\n", + "# and then the order of the parameters can be changed\n", + "plt.hist(bins=10, x=height)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + }, + "id": "5rM2p7inZ4gh", + "outputId": "da7b573e-eaea-437a-8400-6d9cf7c44da5" + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# the bins parameter has a default argument (exactly 10 intervals),\n", + "# which means that this parameter can be omitted\n", + "plt.hist(height)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is worth noting that a function can accept one, two, or several parameters, or accept none at all. For example, if no parameters are specified, the `print()` function returns an empty string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "t6UAoUmwag2c", + "outputId": "ef4a2fe2-25e4-4cb4-de2d-e55464101797" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First line\n", + "\n", + "Third line\n" + ] + } + ], + "source": [ + "# the function may not request parameters\n", + "print(\"First line\")\n", + "print()\n", + "print(\"Third line\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-QM-A2zzJhIn" + }, + "source": [ + "#### Functions and methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some functions are called methods. Methods are functions that can only be applied to a specific object." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "o_fZPD7XJjFy", + "outputId": "80d76b59-0838-44a2-a700-873b19e9e02f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Machine Learning'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "some_string = \"machine learning\"\n", + "\n", + "# apply the .title() method to the string\n", + "some_string.title()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lIM5gFo4TbUg" + }, + "source": [ + "### User-defined functions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CgGpEK0AwM2k" + }, + "source": [ + "#### Defining and calling a function" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "IjjLVSbWqDpE" + }, + "outputs": [], + "source": [ + "# lets define our own function double\n", + "def double(x_arg: int) -> int:\n", + " \"\"\"Multiple transferred number by 2.\"\"\"\n", + " res = x_arg * 2\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EW6-h1F8ufBG", + "outputId": "115c5e57-2e1c-4102-ff92-ddade6454602" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and call it by passing the number 2\n", + "double(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mS-C-sJePhVf" + }, + "source": [ + "#### Empty function body" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "40pnqSnoTR0Z" + }, + "outputs": [], + "source": [ + "# function body cannot be empty\n", + "\n", + "\n", + "def only_return() -> None:\n", + " \"\"\"Return the input value.\"\"\"\n", + " # you must either specify the return keyword\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "id": "HuYLHkX7TZnt" + }, + "outputs": [], + "source": [ + "only_return()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "08Pbq-5VREZk" + }, + "source": [ + "#### Function print() instead of return" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "Jaj1wdaAYFF-" + }, + "outputs": [], + "source": [ + "def double_print(x_arg: int) -> None:\n", + " \"\"\"Multiple passed number by 2 and output result.\"\"\"\n", + " res = x_arg * 2\n", + " print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XgtVgq_HYKyh", + "outputId": "53140a9c-9829-4d6c-dcd9-863b9811b037" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n" + ] + } + ], + "source": [ + "double_print(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zmJv5y8dLUJK" + }, + "source": [ + "#### Parameters of user-defined functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "uhOnVbWhuis_" + }, + "outputs": [], + "source": [ + "# define a function with parameters x and y\n", + "\n", + "\n", + "def calc_sum(x_arg: int, y_arg: int) -> int:\n", + " \"\"\"Add two numbers.\"\"\"\n", + " # and return their sum\n", + " return x_arg + y_arg" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KTEhuHaYwWLQ", + "outputId": "2e3085e6-fe3c-456b-d4a0-e7e9a3ad46ac" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# call this function with one positional and one named parameter\n", + "calc_sum(1, y_arg=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "baCYb7BbT46W", + "outputId": "a46fc104-cdc3-49cc-ec5c-1ccd7894905f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# function parameters can be given default arguments\n", + "\n", + "\n", + "def calc_sum_default(x_arg: int = 1, y_arg: int = 2) -> int:\n", + " \"\"\"Add two integers.\"\"\"\n", + " return x_arg + y_arg\n", + "\n", + "\n", + "# and then you don't have to specify them on the call\n", + "calc_sum_default()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2DQF4G9w_JUW", + "outputId": "96859e9d-1785-4d78-81f2-9f2b19ccb072" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Some string\n" + ] + } + ], + "source": [ + "# function may have no parameters\n", + "\n", + "\n", + "def print_string() -> None:\n", + " \"\"\"Output the 'Some string' string.\"\"\"\n", + " print(\"Some string\")\n", + "\n", + "\n", + "print_string()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jZABsfhPx9wd" + }, + "source": [ + "#### Function annotation\n", + "\n", + "Function annotation allows you to explicitly specify the data type of parameters (parameter annotation) and return values (return annotation)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "TAoI_kYPyB44" + }, + "outputs": [], + "source": [ + "# let's specify that the function takes float type as input and returns int\n", + "# the value 3.5 is the default value of the x parameter\n", + "\n", + "\n", + "def f(x_arg: float = 3.5) -> int:\n", + " \"\"\"Convert the passed float-argument to integer type.\"\"\"\n", + " return int(x_arg)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QaNrg6kZyW8Y", + "outputId": "4afa6d5c-eaa7-4651-e9c1-aa704dd19f3e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x_arg': float, 'return': int}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the desired data type can be viewed via the __annotations__ attribute\n", + "f.__annotations__" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-iKjBO501oYJ", + "outputId": "d6e6c8d3-89c3-4d12-9979-f323f45b82c4" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# call the function without parameters\n", + "f()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vlOHQZGZ_ESX" + }, + "source": [ + "#### Additional features" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QittQ3qiK8S4", + "outputId": "8b2c99f0-f61d-4fe5-e015-22c1762ddea6" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# function calls can be combined with arithmetic operations\n", + "result = calc_sum(1, 2) * 2\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "83RysL9MMQCw", + "outputId": "45598627-36e6-47f3-d456-9e650ba74450" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and logical operations\n", + "result = calc_sum(1, 2) > 2\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "YL1UrXNFb84A", + "outputId": "395474c0-41a3-4146-a978-2e450c2ab8b7" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "P\n" + ] + } + ], + "source": [ + "def first_letter() -> str:\n", + " \"\"\"Return the string 'Python'.\"\"\"\n", + " return \"Python\"\n", + "\n", + "\n", + "print(first_letter()[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WC59uMaoWy8u", + "outputId": "6773f697-f6b8-4cf9-edaa-3ddcff1ac057" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "64" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# function may take no parameters, but use input()\n", + "\n", + "\n", + "def use_input() -> int:\n", + " \"\"\"Square the entered number.\"\"\"\n", + " # request a number from the user and convert it to the int data type\n", + " user_inpt = int(input(\"Введите число: \"))\n", + "\n", + " # square the number\n", + " result_pow = user_inpt**2\n", + "\n", + " # return the result\n", + " return result_pow\n", + "\n", + "\n", + "# call the function\n", + "use_input()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7L2W-41oM6vK" + }, + "source": [ + "#### Function call result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "zVLZODr-PazE", + "outputId": "af00da71-633a-4b23-c7ce-ed29d5ee7234" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2, 3, 4]" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The function can also return a list, tuple, dictionary, etc..\n", + "\n", + "\n", + "# define a function that receives a number as input,\n", + "def create_list(x_arg: int) -> list[int]:\n", + " \"\"\"Create a list filled with numbers from 0 to x_arg.\"\"\"\n", + " # empty list\n", + " my_list: list[int] = []\n", + "\n", + " # in the for loop create a sequence\n", + " for index in range(x_arg):\n", + "\n", + " # and put it on the list\n", + " my_list.append(index)\n", + "\n", + " return my_list\n", + "\n", + "\n", + "# the result of calling this function will be a list of\n", + "create_list(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "RI4Xl_CHNm3B" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('Python', 42)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# function can return two values at once\n", + "\n", + "\n", + "def tuple_f() -> tuple[str, int]:\n", + " \"\"\"Return a tuple ('python', 42).\"\"\"\n", + " string = \"Python\"\n", + " x_arg = 42\n", + " return string, x_arg\n", + "\n", + "\n", + "# call the function\n", + "tuple_f()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "e4AXnLEdNzMJ", + "outputId": "c34bf598-3e76-4128-96ca-494dc144bea1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 42\n", + " \n" + ] + } + ], + "source": [ + "# if you use two variables to receive the result of the function,\n", + "# then the returned tuple will be unpacked into these variables\n", + "a_var, b_var = tuple_f()\n", + "\n", + "# the output is a string and a integer\n", + "print(a_var, b_var)\n", + "print(type(a_var), type(b_var))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "n89-CN1pSlgP", + "outputId": "02b74687-471c-4a3e-e59c-c26440d25189" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('Python', 42)\n", + "\n" + ] + } + ], + "source": [ + "# if one variable is used to receive the result,\n", + "# then the result will be a tuple\n", + "c_var = tuple_f()\n", + "\n", + "print(c_var)\n", + "print(type(c_var))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bQzEDji5VFCY", + "outputId": "a9131375-4436-46a5-d27b-cc982a1ac1df" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the output can be a logical value (True or False)\n", + "\n", + "\n", + "def is_divisible(x_arg: int) -> bool:\n", + " \"\"\"Check if the number is even.\"\"\"\n", + " # if the remainder of division by two is zero\n", + " if x_arg % 2 == 0:\n", + " return True\n", + "\n", + " # otherwise False\n", + " return False\n", + "\n", + "\n", + "is_divisible(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uRNLyptXUoyj" + }, + "source": [ + "#### Using libraries\n", + "\n", + "Additional Python libraries can be used within functions. For example, we can apply the `mean()` function from the Numpy library to calculate the arithmetic mean." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gFTdRnLlUt4Y" + }, + "outputs": [], + "source": [ + "# apply the mean() function of the Numpy library\n", + "# to calculate the arithmetic average\n", + "\n", + "\n", + "# as input our function will take a list or array x,\n", + "def mean_f(x_arg: list[int]) -> float:\n", + " \"\"\"Calculate the average and adds 1 to the result.\"\"\"\n", + " return float(np.mean(x_arg) + 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OFeR_QpWU4i1", + "outputId": "a4f13201-904f-47c1-d97d-cc3d84598450" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3.0" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# prepare data\n", + "x_var: list[int] = [1, 2, 3]\n", + "\n", + "mean_f(x_var)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kY91ANMfXeRG" + }, + "source": [ + "#### Global and local variables\n", + "\n", + "Some variables exist (or, as they say, are visible) only within a function, while others exist throughout the entire program. In the first case, we talk about local variables, and in the second, global variables." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "a4HSsRlBVBT2" + }, + "outputs": [], + "source": [ + "# create a global variable outside the function\n", + "global_name = \"Peter\"\n", + "\n", + "# and then use it inside a new function\n", + "\n", + "\n", + "def show_name() -> None:\n", + " \"\"\"Return the global variable global_name to the console.\"\"\"\n", + " print(global_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_trqrh-zTjkk", + "outputId": "a436b20d-c6cf-42c2-c21a-f1ad43a70c91" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Peter\n" + ] + } + ], + "source": [ + "show_name()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "jmStHPcqTo3F" + }, + "outputs": [], + "source": [ + "# and now let's first create a function,\n", + "# within which we declare a local variable\n", + "\n", + "\n", + "def show_local_name() -> None:\n", + " \"\"\"Return 'Alena' to the console.\"\"\"\n", + " local_name_1 = \"Alena\"\n", + " print(local_name_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9KMmXhAIUJkT", + "outputId": "19f7a460-1ba2-4b13-e72a-b25a74d4543a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Alena\n" + ] + } + ], + "source": [ + "show_local_name()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The function was called without any problems. However, if we try to access the local_name variable outside this function, Python will return an error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "GfAMDzGvUcZ8" + }, + "outputs": [], + "source": [ + "# it is possible to return a local variable to a global variable\n", + "# via the global keyword\n", + "local_name = \"Tatyana\"\n", + "\n", + "\n", + "def make_global() -> None:\n", + " \"\"\"Create a global variable local_name and outputs it to the console.\"\"\"\n", + " global local_name # pylint: disable=W0603\n", + " local_name = \"Alena\"\n", + " print(local_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "glXQZMD9UpDf", + "outputId": "97d5d26f-7f28-4611-f6f7-006866a20068" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Alena\n" + ] + } + ], + "source": [ + "make_global()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "rDAqC_PlZr35" + }, + "outputs": [], + "source": [ + "# define a global variable\n", + "global_number = 5\n", + "\n", + "\n", + "def print_number() -> None:\n", + " \"\"\"Return the value of the local variable local_number to the console.\"\"\"\n", + " # then define a local variable\n", + " local_number = 10\n", + " print(\"Local number:\", local_number)\n", + " print(\"Global number:\", global_number)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JvOjd91fGILS", + "outputId": "d7753061-9c05-49f6-c7d9-59fd4f299b30" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Local number: 10\n", + "Global number: 5\n" + ] + } + ], + "source": [ + "# the function will always \"prefer\" a local variable\"\n", + "print_number()" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "306Y9HOWGIOf", + "outputId": "41ec6f6a-5d13-4412-e844-e63767eda086" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Global number: 5\n" + ] + } + ], + "source": [ + "# the value of the global variable will not change for the rest of the code\n", + "print(\"Global number:\", global_number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xLJn10TGXhlq" + }, + "source": [ + "### Lambda-functions\n", + "\n", + "Convenient to use in cases where the use of the normal function is excessive." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CFPwBvbYXrYR", + "outputId": "4b879d40-03cc-4851-df11-29a92136f043" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a function that takes two numbers and multiplies them\n", + "lf: Callable[[int, int], int] = lambda a_arg, b_arg: a_arg * b_arg\n", + "\n", + "# call the function and pass numbers 2 and 3 to it\n", + "lf(2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "65xVovHHXks9", + "outputId": "d3bdc43a-fed4-4f65-bb86-4dc388694488" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the same functionality can be placed in an ordinary function\n", + "\n", + "\n", + "def normal_f(a_arg: int, b_arg: int) -> int:\n", + " \"\"\"Return the product of the passed arguments.\"\"\"\n", + " return a_arg * b_arg\n", + "\n", + "\n", + "normal_f(2, 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "na0O4KAlE1Pk" + }, + "source": [ + "#### Lambda function inside the filter() function\n", + "\n", + "\n", + "The `filter()` function takes two parameters:\n", + "\n", + "First, another function that acts as a criterion; it returns `True` if the element should be kept, and `False` if it should be removed.\n", + "Second, a set of elements to be filtered in the form of a `list`, `tuple`, or `set`." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RMNawYCas6ER", + "outputId": "0ccd1139-a50f-491c-f44b-43d8602f3c26" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[15, 27, 18]" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nums_list: list[int] = [15, 27, 9, 18, 3, 1, 4]\n", + "\n", + "# write a lambda function that will print True,\n", + "# if the number is greater than 10, and False if it is less than 10.\n", + "is_more_then_10: Callable[[int], bool] = lambda n_arg: n_arg > 10\n", + "\n", + "# put the list and lambda-function into the filter() function\n", + "# and convert the result to a list\n", + "list(filter(is_more_then_10, nums_list))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Y86jO6CewXnU", + "outputId": "c380fd97-b591-4f5b-b9ca-e1c504d5cc49" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[15, 27, 18]" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you can write it all down in one line\n", + "list(filter(lambda n_arg: n_arg > 10, nums_list))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And that's the beauty of lambda functions: you don't need to declare them in advance. Using a regular function, the code would look like this." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VWAYPtGg0YQh", + "outputId": "9a81b80a-52c4-46c3-8bc1-07a445561738" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[15, 27, 18]" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the same problem can be solved using a normal function,\n", + "# but you have to write more code\n", + "\n", + "\n", + "def is_more_then_10_2(n_arg: int) -> bool:\n", + " \"\"\"Check if the passed number is greater than 10.\"\"\"\n", + " if n_arg > 10:\n", + " return True\n", + "\n", + " return False\n", + "\n", + "\n", + "list(filter(is_more_then_10_2, nums_list))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "k9aPF9yVE9eF" + }, + "source": [ + "#### Lambda function inside the sorted() function" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dMFSmXtJYb39", + "outputId": "20eb2b83-cad8-4fc5-fc11-fcbca0ea3725" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(901, 0.0), (1002, 0.22982440568634488), (442, 0.25401128310081567)]" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Remind me that we've created a list of tuples,\n", + "# and each tuple had a movie index and a distance to the movie #\n", + "indices_distances = [\n", + " (901, 0.0),\n", + " (1002, 0.22982440568634488),\n", + " (442, 0.25401128310081567),\n", + "]\n", + "\n", + "# lambda function will take each tuple and return the second [1] element of it\n", + "# passing this function with a key parameter will sort the list by distance\n", + "sorted(indices_distances, key=lambda x_arg: x_arg[1], reverse=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "C8bwJf2oLI69" + }, + "source": [ + "#### Immediately callable functions\n", + "\n", + "\n", + "Lambda functions are what we call immediately invoked function expressions (IIFE). This means we can declare and call such a function at the same time." + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XjbG4yHOK9in", + "outputId": "178e510d-4aac-4ef5-b663-8b527bfb333d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "100" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lambda function can be called immediately at the time of declaration\n", + "(lambda x_arg: x_arg * x_arg)(10) # pylint: disable=C3002" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pgeY1tf6U9PP" + }, + "source": [ + "### \\*args and \\**kwargs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uCX_-CWeYJeZ" + }, + "source": [ + "#### \\*args\n", + "\n", + "Suppose we have a simple function that takes two numbers and calculates their arithmetic mean." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "QxlLBRqLW0Mu" + }, + "outputs": [], + "source": [ + "# write a function to calculate the arithmetic mean of two numbers\n", + "\n", + "\n", + "def mean_simple(a_arg: int, b_arg: int) -> float:\n", + " \"\"\"Calculate the arithmetic mean.\"\"\"\n", + " return (a_arg + b_arg) / 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EhuFz8wpXBVr", + "outputId": "db2f6e0a-3c22-464a-f071-2f8817d3b936" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1.5" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mean_simple(1, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Everything works fine, but we cannot pass more than two numbers to this function. A possible solution would be a function that initially accepts a list as an argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "cyQLlIZLVIM3" + }, + "outputs": [], + "source": [ + "# declare a function to which we want to pass the list\n", + "\n", + "\n", + "def mean_1(list_arg: list[int]) -> float:\n", + " \"\"\"Calculate the arithmetic mean of the passed array of numbers.\"\"\"\n", + " # set a variable for the sum,\n", + " total = 0\n", + "\n", + " # in the loop add all numbers from the list\n", + " for num in list_arg:\n", + " total += num\n", + "\n", + " # and divide by the number of elements\n", + " return total / len(list_arg)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nh7pebndVIQU", + "outputId": "1436f42d-4a15-4d13-d917-bad885b440df" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a list of numbers\n", + "list_: list[int] = [1, 2, 3, 4]\n", + "\n", + "# and pass it to a new function\n", + "mean_1(list_)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 159 + }, + "id": "zy8lFJA9bkBc", + "outputId": "5311a807-f945-4c29-9422-adafa172e940" + }, + "source": [ + "*args allows you to pass an arbitrary number of individual numbers to a function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "vwrIY7CqVIYO" + }, + "outputs": [], + "source": [ + "# declare a function with *args\n", + "\n", + "\n", + "def mean_2(*nums: int) -> float:\n", + " \"\"\"Calculate the arithmetic mean of the passed array of numbers.\"\"\"\n", + " # in this case we add up the elements of the tuple\n", + " total = 0\n", + " for num in nums:\n", + " total += num\n", + "\n", + " return total / len(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "P5Q1bhIVXz9p", + "outputId": "137523e1-03c8-49d5-ad5e-445879480dbf" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# now we can pass individual numbers to the function\n", + "mean_2(1, 2, 3, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bhHgfAZ-Ytmp", + "outputId": "a13075ac-6eef-4c70-b02b-fdd68cdf6be4" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# or list\n", + "mean_2(*list_)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "L3NKa556r5O0", + "outputId": "7523137c-3f2c-419c-81c0-3573b02993b0" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 2, 3, 4) \n" + ] + } + ], + "source": [ + "# we make sure that the unpack operator * forms a tuple\n", + "\n", + "\n", + "def test_type(*nums: int) -> None:\n", + " \"\"\"Check the type of argument *nums.\"\"\"\n", + " print(nums, type(nums))\n", + "\n", + "\n", + "test_type(1, 2, 3, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XHDvzgXFxql2", + "outputId": "05e55975-5e49-4bff-b0ee-e1fa91dad322" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 2, 3, 4) \n" + ] + } + ], + "source": [ + "# the same thing happens with the list\n", + "test_type(*list_)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JeLoABCMy_om", + "outputId": "3f00f8a2-8801-456a-9341-df12e3753e1d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5, 6]\n" + ] + } + ], + "source": [ + "# for illustrative purposes, here is another example\n", + "a_list: list[int] = [1, 2, 3]\n", + "b_list: list[int] = [*a_list, 4, 5, 6]\n", + "\n", + "print(b_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qh8xqKMwYLpH" + }, + "source": [ + "#### \\**kwargs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gzEpZF_13Vfq" + }, + "outputs": [], + "source": [ + "# **kwargs converts named parameters into a dictionary\n", + "\n", + "\n", + "def fn(**kwargs: int) -> ItemsView[str, int]:\n", + " \"\"\"Return a list of key/value pairs of named parameters.\"\"\"\n", + " return kwargs.items()" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rl4dALTK3plJ", + "outputId": "c317ee78-c259-4cff-cd33-110d73749b74" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_items([('a', 1), ('b', 2)])" + ] + }, + "execution_count": 68, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fn(a=1, b=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Zd930nvoasfs" + }, + "outputs": [], + "source": [ + "# *nums becomes a tuple, **params becomes a dictionary\n", + "\n", + "\n", + "def simple_stats(*nums: int, **params: bool) -> None:\n", + " \"\"\"Calculate the arithmetic mean and RMS.\"\"\"\n", + " # if the 'mean' key is in the params dictionary and its value == True\n", + " if \"mean\" in params and params[\"mean\"] is True:\n", + "\n", + " # calculate the arithmetic mean and round up\n", + " # \\t is a tab character\n", + " print(f\"mean: \\t{np.round(np.mean(nums), 3)}\")\n", + "\n", + " # if the 'std' key is in the params dictionary and its value == True\n", + " if \"std\" in params and params[\"std\"] is True:\n", + "\n", + " # calculate the RMS and round up\n", + " print(f\"std: \\t{np.round(np.std(nums), 3)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "YQqRLpXvfYJZ", + "outputId": "d5a72bf9-363d-4204-e659-5d61c414ea88" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mean: \t12.5\n", + "std: \t5.59\n" + ] + } + ], + "source": [ + "# call the simple_stats() function and pass it numbers and named arguments\n", + "simple_stats(5, 10, 15, 20, mean=True, std=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "h5VyRzsjn2ny", + "outputId": "a6762112-09d1-495c-f2e8-1b62fea3e20b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mean: \t12.5\n" + ] + } + ], + "source": [ + "# if one of the parameters is set to False,\n", + "# the function will not output the corresponding metric\n", + "simple_stats(5, 10, 15, 20, mean=True, std=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "J6TjmWJ3hbBv", + "outputId": "21d40d7d-9493-496c-86ac-2064f4b5b1a3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mean: \t12.5\n", + "std: \t5.59\n" + ] + } + ], + "source": [ + "# if we want to pass parameters by list and dictionary,\n", + "list_nums: list[int] = [5, 10, 15, 20]\n", + "settings: dict[str, bool] = {\"mean\": True, \"std\": True}\n", + "\n", + "# then we need to use the unpacking operators * and ** respectively\n", + "simple_stats(*list_nums, **settings)" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "55FDFsesoAOP", + "outputId": "0c09c820-dc81-4d04-d4e0-ce9ab1b1a1ea" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mean: \t12.5\n", + "std: \t5.59\n" + ] + } + ], + "source": [ + "# there's nothing stopping us from adding another parameter\n", + "simple_stats(5, 10, 15, 20, mean=True, std=True, median=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In conclusion, I would like to note that all of the above examples are educational, and it is certainly possible to do without *args and **kwargs here. In practice, they are used in more complex constructions, such as so-called decorators, but this topic is beyond the scope of today's lesson." + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_06_functions.py b/python/makarov/chapter_06_functions.py new file mode 100644 index 00000000..d2443ba0 --- /dev/null +++ b/python/makarov/chapter_06_functions.py @@ -0,0 +1,616 @@ +"""Chapter 6 functions.""" + +# ## Functions in Python + +# ### Built-in functions + +# + +from collections.abc import ItemsView +from typing import Callable + +# import libraries for data visualization +import matplotlib.pyplot as plt + +# Before calling the function, you must remember to import +# the appropriate library +import numpy as np + +# set the reference point for random number generation +np.random.seed(42) +# and generate the growth data for 1000 people +height = list(np.round(np.random.normal(180, 10, 1000))) +# - + +# #### Function parameters and arguments + +# A parameter is what a function requests when called (for example, bins, the number of intervals). +# An argument is the value of this parameter (in our case, 10). + +# now build a histogram by passing it two parameters, +# growth data and the number of intervals +# the first parameter is positional, the second is named. +plt.hist(height, bins=10) +plt.show() + +# the first parameter can also be named (the data is denoted by x) +# and then the order of the parameters can be changed +plt.hist(bins=10, x=height) +plt.show() + +# the bins parameter has a default argument (exactly 10 intervals), +# which means that this parameter can be omitted +plt.hist(height) +plt.show() + +# It is worth noting that a function can accept one, two, or several parameters, or accept none at all. For example, if no parameters are specified, the `print()` function returns an empty string. + +# the function may not request parameters +print("First line") +print() +print("Third line") + +# #### Functions and methods + +# Some functions are called methods. Methods are functions that can only be applied to a specific object. + +# + +some_string = "machine learning" + +# apply the .title() method to the string +some_string.title() + + +# - + +# ### User-defined functions + +# #### Defining and calling a function + + +# lets define our own function double +def double(x_arg: int) -> int: + """Multiple transferred number by 2.""" + res = x_arg * 2 + return res + + +# and call it by passing the number 2 +double(2) + +# #### Empty function body + +# + +# function body cannot be empty + + +def only_return() -> None: + """Return the input value.""" + # you must either specify the return keyword + return + + +# - + +only_return() + + +# #### Function print() instead of return + + +def double_print(x_arg: int) -> None: + """Multiple passed number by 2 and output result.""" + res = x_arg * 2 + print(res) + + +double_print(5) + +# #### Parameters of user-defined functions + +# + +# define a function with parameters x and y + + +def calc_sum(x_arg: int, y_arg: int) -> int: + """Add two numbers.""" + # and return their sum + return x_arg + y_arg + + +# - + +# call this function with one positional and one named parameter +calc_sum(1, y_arg=2) + +# + +# function parameters can be given default arguments + + +def calc_sum_default(x_arg: int = 1, y_arg: int = 2) -> int: + """Add two integers.""" + return x_arg + y_arg + + +# and then you don't have to specify them on the call +calc_sum_default() + +# + +# function may have no parameters + + +def print_string() -> None: + """Output the 'Some string' string.""" + print("Some string") + + +print_string() +# - + +# #### Function annotation +# +# Function annotation allows you to explicitly specify the data type of parameters (parameter annotation) and return values (return annotation). + +# + +# let's specify that the function takes float type as input and returns int +# the value 3.5 is the default value of the x parameter + + +def f(x_arg: float = 3.5) -> int: + """Convert the passed float-argument to integer type.""" + return int(x_arg) + + +# - + +# the desired data type can be viewed via the __annotations__ attribute +f.__annotations__ + +# call the function without parameters +f() + +# #### Additional features + +# function calls can be combined with arithmetic operations +result = calc_sum(1, 2) * 2 +result + +# and logical operations +result = calc_sum(1, 2) > 2 +result + + +# + +def first_letter() -> str: + """Return the string 'Python'.""" + return "Python" + + +print(first_letter()[0]) + +# + +# function may take no parameters, but use input() + + +def use_input() -> int: + """Square the entered number.""" + # request a number from the user and convert it to the int data type + user_inpt = int(input("Введите число: ")) + + # square the number + result_pow = user_inpt**2 + + # return the result + return result_pow + + +# call the function +use_input() +# - + +# #### Function call result + +# + +# The function can also return a list, tuple, dictionary, etc.. + + +# define a function that receives a number as input, +def create_list(x_arg: int) -> list[int]: + """Create a list filled with numbers from 0 to x_arg.""" + # empty list + my_list: list[int] = [] + + # in the for loop create a sequence + for index in range(x_arg): + + # and put it on the list + my_list.append(index) + + return my_list + + +# the result of calling this function will be a list of +create_list(5) + +# + +# function can return two values at once + + +def tuple_f() -> tuple[str, int]: + """Return a tuple ('python', 42).""" + string = "Python" + x_arg = 42 + return string, x_arg + + +# call the function +tuple_f() + +# + +# if you use two variables to receive the result of the function, +# then the returned tuple will be unpacked into these variables +a_var, b_var = tuple_f() + +# the output is a string and a integer +print(a_var, b_var) +print(type(a_var), type(b_var)) + +# + +# if one variable is used to receive the result, +# then the result will be a tuple +c_var = tuple_f() + +print(c_var) +print(type(c_var)) + +# + +# the output can be a logical value (True or False) + + +def is_divisible(x_arg: int) -> bool: + """Check if the number is even.""" + # if the remainder of division by two is zero + if x_arg % 2 == 0: + return True + + # otherwise False + return False + + +is_divisible(10) +# - + +# #### Using libraries +# +# Additional Python libraries can be used within functions. For example, we can apply the `mean()` function from the Numpy library to calculate the arithmetic mean. + +# + +# apply the mean() function of the Numpy library +# to calculate the arithmetic average + + +# as input our function will take a list or array x, +def mean_f(x_arg: list[int]) -> float: + """Calculate the average and adds 1 to the result.""" + return float(np.mean(x_arg) + 1) + + +# + +# prepare data +x_var: list[int] = [1, 2, 3] + +mean_f(x_var) +# - + +# #### Global and local variables +# +# Some variables exist (or, as they say, are visible) only within a function, while others exist throughout the entire program. In the first case, we talk about local variables, and in the second, global variables. + +# + +# create a global variable outside the function +global_name = "Peter" + +# and then use it inside a new function + + +def show_name() -> None: + """Return the global variable global_name to the console.""" + print(global_name) + + +# - + +show_name() + +# + +# and now let's first create a function, +# within which we declare a local variable + + +def show_local_name() -> None: + """Return 'Alena' to the console.""" + local_name_1 = "Alena" + print(local_name_1) + + +# - + +show_local_name() + +# The function was called without any problems. However, if we try to access the local_name variable outside this function, Python will return an error. + +# + +# it is possible to return a local variable to a global variable +# via the global keyword +local_name = "Tatyana" + + +def make_global() -> None: + """Create a global variable local_name and outputs it to the console.""" + global local_name # pylint: disable=W0603 + local_name = "Alena" + print(local_name) + + +# - + +make_global() + +# + +# define a global variable +global_number = 5 + + +def print_number() -> None: + """Return the value of the local variable local_number to the console.""" + # then define a local variable + local_number = 10 + print("Local number:", local_number) + print("Global number:", global_number) + + +# - + +# the function will always "prefer" a local variable" +print_number() + +# the value of the global variable will not change for the rest of the code +print("Global number:", global_number) + +# ### Lambda-functions +# +# Convenient to use in cases where the use of the normal function is excessive. + +# + +# create a function that takes two numbers and multiplies them +lf: Callable[[int, int], int] = lambda a_arg, b_arg: a_arg * b_arg + +# call the function and pass numbers 2 and 3 to it +lf(2, 3) + +# + +# the same functionality can be placed in an ordinary function + + +def normal_f(a_arg: int, b_arg: int) -> int: + """Return the product of the passed arguments.""" + return a_arg * b_arg + + +normal_f(2, 3) +# - + +# #### Lambda function inside the filter() function +# +# +# The `filter()` function takes two parameters: +# +# First, another function that acts as a criterion; it returns `True` if the element should be kept, and `False` if it should be removed. +# Second, a set of elements to be filtered in the form of a `list`, `tuple`, or `set`. + +# + +nums_list: list[int] = [15, 27, 9, 18, 3, 1, 4] + +# write a lambda function that will print True, +# if the number is greater than 10, and False if it is less than 10. +is_more_then_10: Callable[[int], bool] = lambda n_arg: n_arg > 10 + +# put the list and lambda-function into the filter() function +# and convert the result to a list +list(filter(is_more_then_10, nums_list)) +# - + +# you can write it all down in one line +list(filter(lambda n_arg: n_arg > 10, nums_list)) + +# And that's the beauty of lambda functions: you don't need to declare them in advance. Using a regular function, the code would look like this. + +# + +# the same problem can be solved using a normal function, +# but you have to write more code + + +def is_more_then_10_2(n_arg: int) -> bool: + """Check if the passed number is greater than 10.""" + if n_arg > 10: + return True + + return False + + +list(filter(is_more_then_10_2, nums_list)) +# - + +# #### Lambda function inside the sorted() function + +# + +# Remind me that we've created a list of tuples, +# and each tuple had a movie index and a distance to the movie # +indices_distances = [ + (901, 0.0), + (1002, 0.22982440568634488), + (442, 0.25401128310081567), +] + +# lambda function will take each tuple and return the second [1] element of it +# passing this function with a key parameter will sort the list by distance +sorted(indices_distances, key=lambda x_arg: x_arg[1], reverse=False) +# - + +# #### Immediately callable functions +# +# +# Lambda functions are what we call immediately invoked function expressions (IIFE). This means we can declare and call such a function at the same time. + +# lambda function can be called immediately at the time of declaration +(lambda x_arg: x_arg * x_arg)(10) # pylint: disable=C3002 + +# ### \*args and \**kwargs + +# #### \*args +# +# Suppose we have a simple function that takes two numbers and calculates their arithmetic mean. + +# + +# write a function to calculate the arithmetic mean of two numbers + + +def mean_simple(a_arg: int, b_arg: int) -> float: + """Calculate the arithmetic mean.""" + return (a_arg + b_arg) / 2 + + +# - + +mean_simple(1, 2) + +# Everything works fine, but we cannot pass more than two numbers to this function. A possible solution would be a function that initially accepts a list as an argument. + +# + +# declare a function to which we want to pass the list + + +def mean_1(list_arg: list[int]) -> float: + """Calculate the arithmetic mean of the passed array of numbers.""" + # set a variable for the sum, + total = 0 + + # in the loop add all numbers from the list + for num in list_arg: + total += num + + # and divide by the number of elements + return total / len(list_arg) + + +# + +# create a list of numbers +list_: list[int] = [1, 2, 3, 4] + +# and pass it to a new function +mean_1(list_) +# - + +# *args allows you to pass an arbitrary number of individual numbers to a function. + +# + +# declare a function with *args + + +def mean_2(*nums: int) -> float: + """Calculate the arithmetic mean of the passed array of numbers.""" + # in this case we add up the elements of the tuple + total = 0 + for num in nums: + total += num + + return total / len(nums) + + +# - + +# now we can pass individual numbers to the function +mean_2(1, 2, 3, 4) + +# or list +mean_2(*list_) + +# + +# we make sure that the unpack operator * forms a tuple + + +def test_type(*nums: int) -> None: + """Check the type of argument *nums.""" + print(nums, type(nums)) + + +test_type(1, 2, 3, 4) +# - + +# the same thing happens with the list +test_type(*list_) + +# + +# for illustrative purposes, here is another example +a_list: list[int] = [1, 2, 3] +b_list: list[int] = [*a_list, 4, 5, 6] + +print(b_list) +# - + +# #### \**kwargs + +# + +# **kwargs converts named parameters into a dictionary + + +def fn(**kwargs: int) -> ItemsView[str, int]: + """Return a list of key/value pairs of named parameters.""" + return kwargs.items() + + +# - + +fn(a=1, b=2) + +# + +# *nums becomes a tuple, **params becomes a dictionary + + +def simple_stats(*nums: int, **params: bool) -> None: + """Calculate the arithmetic mean and RMS.""" + # if the 'mean' key is in the params dictionary and its value == True + if "mean" in params and params["mean"] is True: + + # calculate the arithmetic mean and round up + # \t is a tab character + print(f"mean: \t{np.round(np.mean(nums), 3)}") + + # if the 'std' key is in the params dictionary and its value == True + if "std" in params and params["std"] is True: + + # calculate the RMS and round up + print(f"std: \t{np.round(np.std(nums), 3)}") + + +# - + +# call the simple_stats() function and pass it numbers and named arguments +simple_stats(5, 10, 15, 20, mean=True, std=True) + +# if one of the parameters is set to False, +# the function will not output the corresponding metric +simple_stats(5, 10, 15, 20, mean=True, std=False) + +# + +# if we want to pass parameters by list and dictionary, +list_nums: list[int] = [5, 10, 15, 20] +settings: dict[str, bool] = {"mean": True, "std": True} + +# then we need to use the unpacking operators * and ** respectively +simple_stats(*list_nums, **settings) +# - + +# there's nothing stopping us from adding another parameter +simple_stats(5, 10, 15, 20, mean=True, std=True, median=True) + +# In conclusion, I would like to note that all of the above examples are educational, and it is certainly possible to do without *args and **kwargs here. In practice, they are used in more complex constructions, such as so-called decorators, but this topic is beyond the scope of today's lesson. diff --git a/python/makarov/chapter_07_classes.ipynb b/python/makarov/chapter_07_classes.ipynb new file mode 100644 index 00000000..2627b853 --- /dev/null +++ b/python/makarov/chapter_07_classes.ipynb @@ -0,0 +1,1622 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Classes and objects in Python.'" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Classes and objects in Python.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lIM5gFo4TbUg" + }, + "source": [ + "### Creating a class" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "id": "QGswhMFMno7-" + }, + "outputs": [], + "source": [ + "class CatClass:\n", + " \"\"\"Cat Class.\"\"\"\n", + "\n", + " # and we will define the method .__init__()\n", + " def __init__(self) -> None:\n", + " \"\"\"Initialize class instance.\"\"\"\n", + " print(\"Cat initializing\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qIIzZD65n1Mh" + }, + "source": [ + "#### Creating an object of CatClass" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 104 + }, + "id": "pERZ4ZQonsJB", + "outputId": "ec41568f-3897-4c9f-e23f-2a65ecb4d894" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cat initializing\n" + ] + }, + { + "data": { + "text/plain": [ + "__main__.CatClass" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a Matroskin object of the CatClass class.\n", + "Matroskin = CatClass()\n", + "\n", + "# Let's check the data type of the created variable.\n", + "type(Matroskin)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1DUEgzmJn6_h" + }, + "source": [ + "#### Class attributes" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "id": "0mQE6dKcwIjD" + }, + "outputs": [], + "source": [ + "# Let's create an updated version of the CatClass class.\n", + "\n", + "\n", + "class CatClass1:\n", + " \"\"\"Cat Class.\"\"\"\n", + "\n", + " # The __init__() method now also accepts the color parameter.\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize cat class with color and type.\"\"\"\n", + " # that parameter will be stored in the self.color attribute variable\n", + " self.color = color\n", + "\n", + " # The value of the type_ attribute is specified within the class.\n", + " self.type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CXFmjySeEJ59", + "outputId": "63e1955b-c1e7-43e1-d5d0-f077bfead122" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('gray', 'cat')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's recreate the CatClass object, passing it the fur color parameter.\n", + "Matroskin1 = CatClass1(\"gray\")\n", + "\n", + "# and we will print the class attributes\n", + "Matroskin1.color, Matroskin1.type_" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lm6DQjYEWR-M" + }, + "source": [ + "#### Class methods" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "id": "KYAGXaEaWXGt" + }, + "outputs": [], + "source": [ + "# Let's rewrite the CatClass class.\n", + "\n", + "\n", + "class CatClass2:\n", + " \"\"\"Cat Class.\"\"\"\n", + "\n", + " # We will leave the __init__() method and attributes unchanged.\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize Cat with color and type.\"\"\"\n", + " self.color = color\n", + " self.type_ = \"cat\"\n", + "\n", + " # lets add the .meow() method for meowing\n", + " def meow(self) -> None:\n", + " \"\"\"Perform meowing..\"\"\"\n", + " for _ in range(3):\n", + " print(\"Meow!\")\n", + "\n", + " # and the .info() method for displaying information about an object\n", + " def info(self) -> None:\n", + " \"\"\"Display information about the Cat instance..\"\"\"\n", + " print(self.color, self.type_)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "id": "pwOtF86Na8Tm" + }, + "outputs": [], + "source": [ + "# let's create an object of the rewritten class\n", + "Matroskin2 = CatClass2(\"gray\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5wKGe_KEcq9C", + "outputId": "7faf0fa9-83e6-4879-e9ee-451f67b99dc3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Meow!\n", + "Meow!\n", + "Meow!\n" + ] + } + ], + "source": [ + "# and we will call the .info() method\n", + "Matroskin2.meow()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "01l4yJA17k9d", + "outputId": "f8831b06-b408-41dd-bdf1-cedd0ef17d84" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gray cat\n" + ] + } + ], + "source": [ + "# и метод .info()\n", + "Matroskin2.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7o5fPMtonH0V" + }, + "source": [ + "### Principles of OOP" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LG0BiM5PgxYR" + }, + "source": [ + "#### Encapsulation\n", + "\n", + " This is the ability of a class to store data and methods within itself. In other words, a class object can be represented as a capsule containing the necessary data and methods.\n", + "\n", + " The concepts of public and private attributes are closely related to the concept of encapsulation. Public attributes are those attributes that can be accessed outside the class \"capsule.\"\n", + "\n", + " By default, all attributes in Python are public." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "X0HiYZq0Rmnd", + "outputId": "21e52d6a-c48c-475e-f9d8-52ab960961da" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'dog'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# change the type attribute of the Matroskin object to dog\n", + "Matroskin1.type_ = \"dog\"\n", + "\n", + "# let's remove this attribute\n", + "Matroskin1.type_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We would like objects of the CatClass class not to change the value of the type_ attribute. In other words, we need to make this attribute private. There are two ways to do this:\n", + "\n", + "Method 1. Place a single underscore before the attribute to indicate to those who will be using our code that this is a private attribute.\n", + "\n", + "Unfortunately, this only partially solves the problem, because the attribute can still be changed." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "id": "_Un9fShyWILH" + }, + "outputs": [], + "source": [ + "class CatClass3:\n", + " \"\"\"Cat Class.\"\"\"\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize Cat with color and type.\"\"\"\n", + " self.color = color\n", + " # An underscore symbol BEFORE the attribute name indicates,\n", + " # that this is a private attribute and should not be changed outside\n", + " # the class.\n", + " self._type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "YmpfrLukW4sm", + "outputId": "d1f43282-6ddf-4054-aac7-82b75041450e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'dog'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a new object of the CatClass class again.\n", + "Matroskin3 = CatClass3(\"gray\")\n", + "\n", + "# and change the value of the _type_ attribute\n", + "Matroskin3._type_ = \"dog\" # pylint: disable=W0212\n", + "Matroskin3._type_ # pylint: disable=W0212" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Method 2. Place a double underscore symbol before the attribute name. Now you will not be able to directly access this class." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "id": "GqU88qogZ8_B" + }, + "outputs": [], + "source": [ + "class CatClass4:\n", + " \"\"\"Cat Class.\"\"\"\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize Cat with color and type.\"\"\"\n", + " self.color = color\n", + " # The double underscore symbol will prevent external access.\n", + " self.__type_ = \"cat\"\n", + " print(self.__type_)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "id": "2O1GUso6aG4C" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cat\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'CatClass4' object has no attribute '__type_'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[21], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# When attempting to call such an attribute, Python will return an error.\u001b[39;00m\n\u001b[0;32m 2\u001b[0m Matroskin4 \u001b[38;5;241m=\u001b[39m CatClass4(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgray\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(Matroskin4\u001b[38;5;241m.\u001b[39m__type_)\n", + "\u001b[1;31mAttributeError\u001b[0m: 'CatClass4' object has no attribute '__type_'" + ] + } + ], + "source": [ + "# When attempting to call such an attribute, Python will return an error.\n", + "Matroskin4 = CatClass4(\"gray\")\n", + "print(Matroskin4.__type_) # pylint: disable=W0212" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "gqsNNuRiaHBr", + "outputId": "4a011366-bbe1-4668-ba86-9a3774713d71" + }, + "outputs": [], + "source": [ + "# However, we can access this attribute using name mangling.\n", + "# Matroskin4._CatClass4__type_ = \"dog\" C0103\n", + "\n", + "# unfortunately, the value of the attribute will change\n", + "# print(Matroskin4._CatClass4__type_)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "33PlUWogG2HN" + }, + "source": [ + "#### Class inheritance\n", + "\n", + "The principle of inheritance assumes that one class inherits the attributes and methods of another. In this case, we talk about a parent class or base class and a child class or derived class." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "e-NaY_Yd4l5h" + }, + "source": [ + "Creating a parent class and a child class" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "id": "HS-07E-6Vc6Q" + }, + "outputs": [], + "source": [ + "# Let's create a class called Animal.\n", + "\n", + "\n", + "class Animal:\n", + " \"\"\"Base class animal.\"\"\"\n", + "\n", + " # Let's define the __init__() method with\n", + " # two parameters: weight (kg) and height (cm).\n", + " def __init__(self, weight: float, length: float) -> None:\n", + " \"\"\"Initialize Animal with weight and length.\"\"\"\n", + " # let's put the arguments of these parameters into the corresponding # variables\n", + " self.weight = weight\n", + " self.length = length\n", + "\n", + " # declare methods .eat()\n", + " def eat(self) -> None:\n", + " \"\"\"Involves eating food.\"\"\"\n", + " print(\"Eating\")\n", + "\n", + " # and .sleep()\n", + " def sleep(self) -> None:\n", + " \"\"\"Sleep method.\"\"\"\n", + " print(\"Sleeping\")" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "id": "lABQGZSoCF0Y" + }, + "outputs": [], + "source": [ + "# Let's create a Bird class.\n", + "# We will write the parent class Animal in brackets.\n", + "\n", + "\n", + "class Bird(Animal):\n", + " \"\"\"Class Bird, descendant of class Animal.\"\"\"\n", + "\n", + " def __init__(self, weight: float, length: float) -> None:\n", + " \"\"\"Initialize Bird with weight, length.\"\"\"\n", + " # Using the super() function, call the .__init__() method of the\n", + " # parent class Animal.\n", + " Animal.__init__(self, weight, length)\n", + "\n", + " # Inside the Bird class, declare a new method .move()\n", + " def move(self) -> None:\n", + " \"\"\"Perform a bird flight.\"\"\"\n", + " # for birds .move() will mean \"to fly\"\n", + " print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "id": "RzdouKGtCQMP" + }, + "outputs": [], + "source": [ + "# Let's create a pigeon object and assign it the values of weight and length.\n", + "pigeon = Bird(0.3, 30)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "YGwcXdjWCcDd", + "outputId": "ed5ba623-7a25-4989-8575-b0b828fd32b1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.3 30\n" + ] + } + ], + "source": [ + "# Let's look at the attributes inherited from the Animal class.\n", + "print(pigeon.weight, pigeon.length)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8wX-Bo_fCcP7", + "outputId": "f81e094f-0fc7-495f-d361-6ae2089af75f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eating\n" + ] + } + ], + "source": [ + "# and methods inherited from the Animal class.\n", + "pigeon.eat()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "d6HH0FwrCw90", + "outputId": "392ed579-8f16-485b-cb46-1fc8a1622756" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Flying\n" + ] + } + ], + "source": [ + "# Now let's call a method that is specific to the Bird class.\n", + "pigeon.move()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "z9yL5WN2C_Qi" + }, + "source": [ + "### Function `super()`\n", + "\n", + "Note that in the previous example, the Bird class only received new methods; no new attributes appeared in it. The thing is, if we want to add an attribute to a child class while preserving the attributes of the parent class, we need to explicitly call the latter using the super() function." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "id": "JYzIVcZrVc9W" + }, + "outputs": [], + "source": [ + "# Let's create the Bird class again.\n", + "\n", + "\n", + "class Bird1(Animal):\n", + " \"\"\"Class Bird, descendant of class Animal.\"\"\"\n", + "\n", + " # Add the flight speed parameter (km/h) to the .__init__() method.\n", + " def __init__(self, weight: float, length: float, flying_speed: float) -> None:\n", + " \"\"\"Initialize bird with weight, length, and flight speed.\"\"\"\n", + " # Using the super() function,\n", + " # we call the .__init__() method of\n", + " # the parent class Animal.\n", + " Animal.__init__(self, weight, length)\n", + " self.flying_speed = flying_speed\n", + "\n", + " # Let's redefine the .move() method.\n", + " def move(self) -> None:\n", + " \"\"\"Perform bird flight.\"\"\"\n", + " print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "id": "cwu9N5Q0VdAO" + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Bird1' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[12], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Let's create another pigeon object of the Bird class, \u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# but this time with three parameters.\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m pigeon1 \u001b[38;5;241m=\u001b[39m Bird1(\u001b[38;5;241m0.3\u001b[39m, \u001b[38;5;241m30\u001b[39m, \u001b[38;5;241m100\u001b[39m)\n", + "\u001b[1;31mNameError\u001b[0m: name 'Bird1' is not defined" + ] + } + ], + "source": [ + "# Let's create another pigeon object of the Bird class,\n", + "# but this time with three parameters.\n", + "pigeon1 = Bird1(0.3, 30, 100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WfcbSzlf6Ao_", + "outputId": "e1c67eff-0beb-4cd5-d23a-e16d77b74288" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.3 30 100\n" + ] + } + ], + "source": [ + "# Let's call both inherited and\n", + "# custom attributes of the Bird class.\n", + "print(pigeon1.weight, pigeon1.length, pigeon1.flying_speed)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "230dmrRP4ZZE", + "outputId": "08c58782-4a4a-487c-afef-caebda3f5518" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sleeping\n" + ] + } + ], + "source": [ + "# call the inherited method .sleep()\n", + "pigeon1.sleep()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "spaGz6VV4g_m", + "outputId": "005310bf-a88a-484e-a816-feac166bf35a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Flying\n" + ] + } + ], + "source": [ + "# and its own .move() method\n", + "pigeon1.move()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qmOoUK4R5D-f" + }, + "source": [ + "#### Class redefinition\n", + "\n", + "An interesting feature of a descendant class in Python is that it redefines (essentially rewrites) the parent class.Let's create a subclass for flightless birds called Flightless, in which:\n", + "\n", + "the only attribute will be their running speed; and we will replace the result of the .move() method (which is logical) from Flying to Running." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "id": "7EFREoZb4kE6" + }, + "outputs": [], + "source": [ + "# Let's create a subclass Flightless of the class Bird.\n", + "\n", + "\n", + "class Flightless(Bird):\n", + " \"\"\"Non-Flying Bird Class.\"\"\"\n", + "\n", + " # The __init__() method of this subclass \"overrides\" the __init__()\n", + " # method of the parent class.\n", + " def __init__(self, weight: float, length: float, running_speed: float) -> None:\n", + " \"\"\"Initialize Non-Flying Bird at running speed.\"\"\"\n", + " # Thus, we are left with only one attribute.\n", + " Bird.__init__(self, weight, length)\n", + "\n", + " self.running_speed = running_speed\n", + "\n", + " # In addition, the result of the .move() method will be 'Running'.\n", + " def move(self) -> None:\n", + " \"\"\"Perform bird running.\"\"\"\n", + " print(\"Running\")" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "id": "lb8QJKEN4kKh" + }, + "outputs": [], + "source": [ + "# Let's create an ostrich object of the Flightless class.\n", + "ostrich = Flightless(13, 33, 60)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "AoTdJFjw4kNn", + "outputId": "19cba34f-4d88-4b14-8996-84ab61c669d7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "60" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's look at the value of the speed attribute\n", + "ostrich.running_speed" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PledBnHF4kQ3", + "outputId": "f8dc2bdd-d8cb-4d1d-f389-2909bf9b5e16" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running\n" + ] + } + ], + "source": [ + "# and check the .move() method\n", + "ostrich.move()" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7oBZyEcG797e", + "outputId": "445235a6-2e6a-4ff7-d66d-99ba8a359145" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eating\n" + ] + } + ], + "source": [ + "# The Flightless subclass retains the methods of all parent classes.\n", + "ostrich.eat()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BW2xaOeB9PDk" + }, + "source": [ + "Multiple inheritance\n", + "\n", + "Python allows a class to inherit methods from two or more classes. Suppose we want to create a SwimmingBird class and take the swimming and flying methods from two different parent classes, namely Fish and Bird." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "id": "jA-Aj_z49RYk" + }, + "outputs": [], + "source": [ + "# Let's create a parent class Fish\n", + "\n", + "\n", + "class Fish:\n", + " \"\"\"Fish Class.\"\"\"\n", + "\n", + " # and method .swim()\n", + " def swim(self) -> None:\n", + " \"\"\"Perform swimming.\"\"\"\n", + " print(\"Swimming\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "id": "CN-A0F2D9RSC" + }, + "outputs": [], + "source": [ + "# and another Bird parent class\n", + "\n", + "\n", + "class Bird2:\n", + " \"\"\"Class Bird.\"\"\"\n", + "\n", + " # and method .fly()\n", + " def fly(self) -> None:\n", + " \"\"\"Perform flying.\"\"\"\n", + " print(\"Flying\")" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "id": "udTUUUr0HKkB" + }, + "outputs": [], + "source": [ + "# Now let's create a descendant class of these two classes.\n", + "\n", + "\n", + "class SwimmingBird(Bird2, Fish):\n", + " \"\"\"Swimming Bird Class.\"\"\"\n", + "\n", + " pass # pylint: disable=unnecessary-pass" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "id": "7SfYHQItHe9I" + }, + "outputs": [], + "source": [ + "# Let's create an object of the SwimmingBird class called duck.\n", + "duck = SwimmingBird()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xogM-VUMHrd0", + "outputId": "99eac1e7-b433-4d7f-808d-fee1d0eee5b2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Flying\n" + ] + } + ], + "source": [ + "# As we can see, ducks can fly,\n", + "duck.fly()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "lHZ6WVWQJmVi", + "outputId": "9e410617-daaa-4f91-d25a-4e21be5efc26" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Swimming\n" + ] + } + ], + "source": [ + "# and swim.\n", + "duck.swim()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ruBf2MpEiN-9" + }, + "source": [ + "#### Polymorphism\n", + "\n", + "means that the same object can take different forms. In programming, polymorphism implies that operators, functions, and objects can interact with different types of data.\n", + "\n", + "For example, the + operator implies addition in the case of numbers and concatenation in the case of strings." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "57k1y3vHzS2Q", + "outputId": "580b15e7-667d-426f-9e1b-545feb183354" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + } + ], + "source": [ + "# for numbers, '+' is the addition operator\n", + "print(2 + 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "XFkxRUt2zTFb", + "outputId": "d413afd8-f001-4220-c0f0-ab14f10900dc" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "classes and objects\n" + ] + } + ], + "source": [ + "# for strings - the concatenation operator\n", + "print(\"classes\" + \" and \" + \"objects\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "syQy4yvkiRUN" + }, + "source": [ + "1. Polymorphic functions\n", + "\n", + "These are functions that can work with different types of data. A classic example is the built-in len() function." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "T23-llHTiTY2", + "outputId": "53e10046-f89b-4e08-855f-15872c223af2" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "13\n" + ] + } + ], + "source": [ + "# The len() function can be applied to a string.\n", + "print(len(\"Hello, World!\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CbWOFs8wqLKZ", + "outputId": "1bdb6886-59d4-4f7a-ea07-d269a971e358" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + } + ], + "source": [ + "# in addition, it is capable of working with a list\n", + "print(len([\"hello\", \"world\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "l03mggVpqLPx", + "outputId": "235f05b6-d75f-4a3c-b65b-5673ae460020" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "# dictionary\n", + "print(len({0: \"Programming\", 1: \"in\", 2: \"Python\"}))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "03fAyPjYiUD-" + }, + "source": [ + "2. Class polymorphism\n", + "\n", + "Class polymorphism assumes that different (unrelated) classes can have methods with the same names.\n", + "\n", + "Let's write two classes, Cat and Dog, and give them similar attributes and methods." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "id": "JexRqp8IiTig" + }, + "outputs": [], + "source": [ + "# let's create a class of cats\n", + "\n", + "\n", + "class CatClass5:\n", + " \"\"\"Cat class.\"\"\"\n", + "\n", + " # Let's define the attributes of the nickname, type, and coat color.\n", + " def __init__(self, name: str, color: str) -> None:\n", + " \"\"\"Initialize Cat with a name, color, and type.\"\"\"\n", + " self.name = name\n", + " self._type_ = \"cat\"\n", + " self.color = color\n", + "\n", + " # Let's create a .info() method to output these attributes.\n", + " def info(self) -> None:\n", + " \"\"\"Display information about the cat.\"\"\"\n", + " print(\n", + " f\"My name is {self.name}, I'm {self._type_}, the color of my fur {self.color}\"\n", + " )\n", + "\n", + " # and the .sound() method, showing that cats can meow\n", + " def sound(self) -> None:\n", + " \"\"\"States that cats can meow.\"\"\"\n", + " print(\"I can meow\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "id": "PEyzqo1qBxhZ" + }, + "outputs": [], + "source": [ + "# let's create a class of dogs\n", + "\n", + "\n", + "class DogClass5:\n", + " \"\"\"Class Dog.\"\"\"\n", + "\n", + " # with the same attributes\n", + " def __init__(self, name: str, color: str) -> None:\n", + " \"\"\"Initialize Dog with name, color, and type.\"\"\"\n", + " self.name = name\n", + " self._type_ = \"dog\"\n", + " self.color = color\n", + "\n", + " # and methods\n", + " def info(self) -> None:\n", + " \"\"\"Display information about the dog.\"\"\"\n", + " print(\n", + " f\"My name is {self.name}, I'm {self._type_}, the color of my fur {self.color}\"\n", + " )\n", + "\n", + " # although, please note, the actions within the methods differ\n", + " def sound(self) -> None:\n", + " \"\"\"Reveals that dogs can bark.\"\"\"\n", + " print(\"I know how to bark\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yxdVCLs7_vGV" + }, + "source": [ + "Let's create objects of these classes" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "id": "j5TO6c1aAHRV" + }, + "outputs": [], + "source": [ + "cat5 = CatClass5(\"Alpha\", \"black\")\n", + "dog5 = DogClass5(\"Alpha\", \"gray\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "In29ldkK_9aa" + }, + "source": [ + "In the `for` loop, we will call the attributes and methods of each class." + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5xvyicz0AGyU", + "outputId": "ab94a6c3-16e7-424d-9763-f38dfee541bb" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "My name is Alpha, I'm cat, the color of my fur black\n", + "I can meow\n", + "\n", + "My name is Alpha, I'm dog, the color of my fur gray\n", + "I know how to bark\n", + "\n" + ] + } + ], + "source": [ + "for animal in (cat5, dog5):\n", + " animal.info()\n", + " animal.sound()\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "UhIuTZgpjK-n" + }, + "source": [ + "### Programming paradigms" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "id": "D329DnitlFFM" + }, + "outputs": [], + "source": [ + "patients: list[dict[str, str | int]] = [\n", + " {\"name\": \"Nikolai\", \"height\": 178},\n", + " {\"name\": \"Ivan\", \"height\": 182},\n", + " {\"name\": \"Alex\", \"height\": 190},\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SakiQ8b0jQb5" + }, + "source": [ + "#### Procedural programming\n", + "\n", + "Procedural programming. Overall, this is the usual programming we have been practicing up to today's lesson. We define a task and sequentially arrive at the desired solution using a set of instructions." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fMwt8bYhjVG0", + "outputId": "6e503541-62ca-4f17-c384-4799190734be" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "183.33333333333334\n" + ] + } + ], + "source": [ + "# Let's create variables for overall growth and number of patients.\n", + "total, count = 0, 0\n", + "\n", + "# In the for loop, we will go through the patients (separate dictionaries)\n", + "for patient in patients:\n", + " # get the growth value and add it to the current value of the total # variable\n", + " total += int(patient[\"height\"])\n", + " # At each iteration, we will increase the patient counter by one.\n", + " count += 1\n", + "\n", + "# divide the total growth by the number of patients,\n", + "# to obtain the average value\n", + "print(total / count)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pdLaSjb-jV1y" + }, + "source": [ + "#### Object-oriented programming\n", + "\n", + "In the world of OOP, all tasks are solved not by one large program, but by classes (and objects created on their basis). As a rule, a separate class is created for each task. And although at first the use of classes may seem rather complicated, in fact it greatly simplifies the solution of many tasks." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "id": "7OKHNVZHjiTu" + }, + "outputs": [], + "source": [ + "# Let's create a class for working with data DataClass\n", + "\n", + "\n", + "class DataClass:\n", + " \"\"\"Class for working with data.\"\"\"\n", + "\n", + " # When creating an object, we will pass data to it for analysis.\n", + " def __init__(self, data: list[dict[str, str | int]]) -> None:\n", + " \"\"\"Class instance.\"\"\"\n", + " self.data = data\n", + " self.metric: str | None = None\n", + " self.__total: int | None = None\n", + " self.__count: int | None = None\n", + "\n", + " # In addition, we will create a method for calculating the average value.\n", + " def count_average(self, metric: str) -> float:\n", + " \"\"\"Расчет среднего значения по переданной метрике.\"\"\"\n", + " # The metric parameter determines which column to use to calculate the # average.\n", + " self.metric = metric\n", + "\n", + " # declare two private attributes\n", + " self.__total = 0\n", + " self.__count = 0\n", + "\n", + " # In the for loop, we will go through the list of dictionaries.\n", + " for item in self.data:\n", + "\n", + " # calculate the total amount specified in metric\n", + " # the meaning of each dictionary\n", + " self.__total += int(item[self.metric])\n", + "\n", + " # and the number of such entries\n", + " self.__count += 1\n", + "\n", + " # divide the total amount of the indicator by the number of entries\n", + " return self.__total / self.__count" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CgiUFzkLjibJ", + "outputId": "9c019f6e-adee-45f2-d837-ff4a876c12e5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "183.33333333333334" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create an object of the DataClass class and pass it patient data.\n", + "data_object = DataClass(patients)\n", + "\n", + "# call the .count_average() method with the 'height' metric\n", + "data_object.count_average(\"height\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "oIzYzt3hji9O" + }, + "source": [ + "#### Functional programming\n", + "\n", + "By and large, functional programming is a set of functions that sequentially solve a given task. The result of one function becomes the input parameter for another." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "T7rvVdD9rU4a" + }, + "source": [ + "function map()" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5PT_4ZLfqqG0", + "outputId": "e659e7fa-e06c-4e21-ef9e-26df60c55556" + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'patients' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[41], line 5\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# The lambda function will retrieve the value by the height key.\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# The map() function will apply the lambda\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# function to each dictionary nested in patients.\u001b[39;00m\n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# The list() function will convert the result into a list.\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m heights: \u001b[38;5;28mlist\u001b[39m[\u001b[38;5;28mint\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mmap\u001b[39m(\u001b[38;5;28;01mlambda\u001b[39;00m patient: \u001b[38;5;28mint\u001b[39m(patient[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mheight\u001b[39m\u001b[38;5;124m\"\u001b[39m]), patients))\n\u001b[0;32m 6\u001b[0m heights\n", + "\u001b[1;31mNameError\u001b[0m: name 'patients' is not defined" + ] + } + ], + "source": [ + "# The lambda function will retrieve the value by the height key.\n", + "# The map() function will apply the lambda\n", + "# function to each dictionary nested in patients.\n", + "# The list() function will convert the result into a list.\n", + "heights: list[int] = list(map(lambda patient: int(patient[\"height\"]), patients))\n", + "heights" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Zr0R6ibHor5X", + "outputId": "6838b211-8132-497d-efe4-7a5893d04db6" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "183.33333333333334\n" + ] + } + ], + "source": [ + "# Let's use the sum() and len() functions to find the average value.\n", + "print(sum(heights) / len(heights))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5WBvRwVxrXRg" + }, + "source": [ + "function einsum()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "id": "co4xTm4krdDn" + }, + "outputs": [], + "source": [ + "# Let's take two two-dimensional arrays.\n", + "a_np_array = np.array([[0, 1, 2], [3, 4, 5]])\n", + "\n", + "b_np_array = np.array([[5, 4], [3, 2], [1, 0]])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "D1U0EgomMX-6", + "outputId": "489d668d-1800-4032-d25b-af055a01fb12" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 5 2]\n", + " [32 20]]\n" + ] + } + ], + "source": [ + "# Multiply a and b by index j using the np.einsum() function.\n", + "einsum_result = np.einsum(\"ij, jk -> ik\", a_np_array, b_np_array)\n", + "print(einsum_result)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_07_classes.py b/python/makarov/chapter_07_classes.py new file mode 100644 index 00000000..13990e94 --- /dev/null +++ b/python/makarov/chapter_07_classes.py @@ -0,0 +1,575 @@ +"""Classes and objects in Python.""" + +import numpy as np + +# ### Creating a class + + +class CatClass: + """Cat Class.""" + + # and we will define the method .__init__() + def __init__(self) -> None: + """Initialize class instance.""" + print("Cat initializing") + + +# #### Creating an object of CatClass + +# + +# Let's create a Matroskin object of the CatClass class. +Matroskin = CatClass() + +# Let's check the data type of the created variable. +type(Matroskin) +# - + +# #### Class attributes + +# + +# Let's create an updated version of the CatClass class. + + +class CatClass1: + """Cat Class.""" + + # The __init__() method now also accepts the color parameter. + def __init__(self, color: str) -> None: + """Initialize cat class with color and type.""" + # that parameter will be stored in the self.color attribute variable + self.color = color + + # The value of the type_ attribute is specified within the class. + self.type_ = "cat" + + +# + +# Let's recreate the CatClass object, passing it the fur color parameter. +Matroskin1 = CatClass1("gray") + +# and we will print the class attributes +Matroskin1.color, Matroskin1.type_ +# - + +# #### Class methods + +# + +# Let's rewrite the CatClass class. + + +class CatClass2: + """Cat Class.""" + + # We will leave the __init__() method and attributes unchanged. + def __init__(self, color: str) -> None: + """Initialize Cat with color and type.""" + self.color = color + self.type_ = "cat" + + # lets add the .meow() method for meowing + def meow(self) -> None: + """Perform meowing..""" + for _ in range(3): + print("Meow!") + + # and the .info() method for displaying information about an object + def info(self) -> None: + """Display information about the Cat instance..""" + print(self.color, self.type_) + + +# - + +# let's create an object of the rewritten class +Matroskin2 = CatClass2("gray") + +# and we will call the .info() method +Matroskin2.meow() + +# и метод .info() +Matroskin2.info() + +# ### Principles of OOP + +# #### Encapsulation +# +# This is the ability of a class to store data and methods within itself. In other words, a class object can be represented as a capsule containing the necessary data and methods. +# +# The concepts of public and private attributes are closely related to the concept of encapsulation. Public attributes are those attributes that can be accessed outside the class "capsule." +# +# By default, all attributes in Python are public. + +# + +# change the type attribute of the Matroskin object to dog +Matroskin1.type_ = "dog" + +# let's remove this attribute +Matroskin1.type_ + + +# - + +# We would like objects of the CatClass class not to change the value of the type_ attribute. In other words, we need to make this attribute private. There are two ways to do this: +# +# Method 1. Place a single underscore before the attribute to indicate to those who will be using our code that this is a private attribute. +# +# Unfortunately, this only partially solves the problem, because the attribute can still be changed. + + +class CatClass3: + """Cat Class.""" + + def __init__(self, color: str) -> None: + """Initialize Cat with color and type.""" + self.color = color + # An underscore symbol BEFORE the attribute name indicates, + # that this is a private attribute and should not be changed outside + # the class. + self._type_ = "cat" + + +# + +# Let's create a new object of the CatClass class again. +Matroskin3 = CatClass3("gray") + +# and change the value of the _type_ attribute +Matroskin3._type_ = "dog" # pylint: disable=W0212 +Matroskin3._type_ # pylint: disable=W0212 + + +# - + +# Method 2. Place a double underscore symbol before the attribute name. Now you will not be able to directly access this class. + + +class CatClass4: + """Cat Class.""" + + def __init__(self, color: str) -> None: + """Initialize Cat with color and type.""" + self.color = color + # The double underscore symbol will prevent external access. + self.__type_ = "cat" + print(self.__type_) + + +# When attempting to call such an attribute, Python will return an error. +Matroskin4 = CatClass4("gray") +print(Matroskin4.__type_) # pylint: disable=W0212 + +# + +# However, we can access this attribute using name mangling. +# Matroskin4._CatClass4__type_ = "dog" C0103 + +# unfortunately, the value of the attribute will change +# print(Matroskin4._CatClass4__type_) +# - + +# #### Class inheritance +# +# The principle of inheritance assumes that one class inherits the attributes and methods of another. In this case, we talk about a parent class or base class and a child class or derived class. + +# Creating a parent class and a child class + +# + +# Let's create a class called Animal. + + +class Animal: + """Base class animal.""" + + # Let's define the __init__() method with + # two parameters: weight (kg) and height (cm). + def __init__(self, weight: float, length: float) -> None: + """Initialize Animal with weight and length.""" + # let's put the arguments of these parameters into the corresponding # variables + self.weight = weight + self.length = length + + # declare methods .eat() + def eat(self) -> None: + """Involves eating food.""" + print("Eating") + + # and .sleep() + def sleep(self) -> None: + """Sleep method.""" + print("Sleeping") + + +# + +# Let's create a Bird class. +# We will write the parent class Animal in brackets. + + +class Bird(Animal): + """Class Bird, descendant of class Animal.""" + + def __init__(self, weight: float, length: float) -> None: + """Initialize Bird with weight, length.""" + # Using the super() function, call the .__init__() method of the + # parent class Animal. + Animal.__init__(self, weight, length) + + # Inside the Bird class, declare a new method .move() + def move(self) -> None: + """Perform a bird flight.""" + # for birds .move() will mean "to fly" + print("Flying") + + +# - + +# Let's create a pigeon object and assign it the values of weight and length. +pigeon = Bird(0.3, 30) + +# Let's look at the attributes inherited from the Animal class. +print(pigeon.weight, pigeon.length) + +# and methods inherited from the Animal class. +pigeon.eat() + +# Now let's call a method that is specific to the Bird class. +pigeon.move() + +# ### Function `super()` +# +# Note that in the previous example, the Bird class only received new methods; no new attributes appeared in it. The thing is, if we want to add an attribute to a child class while preserving the attributes of the parent class, we need to explicitly call the latter using the super() function. + +# + +# Let's create the Bird class again. + + +class Bird1(Animal): + """Class Bird, descendant of class Animal.""" + + # Add the flight speed parameter (km/h) to the .__init__() method. + def __init__(self, weight: float, length: float, flying_speed: float) -> None: + """Initialize bird with weight, length, and flight speed.""" + # Using the super() function, + # we call the .__init__() method of + # the parent class Animal. + Animal.__init__(self, weight, length) + self.flying_speed = flying_speed + + # Let's redefine the .move() method. + def move(self) -> None: + """Perform bird flight.""" + print("Flying") + + +# - + +# Let's create another pigeon object of the Bird class, +# but this time with three parameters. +pigeon1 = Bird1(0.3, 30, 100) + +# Let's call both inherited and +# custom attributes of the Bird class. +print(pigeon1.weight, pigeon1.length, pigeon1.flying_speed) + +# call the inherited method .sleep() +pigeon1.sleep() + +# and its own .move() method +pigeon1.move() + +# #### Class redefinition +# +# An interesting feature of a descendant class in Python is that it redefines (essentially rewrites) the parent class.Let's create a subclass for flightless birds called Flightless, in which: +# +# the only attribute will be their running speed; and we will replace the result of the .move() method (which is logical) from Flying to Running. + +# + +# Let's create a subclass Flightless of the class Bird. + + +class Flightless(Bird): + """Non-Flying Bird Class.""" + + # The __init__() method of this subclass "overrides" the __init__() + # method of the parent class. + def __init__(self, weight: float, length: float, running_speed: float) -> None: + """Initialize Non-Flying Bird at running speed.""" + # Thus, we are left with only one attribute. + Bird.__init__(self, weight, length) + + self.running_speed = running_speed + + # In addition, the result of the .move() method will be 'Running'. + def move(self) -> None: + """Perform bird running.""" + print("Running") + + +# - + +# Let's create an ostrich object of the Flightless class. +ostrich = Flightless(13, 33, 60) + +# let's look at the value of the speed attribute +ostrich.running_speed + +# and check the .move() method +ostrich.move() + +# The Flightless subclass retains the methods of all parent classes. +ostrich.eat() + +# Multiple inheritance +# +# Python allows a class to inherit methods from two or more classes. Suppose we want to create a SwimmingBird class and take the swimming and flying methods from two different parent classes, namely Fish and Bird. + +# + +# Let's create a parent class Fish + + +class Fish: + """Fish Class.""" + + # and method .swim() + def swim(self) -> None: + """Perform swimming.""" + print("Swimming") + + +# + +# and another Bird parent class + + +class Bird2: + """Class Bird.""" + + # and method .fly() + def fly(self) -> None: + """Perform flying.""" + print("Flying") + + +# + +# Now let's create a descendant class of these two classes. + + +class SwimmingBird(Bird2, Fish): + """Swimming Bird Class.""" + + pass # pylint: disable=unnecessary-pass + + +# - + +# Let's create an object of the SwimmingBird class called duck. +duck = SwimmingBird() + +# As we can see, ducks can fly, +duck.fly() + +# and swim. +duck.swim() + +# #### Polymorphism +# +# means that the same object can take different forms. In programming, polymorphism implies that operators, functions, and objects can interact with different types of data. +# +# For example, the + operator implies addition in the case of numbers and concatenation in the case of strings. + +# for numbers, '+' is the addition operator +print(2 + 2) + +# for strings - the concatenation operator +print("classes" + " and " + "objects") + +# 1. Polymorphic functions +# +# These are functions that can work with different types of data. A classic example is the built-in len() function. + +# The len() function can be applied to a string. +print(len("Hello, World!")) + +# in addition, it is capable of working with a list +print(len(["hello", "world"])) + +# dictionary +print(len({0: "Programming", 1: "in", 2: "Python"})) + +# 2. Class polymorphism +# +# Class polymorphism assumes that different (unrelated) classes can have methods with the same names. +# +# Let's write two classes, Cat and Dog, and give them similar attributes and methods. + +# + +# let's create a class of cats + + +class CatClass5: + """Cat class.""" + + # Let's define the attributes of the nickname, type, and coat color. + def __init__(self, name: str, color: str) -> None: + """Initialize Cat with a name, color, and type.""" + self.name = name + self._type_ = "cat" + self.color = color + + # Let's create a .info() method to output these attributes. + def info(self) -> None: + """Display information about the cat.""" + print( + f"My name is {self.name}, I'm {self._type_}, the color of my fur {self.color}" + ) + + # and the .sound() method, showing that cats can meow + def sound(self) -> None: + """States that cats can meow.""" + print("I can meow") + + +# + +# let's create a class of dogs + + +class DogClass5: + """Class Dog.""" + + # with the same attributes + def __init__(self, name: str, color: str) -> None: + """Initialize Dog with name, color, and type.""" + self.name = name + self._type_ = "dog" + self.color = color + + # and methods + def info(self) -> None: + """Display information about the dog.""" + print( + f"My name is {self.name}, I'm {self._type_}, the color of my fur {self.color}" + ) + + # although, please note, the actions within the methods differ + def sound(self) -> None: + """Reveals that dogs can bark.""" + print("I know how to bark") + + +# - + +# Let's create objects of these classes + +cat5 = CatClass5("Alpha", "black") +dog5 = DogClass5("Alpha", "gray") + +# In the `for` loop, we will call the attributes and methods of each class. + +for animal in (cat5, dog5): + animal.info() + animal.sound() + print() + +# ### Programming paradigms + +patients: list[dict[str, str | int]] = [ + {"name": "Nikolai", "height": 178}, + {"name": "Ivan", "height": 182}, + {"name": "Alex", "height": 190}, +] + +# #### Procedural programming +# +# Procedural programming. Overall, this is the usual programming we have been practicing up to today's lesson. We define a task and sequentially arrive at the desired solution using a set of instructions. + +# + +# Let's create variables for overall growth and number of patients. +total, count = 0, 0 + +# In the for loop, we will go through the patients (separate dictionaries) +for patient in patients: + # get the growth value and add it to the current value of the total # variable + total += int(patient["height"]) + # At each iteration, we will increase the patient counter by one. + count += 1 + +# divide the total growth by the number of patients, +# to obtain the average value +print(total / count) +# - + +# #### Object-oriented programming +# +# In the world of OOP, all tasks are solved not by one large program, but by classes (and objects created on their basis). As a rule, a separate class is created for each task. And although at first the use of classes may seem rather complicated, in fact it greatly simplifies the solution of many tasks. + +# + +# Let's create a class for working with data DataClass + + +class DataClass: + """Class for working with data.""" + + # When creating an object, we will pass data to it for analysis. + def __init__(self, data: list[dict[str, str | int]]) -> None: + """Class instance.""" + self.data = data + self.metric: str | None = None + self.__total: int | None = None + self.__count: int | None = None + + # In addition, we will create a method for calculating the average value. + def count_average(self, metric: str) -> float: + """Расчет среднего значения по переданной метрике.""" + # The metric parameter determines which column to use to calculate the # average. + self.metric = metric + + # declare two private attributes + self.__total = 0 + self.__count = 0 + + # In the for loop, we will go through the list of dictionaries. + for item in self.data: + + # calculate the total amount specified in metric + # the meaning of each dictionary + self.__total += int(item[self.metric]) + + # and the number of such entries + self.__count += 1 + + # divide the total amount of the indicator by the number of entries + return self.__total / self.__count + + +# + +# Let's create an object of the DataClass class and pass it patient data. +data_object = DataClass(patients) + +# call the .count_average() method with the 'height' metric +data_object.count_average("height") +# - + +# #### Functional programming +# +# By and large, functional programming is a set of functions that sequentially solve a given task. The result of one function becomes the input parameter for another. + +# function map() + +# The lambda function will retrieve the value by the height key. +# The map() function will apply the lambda +# function to each dictionary nested in patients. +# The list() function will convert the result into a list. +heights: list[int] = list(map(lambda patient: int(patient["height"]), patients)) +heights + +# Let's use the sum() and len() functions to find the average value. +print(sum(heights) / len(heights)) + +# function einsum() + +# + +# Let's take two two-dimensional arrays. +a_np_array = np.array([[0, 1, 2], [3, 4, 5]]) + +b_np_array = np.array([[5, 4], [3, 2], [1, 0]]) +# - + +# Multiply a and b by index j using the np.einsum() function. +einsum_result = np.einsum("ij, jk -> ik", a_np_array, b_np_array) +print(einsum_result) diff --git a/python/makarov/chapter_08_lists_tuples_sets.ipynb b/python/makarov/chapter_08_lists_tuples_sets.ipynb new file mode 100644 index 00000000..0c4b4a20 --- /dev/null +++ b/python/makarov/chapter_08_lists_tuples_sets.ipynb @@ -0,0 +1,2441 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "0AoPSXyUTTLc" + }, + "outputs": [], + "source": [ + "\"\"\"Lists, tuples, and sets.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lIM5gFo4TbUg" + }, + "source": [ + "### Lists" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PPEbDV8hCAGO" + }, + "source": [ + "Basics of working with lists" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "x3wxNu5jthst", + "outputId": "9ea10800-7ade-4833-d849-424f4252cab8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[] []\n" + ] + } + ], + "source": [ + "# An empty list can be created using [] or the list() function.\n", + "# import the stemmer class and create an object\n", + "\n", + "from nltk.stem import PorterStemmer\n", + "\n", + "some_list_1: list[str] = []\n", + "some_list_2: list[str] = list() # pylint: disable=R1734\n", + "\n", + "print(some_list_1, some_list_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tLWO1t--thwP", + "outputId": "bdba1e22-059a-4ae5-b5b7-f8cf32544eec" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 'three', ['number', 'three'], {'number': 3}]" + ] + }, + "execution_count": 110, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# List elements can be numbers, strings, other lists,\n", + "# and dictionaries, among other things.\n", + "number_three = [3, \"three\", [\"number\", \"three\"], {\"number\": 3}]\n", + "number_three" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_jEdnwKSkbSE", + "outputId": "c50a7419-d925-4a2c-ec7d-f705e2c988c0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The length of the list is calculated using the len() function.\n", + "len(number_three)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9KkaG7NJDOMW" + }, + "source": [ + "Index and list slice" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "b3GS578dDRSH", + "outputId": "76a19d40-7499-4467-efd0-8d07b1b5d968" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a e\n" + ] + } + ], + "source": [ + "# the list has positive and negative indices\n", + "abc_list: list[str] = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n", + "\n", + "# let's use them to output the first and last elements\n", + "print(abc_list[0], abc_list[-1])" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "LsfIU3Z3F6Qo", + "outputId": "ad2627b5-bc55-438f-ab49-be1c0ed9814e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Igor'" + ] + }, + "execution_count": 107, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# # when working with a nested list\n", + "salary_list: list[list[str | int]] = [\n", + " [\"Anna\", 90000],\n", + " [\"Igor\", 85000],\n", + " [\"Alex\", 95000],\n", + "]\n", + "\n", + "# First, we specify the index of the nested list,\n", + "# and then the index of the element in it.\n", + "salary_list[1][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "hzcsnn7LISyc", + "outputId": "8e597d24-f23d-41a7-d055-70220a1f033f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The index can be found using the .index() method.\n", + "abc_list.index(\"c\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ARwsxkVfrFOQ", + "outputId": "3137c4c5-16bd-4ccb-e448-81cb54de5270" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The .index() method can also be applied to nested lists.\n", + "salary_list[0].index(90000)" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VvcCb_ZaItpp", + "outputId": "25c98c5c-e90b-4adc-b28d-94d4802ed786" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Tu', 'Wd', 'Th', 'Fr']" + ] + }, + "execution_count": 114, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a list with the days of the week.\n", + "days_list = [\"Mn\", \"Tu\", \"Wd\", \"Th\", \"Fr\", \"St\", \"Sn\"]\n", + "\n", + "# and we will remove the second through fifth elements inclusive\n", + "days_list[1:5]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vFJFJGigJ-kQ", + "outputId": "a0b65aff-7ef8-428c-ea4f-9bd14651f442" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Mn', 'Wd', 'Fr']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# output every second element in the slice from the first to the fifth\n", + "days_list[:5:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "n6Q6not7t9GH", + "outputId": "57d9edce-4af6-4e33-b058-147d844289e7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's check if \"Mn\" is in the list.\n", + "\"Mn\" in days_list" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "HpVMXHWDuXy7", + "outputId": "5fd5743a-2da3-41a3-f875-ae4276e1cd63" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There is such a word.\n" + ] + } + ], + "source": [ + "# if \"Tu\" is in the list\n", + "if \"Tu\" in days_list:\n", + "\n", + " # display a message\n", + " print(\"There is such a word.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "msuaGJ1OLXrB" + }, + "source": [ + "Adding, replacing, and deleting list items" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "id": "fEyyqpUDLcsY" + }, + "outputs": [], + "source": [ + "# create a list\n", + "weekdays: list[str] = [\"Monday\", \"Tuesday\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2YK5UIHOnZwq", + "outputId": "5fa9a3c3-f203-458c-a4fa-befa0b0f36a9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday', 'Thursday']" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# adding a new element with the .append() method\n", + "weekdays.append(\"Thursday\")\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Yvrd-wOMnZ9d", + "outputId": "8e85dec1-5b22-47c3-be53-25b8c2f3aa42" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday', 'Wednesday', 'Thursday']" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add an element to a specific place in the list using the desired index of\n", + "# that element\n", + "weekdays.insert(2, \"Wednesday\")\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "zPEqoCsrzKEB", + "outputId": "c7214ad0-de20-4d05-e178-0ae0b29081fe" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday', 'Wednesday', 'Friday']" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# change the fourth element in the list\n", + "weekdays[3] = \"Friday\"\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "gsWduacznqg4", + "outputId": "0ffc359c-e8dc-473a-d2dd-6bb573746afc" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday', 'Wednesday']" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# remove the element by its value\n", + "weekdays.remove(\"Friday\")\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "D2bnKXNAxmq2", + "outputId": "94426985-ebca-423b-e80a-dc3f5bc0a8b1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday']" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Remove an element by its index using the keyword del\n", + "del weekdays[2]\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "CooE-D9ouFeP", + "outputId": "149a53e2-baf6-4e8e-85a4-630ce28819a5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Tuesday'" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's do the same thing using the .pop() method.\n", + "# This method outputs the element being deleted.\n", + "weekdays.pop(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kM8rmPNXuyN6", + "outputId": "f1a810fc-ccb3-4ccf-8f25-480dbb83f25a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's see what's left on our list.\n", + "weekdays" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MWP0v0fz0IQ4" + }, + "source": [ + "Сложение списков" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cwu9M49e0HlB", + "outputId": "66ef1e04-7468-47c7-9997-fd250cedf9f3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can combine two lists using the .extend() method.\n", + "more_weekdays: list[str] = [\"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"]\n", + "\n", + "weekdays.extend(more_weekdays)\n", + "weekdays" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CE07IDeZx0cl", + "outputId": "e4674475-aa75-4468-a95b-f5a0c142300f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']\n" + ] + } + ], + "source": [ + "weekend = [\"Saturday\", \"Sunday\"]\n", + "\n", + "# or simply by combining two lists\n", + "print(weekdays + weekend)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "pJcSZ0jiz840", + "outputId": "7edd4ed0-2c01-4beb-ca00-f2e135746e97" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Monday']" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Sometimes it is useful to \"multiply\" list items.\n", + "[\"Monday\"] * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3MRsPPs30N1V", + "outputId": "5d0b022c-1487-43dc-b8dd-c4a5751187e0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Monday', 'Monday', 'Tuesday', 'Tuesday']" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# such \"works\" can also be stacked\n", + "[\"Monday\"] * 2 + [\"Tuesday\"] * 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5zWQeyD4lsk9" + }, + "source": [ + "Unpacking lists" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "id": "n6kQjWdPlv7P" + }, + "outputs": [], + "source": [ + "# there is a list\n", + "week: list[str] = [\n", + " \"Monday\",\n", + " \"Tuesday\",\n", + " \"Wednesday\",\n", + " \"Thursday\",\n", + " \"Friday\",\n", + " \"Saturday\",\n", + " \"Sunday\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "ZquIS9Lhl2z_", + "outputId": "4c532ff3-8e31-45e0-ac63-515e8b9b621d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Monday'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# By specifying the index of the element, it can be written to a variable.\n", + "monday = week[0]\n", + "monday" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1HAhG91Dl22z", + "outputId": "d0fd205e-f2c4-4888-fb93-7d0fa82464ba" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('Monday', 'Tuesday', 'Wednesday')" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the slice can be placed in several variables\n", + "monday, tuesday, wednesday = week[:3]\n", + "\n", + "# It is important that the number of cut elements is equal to the number of # variables.\n", + "monday, tuesday, wednesday" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "hfnnO_eUl25o", + "outputId": "cbf4587c-f1f0-445b-b973-64dd677f43f6" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Monday'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you can select the first element and place the rest\n", + "# in a variable with an asterisk\n", + "monday, *rest = week\n", + "monday" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7oVKz24-m9lY", + "outputId": "de4351b4-5e71-49b6-cb0b-beedca62c8c8" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('Monday', 'Sunday')" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can also do this, for example, with the first and last elements.\n", + "monday, *days, sunday = week\n", + "monday, sunday" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xgSI_44Mqlwv", + "outputId": "53e11e9b-8830-48e0-97c5-986219ff5dc0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's see what elements remain in the variable with an asterisk.\n", + "days" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CZZ2Tq0yq4l5" + }, + "source": [ + "Sorting lists" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "id": "zTBWIYWZr80H" + }, + "outputs": [], + "source": [ + "# let's take a list of numbers\n", + "nums: list[int] = [25, 10, 30, 20, 5, 15]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Zt9iwWx3q7IL", + "outputId": "b991cb38-26b3-4c26-a6d9-668056437217" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 10, 15, 20, 25, 30]" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets sort the list using the sorted() function\n", + "sorted(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vS7G44sVs0jv", + "outputId": "14debf29-01e2-48ba-9d67-120ac5d35748" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[25, 10, 30, 20, 5, 15]" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the original list has not changed\n", + "nums" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Qbi91ZlWv116", + "outputId": "09bd4d25-2a75-4517-a261-df619a283929" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 10, 15, 20, 25, 30]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's save the sorted list to a new variable\n", + "sorted_nums = sorted(nums)\n", + "sorted_nums" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "id": "J92cKG_ZsGJd" + }, + "outputs": [], + "source": [ + "# The .sort() method saves the result but does not display it immediately.\n", + "# reverse = True sets descending order\n", + "nums.sort(reverse=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tMLloVoxsdcW", + "outputId": "fa528c25-7eea-4131-dc2a-5ac2758bcc1f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[30, 25, 20, 15, 10, 5]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's show the result\n", + "nums" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kU0tmatFulXn", + "outputId": "0ea3f3cf-fdd9-48dd-b7c5-b3aea0221c28" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 10, 15, 20, 25, 30]" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The .reverse() method reverses the order, saves the result, but does not # print it.\n", + "nums.reverse()\n", + "\n", + "# it also needs to be displayed separately\n", + "nums" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BZfKDeRM3fbf", + "outputId": "163b97aa-7255-4e8d-fa57-4e932be32b20" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The reversed() function returns an iterator.\n", + "reversed(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7piJhHSn8aUW", + "outputId": "e2da4c5b-f524-4926-ed00-b59dab91cab3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[30, 25, 20, 15, 10, 5]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can display the result using the list() function.\n", + "list(reversed(nums))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ldVNvlbg8v3_", + "outputId": "bd43b64e-2679-4060-bd33-cc634c6189f1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 10, 15, 20, 25, 30]" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the result is not saved in\n", + "nums" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_Xyi6IdeuA-4" + }, + "source": [ + "Преобразование списка в строку" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "id": "iUoGSZMq0JFD" + }, + "outputs": [], + "source": [ + "# a list of string elements is given\n", + "str_list: list[str] = [\"P\", \"y\", \"t\", \"h\", \"o\", \"n\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "KuKfbsZLuER1", + "outputId": "70e66ff3-2188-42dc-e5cb-5a2f3d446c98" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Python'" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Using the .join() method, you can join all elements.\n", + "joined_str = \"\".join(str_list)\n", + "joined_str" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "WfMTmZcEzgky", + "outputId": "5e00ef97-a330-431f-c3c2-770330aaeaf3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'P_y_t_h_o_n'" + ] + }, + "execution_count": 115, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# If nothing is specified in quotation marks,\n", + "# the elements will simply be joined,\n", + "# but any other element can be specified.\n", + "joined_str_ = \"_\".join(str_list)\n", + "joined_str_" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uEFM3lgzzr_k" + }, + "source": [ + "List arithmetic" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "id": "tGBnQ-mFzwJw" + }, + "outputs": [], + "source": [ + "# there is a list of numbers\n", + "nums_: list[int] = [3, 2, 1, 4, 5, 12, 3, 3, 7, 9, 11, 15]" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VjwNZw2JzwUG", + "outputId": "e8586a86-a592-444e-9e3c-23ef494a040d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 116, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Using the .count() method,\n", + "# we can count the frequency of an element's\n", + "# occurrence in a list.\n", + "nums_.count(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rrRSZEb13P0e", + "outputId": "d64be983-954e-44e2-cf3a-d801a61a848e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 15 75\n" + ] + } + ], + "source": [ + "# In addition, we can find the minimum and\n", + "# maximum values and the sum of the elements.\n", + "print(min(nums_), max(nums_), sum(nums_))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zZKefwcpZ_rd" + }, + "source": [ + "List comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "id": "gKYUJua2aCdY" + }, + "outputs": [], + "source": [ + "# there is a list of names\n", + "# Let's leave names beginning with the letter \"A\"\n", + "names: list[str] = [\n", + " \"Artem\",\n", + " \"Anton\",\n", + " \"Alexandra\",\n", + " \"Boris\",\n", + " \"Viktor\",\n", + " \"Kenneth\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iZhNYZ7raCw_", + "outputId": "c8806615-90af-4669-da6e-ff3083e1dcba" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Artyom', 'Anton', 'Alexander']" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# First, let's solve this problem using a for loop.\n", + "\n", + "# Let's create an empty list.\n", + "a_names: list[str] = []\n", + "\n", + "# Let's go through the original list in a for loop.\n", + "for name in names:\n", + "\n", + " # Using the .startswith() method, we will\n", + " # check whether the word begins with \"A\".\n", + " if name.startswith(\"A\"):\n", + "\n", + " # if yes, add to the new list\n", + " a_names.append(name)\n", + "\n", + "# print the result\n", + "a_names" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RfU5aFoia66k", + "outputId": "fb93053e-0d50-4df5-8941-2280ad774ed7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Artyom', 'Anton', 'Alexander']" + ] + }, + "execution_count": 119, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The same task can be solved using list comprehension.\n", + "# Essentially, we are writing:\n", + "# \"What to do while there is an element in the\n", + "# list, under what condition.\"\n", + "a_names = [name for name in names if name.startswith(\"A\")]\n", + "a_names" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PtAJqkZRsQGM", + "outputId": "57ffe7da-07b4-4106-9226-e26ccf433fb0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['artem', 'anton', 'alexandra', 'boris', 'viktor', 'kenneth']" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's convert all letters to lowercase; no condition is needed here.\n", + "lower_names = [name.lower() for name in names]\n", + "lower_names" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "aj8uLZu9clcD", + "outputId": "558587b2-02a1-4339-dc8b-18e38a05d74a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['Artem', 'Anton', 'Alexandra', 'Boris', 'Vadim', 'Kenneth']" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the if-else condition is slightly different\n", + "# leave the name if it is not Victor, if it is Victor, replace it with Vadim\n", + "replace_name = [name if name != \"Viktor\" else \"Vadim\" for name in names]\n", + "replace_name" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EiKriSA89dJk", + "outputId": "a6964157-1f0e-4cf7-f53f-0cadad414ce5" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['pari', 'visit', 'lot', 'museum', 'first', 'went', 'louvr', 'largest', 'art', 'museum', 'world', 'alway', 'interest', 'art', 'spent', 'mani', 'hour', 'museum', 'enorm', 'week', 'would', 'enough']\n" + ] + } + ], + "source": [ + "# In a class on natural language processing using list comprehension,\n", + "# we applied Porter's stemmer to a list of words.\n", + "lemmatized: list[str] = [\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", + "# apply the stemmer to element s while there are elements s in the lemmatized # list\n", + "stemmed_p = [porter.stem(s) for s in lemmatized]\n", + "print(stemmed_p)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kY91ANMfXeRG" + }, + "source": [ + "### Tuples" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "aF48XEbsCsV4" + }, + "source": [ + "Basics of working with tuples" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qVBaa3SrtlYB", + "outputId": "c561c5ad-c089-450a-9300-7b1d5e2858e5" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "() ()\n" + ] + } + ], + "source": [ + "# An empty tuple can be created using empty parentheses ()\n", + "# or the tuple() function.\n", + "tuple_1: tuple[()] = ()\n", + "tuple_2: tuple[str, ...] = tuple()\n", + "print(tuple_1, tuple_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "Vv-okCt8tlau", + "outputId": "09cb5284-ae26-4057-a206-7b414437d4f3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'a'" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The elements in the array are ordered, which means there is an index.\n", + "letters = (\"a\", \"b\", \"c\")\n", + "letters[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 159 + }, + "id": "3MERPn2I_o9D", + "outputId": "353f1a99-0e22-4353-9f24-537d0077cec4" + }, + "outputs": [], + "source": [ + "# but you cannot change an element as we did in the list\n", + "# letters[0] = 'd' --> Error" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3AKPc8KEBKDl", + "outputId": "87e678c8-043c-4f31-cef1-75655c3ec8db" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['d', 'b', 'c']" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# To change an element, you first need to convert the tuple to a list.\n", + "letters_list = list(letters)\n", + "letters_list[0] = \"d\"\n", + "letters_list" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "NvRmYNY2C36p", + "outputId": "2c0a674d-e22c-4df9-b7e5-fc6faa7d995f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tuple" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# A single-element array can be created using a comma.\n", + "letter_a: tuple[str] = (\"a\",)\n", + "type(letter_a)" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "D2vQPPY8C_2G", + "outputId": "a10456d8-ae19-4ed5-d5b3-8b44d8b3e29b" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "str" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if you don't specify the comma, you will get a string\n", + "let_a = \"a\"\n", + "type(let_a)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "4VBqLLmkCyGB" + }, + "source": [ + "`enumerate()` function" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2Al5QGWAC0sc", + "outputId": "827cc64c-71e4-48f1-cae6-cf6124d5505c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 'Microsoft') \n", + "(1, 'Apple') \n", + "(2, 'Tesla') \n" + ] + } + ], + "source": [ + "companies: list[str] = [\"Microsoft\", \"Apple\", \"Tesla\"]\n", + "\n", + "# if you store the result of the enumerate() function in a single variable,\n", + "for company in enumerate(companies):\n", + "\n", + " # then we will get tuples\n", + " print(company, type(company))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OHyjLQYRL-lz" + }, + "source": [ + "Printing `dictionary` elements" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "id": "LSkNG2x1MEWX" + }, + "outputs": [], + "source": [ + "shopping_dict: dict[str, int] = {\n", + " \"cucumbers\": 2,\n", + " \"tomatoes\": 3,\n", + " \"onion\": 1,\n", + " \"potatoes\": 2,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "d_s5V8U6NFAL", + "outputId": "9b6ec1e0-25b0-4dce-b3d0-6bd0af6ea425" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('cucumbers', 2)\n", + "('tomatoes', 3)\n", + "('onion', 1)\n", + "('potatoes', 2)\n" + ] + } + ], + "source": [ + "# The same applies to the dictionary and the .items() method.\n", + "for item in shopping_dict.items():\n", + " print(item)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GlSqhwQfJbCN" + }, + "source": [ + "Unpacking tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "h1hVafb_JaUn", + "outputId": "5692e7d9-0089-42d0-987a-b884b8b62c86" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n" + ] + } + ], + "source": [ + "# Like a list, a tuple also can be unpacked into several variables.\n", + "a_var, b_var, c_var = (\"a\", \"b_var\", \"c_var\")\n", + "print(a_var)" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BFtyYKARKQPT", + "outputId": "bb7ed4cf-d02a-4219-e998-f386324a03f4" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 Microsoft\n", + "1 Apple\n", + "2 Tesla\n" + ] + } + ], + "source": [ + "companies = [\"Microsoft\", \"Apple\", \"Tesla\"]\n", + "\n", + "# We already know how to unpack into two variables\n", + "# using the enumerate() function.\n", + "for index, company_name in enumerate(companies):\n", + " print(index, company_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "pO8swT03UAeV", + "outputId": "0b68f3ab-bd57-4526-b439-9c913772ea6d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cucumbers 2\n", + "tomatoes 3\n", + "onion 1\n", + "potatoes 2\n" + ] + } + ], + "source": [ + "shopping_dict = {\n", + " \"cucumbers\": 2,\n", + " \"tomatoes\": 3,\n", + " \"onion\": 1,\n", + " \"potatoes\": 2,\n", + "}\n", + "\n", + "# the same with dictionary keys and values\n", + "\n", + "for key, value in shopping_dict.items():\n", + " print(key, value)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BZRw7ZcPCwGh" + }, + "source": [ + "`zip()` function" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Ti6oDrQjCvhb", + "outputId": "bbb46ac5-a1fa-4925-cced-7e3f2cd4e52e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 122, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if there are two or more lists\n", + "names = [\"Artyom\", \"Anton\", \"Alexander\", \"Boris\", \"Viktor\", \"Genadiy\"]\n", + "income: list[int] = [97000, 110000, 95000, 84000, 140000, 120000]\n", + "\n", + "# The zip() function will combine the first elements of the lists,\n", + "# the second elements of the lists, and so on.\n", + "zip(names, income)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "S84QKkqDHztA", + "outputId": "886a7956-4213-4349-fa15-8063782c15b3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('Artyom', 97000),\n", + " ('Anton', 110000),\n", + " ('Alexander', 95000),\n", + " ('Boris', 84000),\n", + " ('Viktor', 140000),\n", + " ('Genadiy', 120000)]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# to output the result, you need to pass the zip object to the list() function\n", + "# the output will be a list of tuples\n", + "list(zip(names, income))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xLJn10TGXhlq" + }, + "source": [ + "### Sets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "69RH3VDxWu_5" + }, + "source": [ + "Creating a `set()`" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7T9QjMN_tn5Q", + "outputId": "67e65595-422c-408e-ec10-a86901243173" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "set() {'c', 'd', 'e', 'b', 'a'} {'b', 'c', 'a'}\n" + ] + } + ], + "source": [ + "# The empty set is defined using the set() function.\n", + "set_1: set[str] = set()\n", + "\n", + "# A non-empty set is defined using the set() function and a list of elements.\n", + "set_2: set[str] = set(\"abcde\") # pylint: disable=W0130\n", + "\n", + "# or by listing elements in curly brackets {}\n", + "set_3: set[str] = {\"a\", \"b\", \"c\", \"c\"} # pylint: disable=W0130\n", + "\n", + "# the set contains only unique elements, so duplicates are removed\n", + "print(set_1, set_2, set_3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tHsQ7_dCXQkJ" + }, + "source": [ + "Adding and removing items" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "id": "VMdDL588YmOm" + }, + "outputs": [], + "source": [ + "# Let's assume that we want to create a set of vowels in the English language.\n", + "vowels: set[str] = {\"a\", \"e\", \"i\", \"o\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "A3b7LnrTuxu9", + "outputId": "5a6319ac-77ea-435c-884d-b16b4e9f3649" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a', 'e', 'i', 'o', 'ya'}" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add one letter \"ya\" using the .add() method\n", + "vowels.add(\"ya\")\n", + "vowels" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RuCG-RnTk9SZ", + "outputId": "d18e632c-25d8-42a9-e441-084807cbcd20" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a', 'e', 'i', 'o', 'ya', 'yoo'}" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's add two letters \"i\" and \"yoo\" using the .update() method.\n", + "vowels.update([\"i\", \"yoo\"])\n", + "vowels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6OJBJ5cYvwrl", + "outputId": "0693321a-76a4-4a8a-deda-d3c8b5abd101" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a', 'e', 'i', 'o'}" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if we accidentally add a consonant letter\n", + "# we can remove it using the .remove() method\n", + "vowels.add(\"ya\")\n", + "vowels.remove(\"ya\")\n", + "vowels" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uB1je436aY19" + }, + "source": [ + "Set theory in Python" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ScRveXFjagly", + "outputId": "2767f29b-0f54-492d-f9dd-3a0cccbe6048" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 104, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Two sets are equal if they contain the same elements,\n", + "# regardless of the order of the elements.\n", + "{\"a\", \"b\", \"c\"} == {\"c\", \"b\", \"a\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "O5_E1AS9JOL2", + "outputId": "807df047-e851-4a72-9035-c72316d33b59" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "# Let's calculate the power of the set using the len() function.\n", + "print(len({\"a\", \"b\", \"c\"}))" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tktbnMu4JOOY", + "outputId": "2f201ee0-3b16-4ff6-9121-de1f0155834f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# Let's check whether the element is contained in the set.\n", + "print(\"a\" in {\"a\", \"b\", \"c\"})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7LjJsYc2JORQ", + "outputId": "3d5cd120-68d9-450c-ba02-c95fb0c3f051" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "# the reverse operation is also possible\n", + "print(\"a\" not in {\"a\", \"b\", \"c\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "MF1nGQvDJOUI", + "outputId": "95c006ba-48be-4766-fa53-293ecdb1ec27" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's check whether A is a subset of B.\n", + "set_a: set[str] = {\"a\", \"b\", \"c\"}\n", + "set_b: set[str] = {\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"}\n", + "\n", + "set_a.issubset(set_b)" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Ne2zLJy3DMT7", + "outputId": "96bcbed1-0112-40f7-f012-149a229f67af" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's check whether B is a superset of A.\n", + "set_b.issuperset(set_a)" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "id": "0MxJj85iDc_y" + }, + "outputs": [], + "source": [ + "# Participants in natural language processing\n", + "# (nlp) and computer vision (cv) teams are listed.\n", + "nlp: set[str] = {\"Anna\", \"Nikolai\", \"Pavel\", \"Oksana\"}\n", + "cv: set[str] = {\"Nikolai\", \"Yevgeniy\", \"Olga\", \"Oksana\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ipXl-eO5EFKS", + "outputId": "bc4c9d32-c49f-473e-ff79-5631038a2e61" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Oksana', 'Yevgeniy', 'Pavel', 'Nikolai', 'Olga', 'Anna'}\n", + "{'Oksana', 'Yevgeniy', 'Pavel', 'Nikolai', 'Olga', 'Anna'}\n" + ] + } + ], + "source": [ + "# find those who work either in nlp, or in cv, or in both teams\n", + "\n", + "# you can use the .union() method\n", + "print(nlp.union(cv))\n", + "\n", + "# or symbol |\n", + "print(nlp | cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vkUEl3eeEnPn", + "outputId": "3606efdb-d621-4268-b072-7c05e676054b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Oksana', 'Nikolai'}\n", + "{'Oksana', 'Nikolai'}\n" + ] + } + ], + "source": [ + "# find the intersection of sets, i.e., those who work in both NLP and CV\n", + "print(nlp.intersection(cv))\n", + "print(nlp & cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mNV8c0hQExzL", + "outputId": "0a71a036-d2a9-4728-9f4a-adff5df74b4b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Anna', 'Pavel'}\n", + "{'Anna', 'Pavel'}\n" + ] + } + ], + "source": [ + "# Let's exclude those who work only in NLP,\n", + "# but not in CV or CV and NLP simultaneously.\n", + "print(nlp.difference(cv))\n", + "print(nlp - cv)" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RnawDdtME8T4", + "outputId": "9691b8dd-bc78-428c-ec7f-322a316f33ba" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Olga', 'Yevgeniy'}\n", + "{'Olga', 'Yevgeniy'}\n" + ] + } + ], + "source": [ + "# Let's exclude those who work only in CV, but not in NLP, or in NLP and CV #\n", + "# simultaneously.\n", + "print(cv.difference(nlp))\n", + "print(cv - nlp)" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "sHIWgu4ZFEqv", + "outputId": "8f8c106c-3186-4b23-f95c-5d508a708b65" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Yevgeniy', 'Pavel', 'Olga', 'Anna'}\n", + "{'Yevgeniy', 'Pavel', 'Olga', 'Anna'}\n" + ] + } + ], + "source": [ + "# find those who work either in CV or NLP, but not in both fields at the same # time\n", + "print(nlp.symmetric_difference(cv))\n", + "print(nlp ^ cv)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "8uLziVR-Z5mU" + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_08_lists_tuples_sets.py b/python/makarov/chapter_08_lists_tuples_sets.py new file mode 100644 index 00000000..ffa3557e --- /dev/null +++ b/python/makarov/chapter_08_lists_tuples_sets.py @@ -0,0 +1,515 @@ +"""Lists, tuples, and sets.""" + +# ### Lists + +# Basics of working with lists + +# + +# An empty list can be created using [] or the list() function. +# import the stemmer class and create an object + +from nltk.stem import PorterStemmer + +some_list_1: list[str] = [] +some_list_2: list[str] = list() # pylint: disable=R1734 + +print(some_list_1, some_list_2) +# - + +# List elements can be numbers, strings, other lists, +# and dictionaries, among other things. +number_three = [3, "three", ["number", "three"], {"number": 3}] +number_three + +# The length of the list is calculated using the len() function. +len(number_three) + +# Index and list slice + +# + +# the list has positive and negative indices +abc_list: list[str] = ["a", "b", "c", "d", "e"] + +# let's use them to output the first and last elements +print(abc_list[0], abc_list[-1]) + +# + +# # when working with a nested list +salary_list: list[list[str | int]] = [ + ["Anna", 90000], + ["Igor", 85000], + ["Alex", 95000], +] + +# First, we specify the index of the nested list, +# and then the index of the element in it. +salary_list[1][0] +# - + +# The index can be found using the .index() method. +abc_list.index("c") + +# The .index() method can also be applied to nested lists. +salary_list[0].index(90000) + +# + +# Let's create a list with the days of the week. +days_list = ["Mn", "Tu", "Wd", "Th", "Fr", "St", "Sn"] + +# and we will remove the second through fifth elements inclusive +days_list[1:5] +# - + +# output every second element in the slice from the first to the fifth +days_list[:5:2] + +# Let's check if "Mn" is in the list. +"Mn" in days_list + +# if "Tu" is in the list +if "Tu" in days_list: + + # display a message + print("There is such a word.") + +# Adding, replacing, and deleting list items + +# create a list +weekdays: list[str] = ["Monday", "Tuesday"] + +# adding a new element with the .append() method +weekdays.append("Thursday") +weekdays + +# add an element to a specific place in the list using the desired index of +# that element +weekdays.insert(2, "Wednesday") +weekdays + +# change the fourth element in the list +weekdays[3] = "Friday" +weekdays + +# remove the element by its value +weekdays.remove("Friday") +weekdays + +# Remove an element by its index using the keyword del +del weekdays[2] +weekdays + +# Let's do the same thing using the .pop() method. +# This method outputs the element being deleted. +weekdays.pop(1) + +# Let's see what's left on our list. +weekdays + +# Сложение списков + +# + +# You can combine two lists using the .extend() method. +more_weekdays: list[str] = ["Tuesday", "Wednesday", "Thursday", "Friday"] + +weekdays.extend(more_weekdays) +weekdays + +# + +weekend = ["Saturday", "Sunday"] + +# or simply by combining two lists +print(weekdays + weekend) +# - + +# Sometimes it is useful to "multiply" list items. +["Monday"] * 2 + +# such "works" can also be stacked +["Monday"] * 2 + ["Tuesday"] * 2 + +# Unpacking lists + +# there is a list +week: list[str] = [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +] + +# By specifying the index of the element, it can be written to a variable. +monday = week[0] +monday + +# + +# the slice can be placed in several variables +monday, tuesday, wednesday = week[:3] + +# It is important that the number of cut elements is equal to the number of # variables. +monday, tuesday, wednesday +# - + +# you can select the first element and place the rest +# in a variable with an asterisk +monday, *rest = week +monday + +# You can also do this, for example, with the first and last elements. +monday, *days, sunday = week +monday, sunday + +# Let's see what elements remain in the variable with an asterisk. +days + +# Sorting lists + +# let's take a list of numbers +nums: list[int] = [25, 10, 30, 20, 5, 15] + +# lets sort the list using the sorted() function +sorted(nums) + +# the original list has not changed +nums + +# let's save the sorted list to a new variable +sorted_nums = sorted(nums) +sorted_nums + +# The .sort() method saves the result but does not display it immediately. +# reverse = True sets descending order +nums.sort(reverse=True) + +# let's show the result +nums + +# + +# The .reverse() method reverses the order, saves the result, but does not # print it. +nums.reverse() + +# it also needs to be displayed separately +nums +# - + +# The reversed() function returns an iterator. +reversed(nums) + +# You can display the result using the list() function. +list(reversed(nums)) + +# the result is not saved in +nums + +# Преобразование списка в строку + +# a list of string elements is given +str_list: list[str] = ["P", "y", "t", "h", "o", "n"] + +# Using the .join() method, you can join all elements. +joined_str = "".join(str_list) +joined_str + +# If nothing is specified in quotation marks, +# the elements will simply be joined, +# but any other element can be specified. +joined_str_ = "_".join(str_list) +joined_str_ + +# List arithmetic + +# there is a list of numbers +nums_: list[int] = [3, 2, 1, 4, 5, 12, 3, 3, 7, 9, 11, 15] + +# Using the .count() method, +# we can count the frequency of an element's +# occurrence in a list. +nums_.count(3) + +# In addition, we can find the minimum and +# maximum values and the sum of the elements. +print(min(nums_), max(nums_), sum(nums_)) + +# List comprehension + +# there is a list of names +# Let's leave names beginning with the letter "A" +names: list[str] = [ + "Artem", + "Anton", + "Alexandra", + "Boris", + "Viktor", + "Kenneth", +] + +# + +# First, let's solve this problem using a for loop. + +# Let's create an empty list. +a_names: list[str] = [] + +# Let's go through the original list in a for loop. +for name in names: + + # Using the .startswith() method, we will + # check whether the word begins with "A". + if name.startswith("A"): + + # if yes, add to the new list + a_names.append(name) + +# print the result +a_names +# - + +# The same task can be solved using list comprehension. +# Essentially, we are writing: +# "What to do while there is an element in the +# list, under what condition." +a_names = [name for name in names if name.startswith("A")] +a_names + +# Let's convert all letters to lowercase; no condition is needed here. +lower_names = [name.lower() for name in names] +lower_names + +# the if-else condition is slightly different +# leave the name if it is not Victor, if it is Victor, replace it with Vadim +replace_name = [name if name != "Viktor" else "Vadim" for name in names] +replace_name + +# + +# In a class on natural language processing using list comprehension, +# we applied Porter's stemmer to a list of words. +lemmatized: list[str] = [ + "paris", + "visited", + "lot", + "museum", + "first", + "went", + "louvre", + "largest", + "art", + "museum", + "world", + "always", + "interested", + "art", + "spent", + "many", + "hour", + "museum", + "enormous", + "week", + "would", + "enough", +] + + +porter = PorterStemmer() + +# apply the stemmer to element s while there are elements s in the lemmatized # list +stemmed_p = [porter.stem(s) for s in lemmatized] +print(stemmed_p) +# - + +# ### Tuples + +# Basics of working with tuples + +# An empty tuple can be created using empty parentheses () +# or the tuple() function. +tuple_1: tuple[()] = () +tuple_2: tuple[str, ...] = tuple() +print(tuple_1, tuple_2) + +# The elements in the array are ordered, which means there is an index. +letters = ("a", "b", "c") +letters[0] + +# + +# but you cannot change an element as we did in the list +# letters[0] = 'd' --> Error +# - + +# To change an element, you first need to convert the tuple to a list. +letters_list = list(letters) +letters_list[0] = "d" +letters_list + +# A single-element array can be created using a comma. +letter_a: tuple[str] = ("a",) +type(letter_a) + +# if you don't specify the comma, you will get a string +let_a = "a" +type(let_a) + +# `enumerate()` function + +# + +companies: list[str] = ["Microsoft", "Apple", "Tesla"] + +# if you store the result of the enumerate() function in a single variable, +for company in enumerate(companies): + + # then we will get tuples + print(company, type(company)) +# - + +# Printing `dictionary` elements + +shopping_dict: dict[str, int] = { + "cucumbers": 2, + "tomatoes": 3, + "onion": 1, + "potatoes": 2, +} + +# The same applies to the dictionary and the .items() method. +for item in shopping_dict.items(): + print(item) + +# Unpacking tuples + +# Like a list, a tuple also can be unpacked into several variables. +a_var, b_var, c_var = ("a", "b_var", "c_var") +print(a_var) + +# + +companies = ["Microsoft", "Apple", "Tesla"] + +# We already know how to unpack into two variables +# using the enumerate() function. +for index, company_name in enumerate(companies): + print(index, company_name) + +# + +shopping_dict = { + "cucumbers": 2, + "tomatoes": 3, + "onion": 1, + "potatoes": 2, +} + +# the same with dictionary keys and values + +for key, value in shopping_dict.items(): + print(key, value) +# - + +# `zip()` function + +# + +# if there are two or more lists +names = ["Artyom", "Anton", "Alexander", "Boris", "Viktor", "Genadiy"] +income: list[int] = [97000, 110000, 95000, 84000, 140000, 120000] + +# The zip() function will combine the first elements of the lists, +# the second elements of the lists, and so on. +zip(names, income) +# - + +# to output the result, you need to pass the zip object to the list() function +# the output will be a list of tuples +list(zip(names, income)) + +# ### Sets + +# Creating a `set()` + +# + +# The empty set is defined using the set() function. +set_1: set[str] = set() + +# A non-empty set is defined using the set() function and a list of elements. +set_2: set[str] = set("abcde") # pylint: disable=W0130 + +# or by listing elements in curly brackets {} +set_3: set[str] = {"a", "b", "c", "c"} # pylint: disable=W0130 + +# the set contains only unique elements, so duplicates are removed +print(set_1, set_2, set_3) +# - + +# Adding and removing items + +# Let's assume that we want to create a set of vowels in the English language. +vowels: set[str] = {"a", "e", "i", "o"} + +# add one letter "ya" using the .add() method +vowels.add("ya") +vowels + +# Let's add two letters "i" and "yoo" using the .update() method. +vowels.update(["i", "yoo"]) +vowels + +# if we accidentally add a consonant letter +# we can remove it using the .remove() method +vowels.add("ya") +vowels.remove("ya") +vowels + +# Set theory in Python + +# Two sets are equal if they contain the same elements, +# regardless of the order of the elements. +{"a", "b", "c"} == {"c", "b", "a"} + +# Let's calculate the power of the set using the len() function. +print(len({"a", "b", "c"})) + +# Let's check whether the element is contained in the set. +print("a" in {"a", "b", "c"}) + +# the reverse operation is also possible +print("a" not in {"a", "b", "c"}) + +# + +# Let's check whether A is a subset of B. +set_a: set[str] = {"a", "b", "c"} +set_b: set[str] = {"a", "b", "c", "d", "e", "f"} + +set_a.issubset(set_b) +# - + +# Let's check whether B is a superset of A. +set_b.issuperset(set_a) + +# Participants in natural language processing +# (nlp) and computer vision (cv) teams are listed. +nlp: set[str] = {"Anna", "Nikolai", "Pavel", "Oksana"} +cv: set[str] = {"Nikolai", "Yevgeniy", "Olga", "Oksana"} + +# + +# find those who work either in nlp, or in cv, or in both teams + +# you can use the .union() method +print(nlp.union(cv)) + +# or symbol | +print(nlp | cv) +# - + +# find the intersection of sets, i.e., those who work in both NLP and CV +print(nlp.intersection(cv)) +print(nlp & cv) + +# Let's exclude those who work only in NLP, +# but not in CV or CV and NLP simultaneously. +print(nlp.difference(cv)) +print(nlp - cv) + +# Let's exclude those who work only in CV, but not in NLP, or in NLP and CV # +# simultaneously. +print(cv.difference(nlp)) +print(cv - nlp) + +# find those who work either in CV or NLP, but not in both fields at the same # time +print(nlp.symmetric_difference(cv)) +print(nlp ^ cv) diff --git a/python/makarov/chapter_09_dictionaries.ipynb b/python/makarov/chapter_09_dictionaries.ipynb new file mode 100644 index 00000000..ea8ae80f --- /dev/null +++ b/python/makarov/chapter_09_dictionaries.ipynb @@ -0,0 +1,2648 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Dictionaries in Python.'" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Dictionaries in Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AEHY4SW_3mIj" + }, + "source": [ + "#### Creating a `dict()`" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "x3wxNu5jthst", + "outputId": "eedbd51a-e6ce-4a0f-ac35-7d57c4cc59ef" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{} {}\n" + ] + } + ], + "source": [ + "# An empty dictionary can be created using {} or the dict() function.\n", + "# Import the Counter class.\n", + "from collections import Counter\n", + "\n", + "# import the pprint() function from the pprint module\n", + "# it outputs some data structures better than the usual print()\n", + "from pprint import pprint\n", + "\n", + "import numpy as np\n", + "\n", + "dict_1: dict[str, str] = {}\n", + "dict_2: dict[str, str] = dict() # pylint: disable=R1735\n", + "print(dict_1, dict_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tLWO1t--thwP", + "outputId": "c802fcb0-3757-40ab-94c2-44fae324b0db" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'name': 'Toyota', 'founded': 1937, 'founder': 'Kiichiro Toyoda'}" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the dictionary can be filled\n", + "# with keys and values right away\n", + "company: dict[str, str | int] = {\n", + " \"name\": \"Toyota\",\n", + " \"founded\": 1937,\n", + " \"founder\": \"Kiichiro Toyoda\",\n", + "}\n", + "company" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "pBONkfBYZRkZ", + "outputId": "f364cd9b-bbac-4011-e7f4-069889ac14df" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'TYO': 'Toyota', 'TSLA': 'Tesla', 'F': 'Ford'}" + ] + }, + "execution_count": 135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# A dictionary can be created from nested lists.\n", + "tickers: dict[str, str] = dict([[\"TYO\", \"Toyota\"], [\"TSLA\", \"Tesla\"], [\"F\", \"Ford\"]])\n", + "tickers" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "y5zC4qKWbUn3", + "outputId": "becdc0ee-1018-4dee-d6e9-9a861791c5c7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'k1': 0, 'k2': 0, 'k3': 0}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if you put the keys in a tuple\n", + "keys: tuple[str, ...] = (\"k1\", \"k2\", \"k3\")\n", + "# and set the value for all keys\n", + "value_global = 0\n", + "\n", + "# then, using the .fromkeys() method, you can create a dictionary\n", + "# with these keys and a specified value for each of them\n", + "empty_values = dict.fromkeys(keys, value_global)\n", + "empty_values" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SdW5ePii6BGZ" + }, + "source": [ + "#### Dictionary keys and values" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W9vaAXb2zKVb" + }, + "source": [ + "Types of dictionary elements" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "d0bh3eRu6EAy", + "outputId": "ef5c819c-8445-4b53-d843-19154d4f3e47" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'k1': 123,\n", + " 'k2': 'string',\n", + " 'k3': nan,\n", + " 'k4': True,\n", + " 'k5': None,\n", + " 'k6': [1, 2, 3],\n", + " 'k7': array([1, 2, 3]),\n", + " 'k8': {1: 'v1', 2: 'v2', 3: 'v3'}}" + ] + }, + "execution_count": 134, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's give an example of what the\n", + "# dictionary values might be.\n", + "\n", + "val_types: dict[str, int | str | bool | None | list[int] | object | float] = {\n", + " \"k1\": 123,\n", + " \"k2\": \"string\",\n", + " \"k3\": np.nan, # none type\n", + " \"k4\": True, # boolean type\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", + "val_types" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AktD-qd772bs" + }, + "source": [ + "```.keys(), .values() и .items()``` methods" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "id": "FoLHc64C716M" + }, + "outputs": [], + "source": [ + "# Example of a dictionary representing a person\n", + "person: dict[str, str | int | list[str]] = {\n", + " \"first name\": \"Ivan\",\n", + " \"last name\": \"Ivanov\",\n", + " \"born\": 1980,\n", + " \"dept\": \"IT\",\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8Gl7ZMqt8wuZ", + "outputId": "708807b9-c8e5-478c-ac25-baee23c1a0ad" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['first name', 'last name', 'born', 'dept'])\n" + ] + } + ], + "source": [ + "# lets see the keys of the dictionary\n", + "print(person.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "j3mruPRR8xgX", + "outputId": "06bbf715-5091-45c5-d84a-8bfcdefdcf76" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_values(['Ivan', 'Ivanov', 1980, 'IT'])\n" + ] + } + ], + "source": [ + "# values of the dictionary\n", + "print(person.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "wfmjr1bu81Ay", + "outputId": "53c39b8e-dc1f-4be5-800b-97f534efc66c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_items([('first name', 'Ivan'), ('last name', 'Ivanov'), ('born', 1980), ('dept', 'IT')])\n" + ] + } + ], + "source": [ + "# items of the dictionary\n", + "print(person.items())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YxrdHML389v4" + }, + "source": [ + "Using a for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ssN6LrjO83h8", + "outputId": "1d079d55-69b3-4f88-8f58-d34896f7945e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "first name Ivan\n", + "last name Ivanov\n", + "born 1980\n", + "dept IT\n" + ] + } + ], + "source": [ + "# keys and values can be output in a for loop\n", + "for key, value_p in person.items():\n", + " print(key, value_p)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zU-JtgYJ-vyO" + }, + "source": [ + "Key access and method `.get()`" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "Au-MDTwZ-tGI", + "outputId": "3ba22481-65b9-43b9-8be3-e68bc38d87a1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Ivanov'" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the value can be viewed by key\n", + "person[\"last name\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 159 + }, + "id": "XwWDSYzH-O0l", + "outputId": "dbc6b773-bbcd-45f9-c0ac-bab705e05338" + }, + "outputs": [], + "source": [ + "# if there is no such key,\n", + "# Python will return an error\n", + "# person['education'] --> Error" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dx2nFVH7eils", + "outputId": "b9ff14d3-4bea-41c7-b838-4560ddd3d228" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "# To prevent this from happening, you can use the .get() method.\n", + "# By default, if the key is missing, it returns the value None.\n", + "print(person.get(\"education\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qTovRCnIb1ei", + "outputId": "e0bbb24f-00fb-4c43-f611-fc4ad8866598" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1980\n" + ] + } + ], + "source": [ + "# if the key does exist,\n", + "# .get() will return the corresponding value\n", + "print(person.get(\"born\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "IBgf5Al-aCOK" + }, + "source": [ + "Checking whether a key and value are in the dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XbRxj_nPaHJU", + "outputId": "faa46646-4e20-432b-dbe8-c68e06ff9699" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# let's check if there is such a key in the dictionary\n", + "print(\"born\" in person)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "sAKfv79KbC1p", + "outputId": "3f9562bd-fab8-4a29-abee-ec82d9d85fae" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# and now let's check if there is such a value in the dictionary\n", + "print(1980 in person.values())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UelKiVrybH30", + "outputId": "0f5eacb2-eb21-4ef2-b818-9e66500e1227" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "# You can also check for the presence\n", + "# of both the key and the value at the same time.\n", + "print((\"born\", 1980) in person.items())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kY91ANMfXeRG" + }, + "source": [ + "### Basic operation with dictionary types in Python" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ebptqYBRcrJp" + }, + "source": [ + "#### Adding and changing elements" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qVBaa3SrtlYB", + "outputId": "83fbde38-1fff-4e8c-c2c5-5de94465eca9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'dept': 'IT',\n", + " 'languages': ['Python', 'C++']}" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can add an element by assigning a new value to the new key.\n", + "# Please note that in this case, the new value is a list.\n", + "person[\"languages\"] = [\"Python\", \"C++\"]\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Vv-okCt8tlau", + "outputId": "74f5f097-72cc-4539-ba8c-f4baf7223a83" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'dept': 'IT',\n", + " 'languages': ['Python']}" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can change an element by assigning a new value to the existing key.\n", + "# The value is still a list, but it consists of a single element.\n", + "person[\"languages\"] = [\"Python\"]\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FBO1GOoDHXjc", + "outputId": "87efcd08-cdd8-47cb-ac39-52807319d17c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'dept': 'IT',\n", + " 'languages': ['Python'],\n", + " 'job': 'programmer',\n", + " 'experience': 7}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now let's create a new dictionary with new elements\n", + "new_elements: dict[str, str | int] = {\"job\": \"programmer\", \"experience\": 7}\n", + "\n", + "# and add it to the existing dictionary using the .update() method\n", + "person.update(new_elements)\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8ABSReiDS86F", + "outputId": "f7c2c895-86fc-451c-a619-56514d1b4ad2" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'dept': 'IT',\n", + " 'languages': ['Python'],\n", + " 'job': 'programmer',\n", + " 'experience': 7}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The .setdefault() method checks whether the key exists in the dictionary.\n", + "# If it does, the value will not change.\n", + "person.setdefault(\"last name\", \"Petrov\")\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "uq1eR4FEYIFx", + "outputId": "b9ca0002-c8bc-458c-b978-c86413159dfb" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'dept': 'IT',\n", + " 'languages': ['Python'],\n", + " 'job': 'programmer',\n", + " 'experience': 7,\n", + " 'f_languages': ['russian', 'english']}" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if not, a new key and corresponding value will be added\n", + "person.setdefault(\"f_languages\", [\"russian\", \"english\"])\n", + "person" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wUMTWNK-fFsd" + }, + "source": [ + "#### Deleting elements" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "AKViA8ItfIye", + "outputId": "037a5a8d-0b08-4c4a-aec2-29e4eea7e49e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "IT\n" + ] + } + ], + "source": [ + "# The .pop() method removes an element by key and outputs the value being # removed.\n", + "print(person.pop(\"dept\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "anOK_5RVh8eG", + "outputId": "9a696c51-117c-42cc-aa12-3049452b3111" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'first name': 'Ivan',\n", + " 'last name': 'Ivanov',\n", + " 'born': 1980,\n", + " 'languages': ['Python'],\n", + " 'job': 'programmer',\n", + " 'experience': 7,\n", + " 'f_languages': ['russian', 'english']}" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and we will see the updated dictionary\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "id": "t6flk9z_fluM" + }, + "outputs": [], + "source": [ + "# The keyword del also removes an element by key.\n", + "# The value being removed is not displayed.\n", + "del person[\"born\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6aruZx9MKBUK", + "outputId": "0334ba54-fb22-460f-a83a-99ce528947be" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('f_languages', ['russian', 'english'])" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The .popitem() method removes the last added element and outputs it.\n", + "person.popitem()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tH_TmTAgf1Qc", + "outputId": "77b794f7-1026-4973-b30b-835773e2aa9d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The .clear() method removes\n", + "# all elements from the dictionary.\n", + "person.clear()\n", + "person" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "KQzvF_SmHFYa" + }, + "outputs": [], + "source": [ + "# The keyword del also allows\n", + "# you to delete the entire dictionary.\n", + "del person" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 159 + }, + "id": "41jpFZaGA3U3", + "outputId": "659769e5-c524-40b6-cc40-e0253b2ab52f" + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'person' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[38], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Let's make sure that this dictionary no longer exists.\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m person\n", + "\u001b[1;31mNameError\u001b[0m: name 'person' is not defined" + ] + } + ], + "source": [ + "# Let's make sure that this dictionary no longer exists.\n", + "person" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VS8k8X8kwAhj" + }, + "source": [ + "#### Sorting dictionaries" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "id": "u3rg89UKwE1e" + }, + "outputs": [], + "source": [ + "# let's take a simple dictionary to demonstrate sorting\n", + "dict_to_sort: dict[str, int] = {\"k2\": 30, \"k1\": 20, \"k3\": 10}" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bTwIep0qwFW8", + "outputId": "117cde36-cd88-49b3-ba59-7b52cb3e70d1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['k1', 'k2', 'k3']" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# sort the keys\n", + "sorted(dict_to_sort)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tnJvCeBxna2q", + "outputId": "544cdf21-7661-4fb1-cdcb-c1d39fec5eab" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[10, 20, 30]" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and values\n", + "sorted(dict_to_sort.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jYQNHiJrMhSA", + "outputId": "cbfcc983-24f9-4c9f-bea1-f2c5dcfd806d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_items([('k2', 30), ('k1', 20), ('k3', 10)])" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's look at the key:value pairs.\n", + "dict_to_sort.items()" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2Lbe96f0nh85", + "outputId": "3a86244b-ab49-4aad-b350-58d7abd88883" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('k1', 20), ('k2', 30), ('k3', 10)]" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# to sort them by key (index [0])\n", + "# we will use the .items() method and a lambda function\n", + "sorted(dict_to_sort.items(), key=lambda item: item[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Vl9gs9fVoE-A", + "outputId": "bd90cb3f-4e6a-4c6f-91e8-77b84df8b85f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('k3', 10), ('k1', 20), ('k2', 30)]" + ] + }, + "execution_count": 102, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Sorting by value is performed in the same way, however,\n", + "# we pass the index [1] to the lambda function.\n", + "sorted(dict_to_sort.items(), key=lambda item: item[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "v9aK8-q2CdXO" + }, + "source": [ + "#### Copying dictionaries" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "id": "ysVmXSyVFZMU" + }, + "outputs": [], + "source": [ + "# Let's create a source dictionary\n", + "# with the number of students in the first\n", + "# and second years of university.\n", + "original: dict[str, int] = {\"First course\": 174, \"Second Course\": 131}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DYkMoaN3GL1X" + }, + "source": [ + "Copying with method `copy()`" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-t7mXlsUCc2p", + "outputId": "877c2f4b-629f-48d4-cca6-3a0fa71151f1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'First course': 174, 'Second Course': 131}\n", + "{'First course': 174, 'Second Course': 131, 'Third course': 117}\n" + ] + } + ], + "source": [ + "# Let's create a copy of this dictionary using the .copy() method.\n", + "new_1 = original.copy()\n", + "\n", + "# add information about the third course to the new dictionary\n", + "new_1[\"Third course\"] = 117\n", + "\n", + "# the source dictionary has not changed\n", + "print(original)\n", + "print(new_1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "h9IslECkGSsr" + }, + "source": [ + "Copying with `=` operator but its not recommended" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cQZ-uDDpEvkO", + "outputId": "99f751ae-396c-4a2c-ffd8-f06a75b6bb57" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{}\n", + "{}\n" + ] + } + ], + "source": [ + "# transfer the source dictionary to a new variable\n", + "new_2 = original\n", + "\n", + "# delete elements of the new dictionary\n", + "new_2.clear()\n", + "\n", + "# data has also been deleted from the source dictionary\n", + "print(original)\n", + "print(new_2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3iDksQfFNiux" + }, + "source": [ + "### `dir()` function" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nv3sToYdNmTd", + "outputId": "10c4048b-b1b3-471f-838d-9d211546fee3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__']\n" + ] + } + ], + "source": [ + "# The dir() function returns\n", + "# all methods of the object passed to it.\n", + "some_dict = {\"k\": 1}\n", + "\n", + "# Special methods come first.\n", + "# They begin and end with the symbol '__'.\n", + "# Let's display the first 11 elements.\n", + "print(dir(some_dict)[:11])" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UkqCOYF0su5e", + "outputId": "7074b3c3-e901-44d7-bd5a-9b8d3d865a3a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'k': 1}\n" + ] + } + ], + "source": [ + "# when we pass our dictionary to the print() function,\n", + "print(some_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "BGLlQ1PhqEKF", + "outputId": "cf166c59-ba9f-4f1c-d1ac-6b7ec6ce0a57" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\"{'k': 1}\"" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# In fact, we apply the .__str__() method to the object.\n", + "some_dict.__str__() # pylint: disable=C2801" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "s2PqsanmtAE4", + "outputId": "eb3b4328-96cf-4339-8c4b-365948c4834c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']\n" + ] + } + ], + "source": [ + "# In most cases, we will be interested in methods without '__'.\n", + "methods = dir(some_dict)[-11:]\n", + "print(methods)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7fi2zJoGvh5v" + }, + "source": [ + "### Dict comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "id": "Qr-HfxbHv_if" + }, + "outputs": [], + "source": [ + "# Let's create another simple dictionary\n", + "source_dict: dict[str, int] = {\"k1\": 2, \"k2\": 4, \"k3\": 6}" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "wqP1P4EcwAC4", + "outputId": "af999e25-fed2-4303-e69a-182fdab468f5" + }, + "outputs": [], + "source": [ + "# Using dict comprehension, multiply each value by two\n", + "new_source_dict = {\n", + " key: value * 2 for (key, value) in source_dict.items()\n", + "} # pylint: disable=C0301" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "l1w42uT0Kf1b", + "outputId": "906ee62e-c5d0-498c-d6ff-ba99c4352f14" + }, + "outputs": [], + "source": [ + "# make all key characters uppercase\n", + "new_source_dict = {key.upper(): value for (key, value) in source_dict.items()}" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XKoh7SUJ5S8z", + "outputId": "785a0735-56eb-4599-8a1c-ac788c8f7dce" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'k2': 4}\n" + ] + } + ], + "source": [ + "# add a condition that the value must be\n", + "# greater than two AND less than six\n", + "new_dict_1 = {\n", + " key: value\n", + " for (key, value) in source_dict.items()\n", + " if value > 2\n", + " if value < 6 # pylint: disable=C0301\n", + "}\n", + "\n", + "print(new_dict_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "I1nyzDSi6V3Y", + "outputId": "72f66774-7065-4815-d211-ef06ebd318ee" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'k2': 4}" + ] + }, + "execution_count": 110, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_dict: dict[str, int] = {}\n", + "\n", + "# when solving the same problem in a for loop\n", + "for key, value in source_dict.items():\n", + "\n", + " # we would use logical AND\n", + " if 2 < value < 6:\n", + "\n", + " # if the conditions are true, write the key and\n", + " # value to a new dictionary\n", + " new_dict[key] = value\n", + "\n", + "new_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-rJUlsr563N7", + "outputId": "00c0b343-8ccb-4cfb-9ef3-f5568de87730" + }, + "outputs": [], + "source": [ + "# The if-else condition is placed at the very beginning\n", + "# of the dict comprehension scheme.\n", + "# We will replace the value with the word even if it is even,\n", + "# and odd if it is odd.\n", + "even_odd_dict: dict[str, str] = {\n", + " key: (\"even\" if value % 2 == 0 else \"odd\")\n", + " for (key, value) in source_dict.items() # pylint: disable=C0301\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3sCsWyonkkGM", + "outputId": "3dacd13e-10d3-44a7-8f23-3898e5840d13" + }, + "outputs": [], + "source": [ + "# dict comprehension can be used\n", + "# instead of the .fromkeys() method.\n", + "keys = (\"k1\", \"k2\", \"k3\")\n", + "# Pass the keys from the keys tuple to\n", + "# the dictionary and set the value of each to 0.\n", + "zeros_dict = {key: 0 for key in keys}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HplemEzXwNw0" + }, + "source": [ + "### Additional examples" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9I3D7qej8JFO" + }, + "source": [ + "#### lambda-functions, and `map()`, `zip()` functions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NQxOQz-_jilk" + }, + "source": [ + "Example with `list()`" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "id": "ZXoJ1TMsh13z" + }, + "outputs": [], + "source": [ + "# Lets take a list of words\n", + "words: list[str] = [\"apple\", \"banana\", \"fig\", \"blackberry\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BSyuvd278UPf", + "outputId": "4e410273-cca8-475f-e132-b2809c9ee789" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[4,\n", + " 2,\n", + " 4,\n", + " 2,\n", + " 5,\n", + " 2,\n", + " 7,\n", + " 1,\n", + " 3,\n", + " 2,\n", + " 7,\n", + " 2,\n", + " 5,\n", + " 4,\n", + " 2,\n", + " 3,\n", + " 6,\n", + " 3,\n", + " 7,\n", + " 3,\n", + " 6,\n", + " 2,\n", + " 3,\n", + " 7,\n", + " 4,\n", + " 6,\n", + " 4,\n", + " 10,\n", + " 2,\n", + " 3,\n", + " 2,\n", + " 1,\n", + " 5,\n", + " 4,\n", + " 5,\n", + " 5,\n", + " 3,\n", + " 6,\n", + " 2,\n", + " 8,\n", + " 2,\n", + " 1,\n", + " 4,\n", + " 5,\n", + " 5,\n", + " 3,\n", + " 2,\n", + " 6]" + ] + }, + "execution_count": 123, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create a lambda function that calculates\n", + "# the length of the word passed to it.\n", + "# Using the map() function, apply the lambda function\n", + "# to each element of the words list\n", + "# and place the word lengths in a new list\n", + "# called length using the list() function.\n", + "length = list(map(len, words))\n", + "length" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "b0JRdAJHh2df", + "outputId": "5eda6227-fd0c-4170-c487-81c10956a8db" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'when': 4, 'we': 2, 'were': 4, 'in': 2, 'paris': 5, 'visited': 7, 'a': 1, 'lot': 3, 'of': 2, 'museums': 7, 'first': 5, 'went': 4, 'to': 2, 'the': 3, 'louvre': 6, 'largest': 7, 'art': 3, 'museum': 6, 'world.i': 7, 'have': 4, 'always': 6, 'been': 4, 'interested': 10, 'so': 2, 'i': 1, 'spent': 5, 'many': 4, 'hours': 5, 'there': 5, 'is': 2, 'enormous': 8, 'week': 4, 'would': 5, 'not': 3, 'be': 2, 'enough': 6}\n" + ] + } + ], + "source": [ + "# Using the zip() function, we will concatenate\n", + "# both lists element by element\n", + "# and convert them into a dictionary.\n", + "from_zip_dict = dict(zip(words, length))\n", + "print(from_zip_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kYNYaOQ-9-V6", + "outputId": "f3887c5f-3134-4c9f-cba7-9e55f340e20d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'when': 4, 'we': 2, 'were': 4, 'in': 2, 'paris': 5, 'visited': 7, 'a': 1, 'lot': 3, 'of': 2, 'museums': 7, 'first': 5, 'went': 4, 'to': 2, 'the': 3, 'louvre': 6, 'largest': 7, 'art': 3, 'museum': 6, 'world.i': 7, 'have': 4, 'always': 6, 'been': 4, 'interested': 10, 'so': 2, 'i': 1, 'spent': 5, 'many': 4, 'hours': 5, 'there': 5, 'is': 2, 'enormous': 8, 'week': 4, 'would': 5, 'not': 3, 'be': 2, 'enough': 6}\n" + ] + } + ], + "source": [ + "# The same can be done using the zip() function\n", + "# and list comprehension.\n", + "zip_length_dict = dict(zip(words, [len(word) for word in words]))\n", + "print(zip_length_dict)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PUs12XYyjmBh" + }, + "source": [ + "Example with `dictionary()`" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "id": "0ZVWDzRMjo-6" + }, + "outputs": [], + "source": [ + "# let's take a dictionary with people's height in feet\n", + "height_feet: dict[str, float] = {\n", + " \"Alex\": 6.1,\n", + " \"Jerry\": 5.4,\n", + " \"Ben\": 5.8,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "irwOj3Rt_M1e", + "outputId": "3f5be590-39ab-4dbf-b475-4ab6afc82d7a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.85928, 1.6459200000000003, 1.76784]" + ] + }, + "execution_count": 115, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# To convert feet to meters, let's create a lambda\n", + "# function lambda m: m * 0.3048\n", + "# Apply this function to the dictionary\n", + "# values using the map() function\n", + "# Convert to a list\n", + "metres = list(map(lambda m: m * 0.3048, height_feet.values()))\n", + "metres" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RcqkuR4WjsnB", + "outputId": "74026d78-3508-4898-9502-70f84f556a5d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Alex': 1.86, 'Jerry': 1.65, 'Ben': 1.77}" + ] + }, + "execution_count": 116, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Using the zip() function, we will connect the keys\n", + "# of the source dictionary with the elements of the list metres.\n", + "dict(zip(height_feet.keys(), np.round(metres, 2)))" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "pxqmUJG7CEtO", + "outputId": "b3ee3331-c47a-42ac-ac3c-17f82987d4d3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Alex': 1.86, 'Jerry': 1.65, 'Ben': 1.77}\n" + ] + } + ], + "source": [ + "# The same can be done using dict comprehensions.\n", + "# All in one line.\n", + "# We simply convert the dictionary values to meters.\n", + "students_heights_dict = {\n", + " key: np.round(value * 0.3048, 2) for (key, value) in height_feet.items()\n", + "}\n", + "print(students_heights_dict)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "I-UUEhQNvezN" + }, + "source": [ + "#### Nested dictionaries" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "id": "OA69rLjwwTAc" + }, + "outputs": [], + "source": [ + "# let's take a dictionary with employee IDs as keys\n", + "employees: dict[str, dict[str, str | int | float]] = {\n", + " \"id1\": {\n", + " \"first name\": \"Alexander\",\n", + " \"last name\": \"Ivanov\",\n", + " \"age\": 30,\n", + " \"job\": \"Programmer\",\n", + " },\n", + " \"id2\": {\n", + " \"first name\": \"Olga\",\n", + " \"last name\": \"Petrova\",\n", + " \"age\": 35,\n", + " \"job\": \"ML-engineer\",\n", + " },\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8UNwQKCANq0J", + "outputId": "a9831ab9-878a-4201-dc20-1d0a741eca26" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'first name': 'Alexander', 'last name': 'Ivanov', 'age': 30, 'job': 'Programmer'}\n", + "{'first name': 'Olga', 'last name': 'Petrova', 'age': 35, 'job': 'ML-engineer'}\n" + ] + } + ], + "source": [ + "# and values - nested dictionaries with information about them\n", + "for value_e in employees.values():\n", + " print(value_e)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xBRzL0hdkF95" + }, + "source": [ + "##### Basics operations" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0Hx_jDxnOBF3", + "outputId": "c7767b24-5831-436b-cd71-d04d2917a9aa" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30\n" + ] + } + ], + "source": [ + "# To retrieve the value of an element in a nested dictionary,\n", + "# we will use a double key.\n", + "print(employees[\"id1\"][\"age\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iUNy0ji7ORNC", + "outputId": "8e0c2822-2aac-4c93-9998-3c9547edf06e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id1': {'age': 30,\n", + " 'first name': 'Alexander',\n", + " 'job': 'Programmer',\n", + " 'last name': 'Ivanov'},\n", + " 'id2': {'age': 35,\n", + " 'first name': 'Olga',\n", + " 'job': 'ML-engineer',\n", + " 'last name': 'Petrova'},\n", + " 'id3': {'age': 27,\n", + " 'first name': 'Darya',\n", + " 'job': 'web-designer',\n", + " 'last name': 'Nekrasova'}}\n" + ] + } + ], + "source": [ + "# add information about the new employee\n", + "employees[\"id3\"] = {\n", + " \"first name\": \"Darya\",\n", + " \"last name\": \"Nekrasova\",\n", + " \"age\": 27,\n", + " \"job\": \"web-designer\",\n", + "}\n", + "\n", + "# and display the updated dictionary using the pprint() function\n", + "pprint(employees)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mHmC4hPGwTC_", + "outputId": "897b5449-4fed-4df6-a538-be532c3c6fcf" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id1': {'age': 30,\n", + " 'first name': 'Alexander',\n", + " 'job': 'Programmer',\n", + " 'last name': 'Ivanov'},\n", + " 'id2': {'age': 35,\n", + " 'first name': 'Olga',\n", + " 'job': 'ML-engineer',\n", + " 'last name': 'Petrova'},\n", + " 'id3': {'age': 26,\n", + " 'first name': 'Darya',\n", + " 'job': 'web-designer',\n", + " 'last name': 'Nekrasova'}}\n" + ] + } + ], + "source": [ + "# You can also change the value of a nested dictionary using a double key.\n", + "employees[\"id3\"][\"age\"] = 26\n", + "pprint(employees)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kP8KzxtckMf0" + }, + "source": [ + "##### `for` loops" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rfKMVzEGlUf1", + "outputId": "7567b97d-4963-4dc8-eb09-73d2c84d9775" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id1': {'age': 30.0,\n", + " 'first name': 'Alexander',\n", + " 'job': 'Programmer',\n", + " 'last name': 'Ivanov'},\n", + " 'id2': {'age': 35.0,\n", + " 'first name': 'Olga',\n", + " 'job': 'ML-engineer',\n", + " 'last name': 'Petrova'},\n", + " 'id3': {'age': 26.0,\n", + " 'first name': 'Darya',\n", + " 'job': 'web-designer',\n", + " 'last name': 'Nekrasova'}}\n" + ] + } + ], + "source": [ + "# change the data type in the age information from int to float\n", + "\n", + "# To do this, we will first go through the nested dictionaries,\n", + "# i.e., the values of info in the external dictionary employees.\n", + "for info in employees.values():\n", + "\n", + " # then by keys and values of the nested dictionary info\n", + " for key_info, value_info in info.items():\n", + "\n", + " # if the key matches the word 'age'\n", + " if key_info == \"age\":\n", + "\n", + " # convert the value to float type\n", + " info[key_info] = float(value_info)\n", + "\n", + "pprint(employees)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HO97JxkUkZyR" + }, + "source": [ + "##### Nested dictionaries and dict comprehension\n" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-lBSDGLtm62e", + "outputId": "11b6677f-5514-4a7f-c868-7959c26b0e3a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id1': {'age': 30.0,\n", + " 'first name': 'Alexander',\n", + " 'job': 'Programmer',\n", + " 'last name': 'Ivanov'},\n", + " 'id2': {'age': 35.0,\n", + " 'first name': 'Olga',\n", + " 'job': 'ML-engineer',\n", + " 'last name': 'Petrova'},\n", + " 'id3': {'age': 26.0,\n", + " 'first name': 'Darya',\n", + " 'job': 'web-designer',\n", + " 'last name': 'Nekrasova'}}\n" + ] + } + ], + "source": [ + "# convert back from float to int, but now using dict comprehension\n", + "# first, let's just print the employees dictionary without any changes\n", + "pprint({id: info for id, info in employees.items()})" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qaPZCn-PnHpn", + "outputId": "38d50011-d70a-4cc0-b366-21a5fb6dc926" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id1': {'age': 30,\n", + " 'first name': 'Alexander',\n", + " 'job': 'Programmer',\n", + " 'last name': 'Ivanov'},\n", + " 'id2': {'age': 35,\n", + " 'first name': 'Olga',\n", + " 'job': 'ML-engineer',\n", + " 'last name': 'Petrova'},\n", + " 'id3': {'age': 26,\n", + " 'first name': 'Darya',\n", + " 'job': 'web-designer',\n", + " 'last name': 'Nekrasova'}}\n" + ] + } + ], + "source": [ + "# and then replace the value of the outer dictionary info\n", + "# (i.e., the nested dictionary)\n", + "# with another dict comprehension with an if-else condition\n", + "pprint(\n", + " {\n", + " id: {\n", + " key: (int(value_i) if key == \"age\" else value_i)\n", + " for key, value_i in info.items()\n", + " }\n", + " for id, info in employees.items()\n", + " }\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KQw8_33YMLU2" + }, + "source": [ + "#### Word frequency in the text" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ysL5RwJEMO7M" + }, + "outputs": [], + "source": [ + "# lets take a text corpus\n", + "corpus = (\n", + " \"When we were in Paris we visited a lot of museums. \"\n", + " \"We first went to the Louvre, the largest art museum in the world.\"\n", + " \"I have always been interested in art so I spent many hours there.\"\n", + " \"The museum is enormous, so a week there would not be enough.\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vu3yQDqNRb9o" + }, + "source": [ + "##### Preliminary text processing" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Y0Q0RhvlRRqJ", + "outputId": "d3ec9c90-e0b7-430b-b636-4bc33801ff6b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['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.']\n" + ] + } + ], + "source": [ + "# let's split into words\n", + "words = corpus.split()\n", + "print(words)" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VPFYOtFWXmm2", + "outputId": "c3c416a3-d537-40d8-e823-6c81c3f4b72e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['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']\n" + ] + } + ], + "source": [ + "# Using list comprehension, we will remove periods and commas\n", + "# and convert all words to lowercase.\n", + "words = [word.strip(\".\").strip(\",\").lower() for word in words]\n", + "print(words)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JvApRTwkRfaS" + }, + "source": [ + "##### Method 1. If-else condition" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0FbwZ4ODSlxH", + "outputId": "8c0b1ea0-041d-4ee3-cae7-46a191f0a546" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('the', 4), ('we', 3), ('in', 3), ('a', 2), ('art', 2), ('museum', 2)]\n" + ] + } + ], + "source": [ + "# Let's create an empty dictionary for the bag of words bow.\n", + "bow_1: dict[str, int] = {}\n", + "\n", + "# Let's go through the words in the text\n", + "for word in words:\n", + "\n", + " # if we encounter a word that is already in the dictionary\n", + " if word in bow_1:\n", + "\n", + " # increase its value (frequency) by 1\n", + " bow_1[word] = bow_1[word] + 1\n", + "\n", + " # otherwise, if the word appears for the first time\n", + " else:\n", + "\n", + " # set its value to 1\n", + " bow_1[word] = 1\n", + "\n", + "# sort the dictionary by meaning in descending order (reverse = True)\n", + "# and display the six most frequent words\n", + "print(sorted(bow_1.items(), key=lambda item: item[1], reverse=True)[:6])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DckCYLgvaF3D" + }, + "source": [ + "##### Method 2. The .get() method" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-cfKJK7dUx6E", + "outputId": "01b035d5-f1cb-4e1d-d455-d6175a15b9c3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('the', 4), ('we', 3), ('in', 3), ('a', 2), ('art', 2), ('museum', 2)]\n" + ] + } + ], + "source": [ + "bow_2: dict[str, int] = {}\n", + "\n", + "# Let's go through the for loop again by words\n", + "for word in words:\n", + "\n", + " # if the word is not yet in the dictionary, .get() will return the value 0,\n", + " # to which we will add one\n", + " # if the word exists, the .get() method will return the existing value,\n", + " # for example, 2 or 3,\n", + " # and we will also increase the counter by 1\n", + " bow_2[word] = bow_2.get(word, 0) + 1\n", + "\n", + "# let's list the most popular words\n", + "print(sorted(bow_2.items(), key=lambda item: item[1], reverse=True)[:6])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "p9pnHw9JdTDb" + }, + "source": [ + "##### Method 3. The collections module" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DBxI0C6GMO-P", + "outputId": "b688998c-0316-40a1-a3eb-38839afd60fd" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('the', 4), ('we', 3), ('in', 3), ('a', 2), ('art', 2), ('museum', 2)]" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create an object of this class, passing it a list of words\n", + "bow_3 = Counter(words)\n", + "\n", + "# Let's extract the six most common words using the .most_common method.\n", + "bow_3.most_common(6)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Encet8AUTxaK" + }, + "source": [ + "### Additional materials" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PMf-4k76T17z" + }, + "source": [ + "#### Mutable and immutable data types" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YSZEqdoqZPFJ" + }, + "source": [ + "Immutable data type" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "evIywP2QteRj", + "outputId": "41dc2190-2e36-4393-d42d-594a8c8c0a86" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "140735512785520 Python\n" + ] + } + ], + "source": [ + "# let's create a string object\n", + "string = \"Python\"\n", + "\n", + "# let's look at identity, type, and value\n", + "# the id() function outputs the address of an object in the computer's memory\n", + "print(id(string), type(string), string)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ddda36SbVNP3", + "outputId": "1efe542a-2076-48b7-d8ff-f38f526ca50f" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1236675369008 Python is cool\n" + ] + } + ], + "source": [ + "# let's try to change this object\n", + "string = string + \" is cool\"\n", + "\n", + "# Let's look at the identity, type, and value\n", + "print(id(string), type(string), string)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zD5pA-shZS9y" + }, + "source": [ + "Mutable data type" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "m3v7sz66WaG2", + "outputId": "79bed439-00cc-4d22-ff23-ea2ac933869b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1236675352064 [1, 2, 3]\n" + ] + } + ], + "source": [ + "# creating the list again\n", + "lst: list[int] = [1, 2, 3]\n", + "\n", + "# Let's look at the identity, type, and value\n", + "print(id(lst), type(lst), lst)" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "MwsfBPKuY44t", + "outputId": "e68fe4a2-9de8-4649-aab7-284c6868c3df" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1236675352064 [1, 2, 3, 4]\n" + ] + } + ], + "source": [ + "# add an item to the list\n", + "lst.append(4)\n", + "\n", + "# display the identity, type, and value again\n", + "print(id(lst), type(lst), lst)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "RN5eo53UcJ8v" + }, + "source": [ + "Copying objects" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WHkQSdiHe7z6", + "outputId": "3214f311-d3a7-4f47-b029-413b6f76729c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python Python is cool\n" + ] + } + ], + "source": [ + "# let's create the string again\n", + "string = \"Python\"\n", + "\n", + "# copy via assignment\n", + "string2 = string\n", + "\n", + "# changing the copy\n", + "string2 = string2 + \" is cool\"\n", + "\n", + "# let's see the result\n", + "print(string, string2)" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "4acHz97ajcSH", + "outputId": "4cff9e9d-be08-41b3-9a3d-6883e02d0a71" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False False\n" + ] + } + ], + "source": [ + "# The == operator compares values.\n", + "# The is operator compares identities.\n", + "print(string == string2, string is string2)" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "LHQ7dLSjbLiF", + "outputId": "d24c9d3f-af32-4d65-9219-7336ad8b5cae" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4] [1, 2, 3, 4]\n" + ] + } + ], + "source": [ + "# let's create a list again\n", + "lst = [1, 2, 3]\n", + "\n", + "# Copy it to a new variable through assignment\n", + "lst2 = lst\n", + "\n", + "# add a new item to the copied list\n", + "lst2.append(4)\n", + "\n", + "# let's display the original list and a copy\n", + "print(lst, lst2)" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Oje2eXOYjQwq", + "outputId": "750ce99e-09f8-42a1-f584-da308d4a4b51" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True True\n" + ] + } + ], + "source": [ + "# let's make sure we're talking about the same thing\n", + "print(lst == lst2, lst is lst2)" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bMxYXjZ1fwwV", + "outputId": "a4da24b7-1247-4586-a96f-b461ad1f9d47" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3] [1, 2, 3, 4]\n" + ] + } + ], + "source": [ + "# Let's create the list again\n", + "lst = [1, 2, 3]\n", + "\n", + "# copy using the .copy() method\n", + "lst2 = lst.copy()\n", + "\n", + "# add a new item to the copied list\n", + "lst2.append(4)\n", + "\n", + "# let's display the original list and a copy\n", + "print(lst, lst2)" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "uajQvKK5gN2x", + "outputId": "17e77160-2826-4cdf-9328-06c7844b6dfd" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4] [1, 2, 3, 4] True False\n" + ] + } + ], + "source": [ + "# now let's make the values of the lists the same\n", + "lst.append(4)\n", + "\n", + "# and make sure that these are still different objects\n", + "print(lst, lst2, lst == lst2, lst is lst2)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_09_dictionaries.py b/python/makarov/chapter_09_dictionaries.py new file mode 100644 index 00000000..92c5be3d --- /dev/null +++ b/python/makarov/chapter_09_dictionaries.py @@ -0,0 +1,634 @@ +"""Dictionaries in Python.""" + +# #### Creating a `dict()` + +# + +# An empty dictionary can be created using {} or the dict() function. +# Import the Counter class. +from collections import Counter + +# import the pprint() function from the pprint module +# it outputs some data structures better than the usual print() +from pprint import pprint + +import numpy as np + +dict_1: dict[str, str] = {} +dict_2: dict[str, str] = dict() # pylint: disable=R1735 +print(dict_1, dict_2) +# - + +# the dictionary can be filled +# with keys and values right away +company: dict[str, str | int] = { + "name": "Toyota", + "founded": 1937, + "founder": "Kiichiro Toyoda", +} +company + +# A dictionary can be created from nested lists. +tickers: dict[str, str] = dict([["TYO", "Toyota"], ["TSLA", "Tesla"], ["F", "Ford"]]) +tickers + +# + +# if you put the keys in a tuple +keys: tuple[str, ...] = ("k1", "k2", "k3") +# and set the value for all keys +value_global = 0 + +# then, using the .fromkeys() method, you can create a dictionary +# with these keys and a specified value for each of them +empty_values = dict.fromkeys(keys, value_global) +empty_values +# - + +# #### Dictionary keys and values + +# Types of dictionary elements + +# + +# Let's give an example of what the +# dictionary values might be. + +val_types: dict[str, int | str | bool | None | list[int] | object | float] = { + "k1": 123, + "k2": "string", + "k3": np.nan, # none type + "k4": True, # boolean type + "k5": None, + "k6": [1, 2, 3], + "k7": np.array([1, 2, 3]), + "k8": {1: "v1", 2: "v2", 3: "v3"}, +} + +val_types +# - + +# ```.keys(), .values() и .items()``` methods + +# Example of a dictionary representing a person +person: dict[str, str | int | list[str]] = { + "first name": "Ivan", + "last name": "Ivanov", + "born": 1980, + "dept": "IT", +} + +# lets see the keys of the dictionary +print(person.keys()) + +# values of the dictionary +print(person.values()) + +# items of the dictionary +print(person.items()) + +# Using a for loop + +# keys and values can be output in a for loop +for key, value_p in person.items(): + print(key, value_p) + +# Key access and method `.get()` + +# the value can be viewed by key +person["last name"] + +# + +# if there is no such key, +# Python will return an error +# person['education'] --> Error +# - + +# To prevent this from happening, you can use the .get() method. +# By default, if the key is missing, it returns the value None. +print(person.get("education")) + +# if the key does exist, +# .get() will return the corresponding value +print(person.get("born")) + +# Checking whether a key and value are in the dictionary + +# let's check if there is such a key in the dictionary +print("born" in person) + +# and now let's check if there is such a value in the dictionary +print(1980 in person.values()) + +# You can also check for the presence +# of both the key and the value at the same time. +print(("born", 1980) in person.items()) + +# ### Basic operation with dictionary types in Python + +# #### Adding and changing elements + +# You can add an element by assigning a new value to the new key. +# Please note that in this case, the new value is a list. +person["languages"] = ["Python", "C++"] +person + +# You can change an element by assigning a new value to the existing key. +# The value is still a list, but it consists of a single element. +person["languages"] = ["Python"] +person + +# + +# Now let's create a new dictionary with new elements +new_elements: dict[str, str | int] = {"job": "programmer", "experience": 7} + +# and add it to the existing dictionary using the .update() method +person.update(new_elements) +person +# - + +# The .setdefault() method checks whether the key exists in the dictionary. +# If it does, the value will not change. +person.setdefault("last name", "Petrov") +person + +# if not, a new key and corresponding value will be added +person.setdefault("f_languages", ["russian", "english"]) +person + +# #### Deleting elements + +# The .pop() method removes an element by key and outputs the value being # removed. +print(person.pop("dept")) + +# and we will see the updated dictionary +person + +# The keyword del also removes an element by key. +# The value being removed is not displayed. +del person["born"] + +# The .popitem() method removes the last added element and outputs it. +person.popitem() + +# The .clear() method removes +# all elements from the dictionary. +person.clear() +person + +# The keyword del also allows +# you to delete the entire dictionary. +del person + +# Let's make sure that this dictionary no longer exists. +person + +# #### Sorting dictionaries + +# let's take a simple dictionary to demonstrate sorting +dict_to_sort: dict[str, int] = {"k2": 30, "k1": 20, "k3": 10} + +# sort the keys +sorted(dict_to_sort) + +# and values +sorted(dict_to_sort.values()) + +# Let's look at the key:value pairs. +dict_to_sort.items() + +# to sort them by key (index [0]) +# we will use the .items() method and a lambda function +sorted(dict_to_sort.items(), key=lambda item: item[0]) + +# Sorting by value is performed in the same way, however, +# we pass the index [1] to the lambda function. +sorted(dict_to_sort.items(), key=lambda item: item[1]) + +# #### Copying dictionaries + +# Let's create a source dictionary +# with the number of students in the first +# and second years of university. +original: dict[str, int] = {"First course": 174, "Second Course": 131} + +# Copying with method `copy()` + +# + +# Let's create a copy of this dictionary using the .copy() method. +new_1 = original.copy() + +# add information about the third course to the new dictionary +new_1["Third course"] = 117 + +# the source dictionary has not changed +print(original) +print(new_1) +# - + +# Copying with `=` operator but its not recommended + +# + +# transfer the source dictionary to a new variable +new_2 = original + +# delete elements of the new dictionary +new_2.clear() + +# data has also been deleted from the source dictionary +print(original) +print(new_2) +# - + +# ### `dir()` function + +# + +# The dir() function returns +# all methods of the object passed to it. +some_dict = {"k": 1} + +# Special methods come first. +# They begin and end with the symbol '__'. +# Let's display the first 11 elements. +print(dir(some_dict)[:11]) +# - + +# when we pass our dictionary to the print() function, +print(some_dict) + +# In fact, we apply the .__str__() method to the object. +some_dict.__str__() # pylint: disable=C2801 + +# In most cases, we will be interested in methods without '__'. +methods = dir(some_dict)[-11:] +print(methods) + +# ### Dict comprehension + +# Let's create another simple dictionary +source_dict: dict[str, int] = {"k1": 2, "k2": 4, "k3": 6} + +# Using dict comprehension, multiply each value by two +new_source_dict = { + key: value * 2 for (key, value) in source_dict.items() +} # pylint: disable=C0301 + +# make all key characters uppercase +new_source_dict = {key.upper(): value for (key, value) in source_dict.items()} + +# + +# add a condition that the value must be +# greater than two AND less than six +new_dict_1 = { + key: value + for (key, value) in source_dict.items() + if value > 2 + if value < 6 # pylint: disable=C0301 +} + +print(new_dict_1) + +# + +new_dict: dict[str, int] = {} + +# when solving the same problem in a for loop +for key, value in source_dict.items(): + + # we would use logical AND + if 2 < value < 6: + + # if the conditions are true, write the key and + # value to a new dictionary + new_dict[key] = value + +new_dict +# - + +# The if-else condition is placed at the very beginning +# of the dict comprehension scheme. +# We will replace the value with the word even if it is even, +# and odd if it is odd. +even_odd_dict: dict[str, str] = { + key: ("even" if value % 2 == 0 else "odd") + for (key, value) in source_dict.items() # pylint: disable=C0301 +} + +# dict comprehension can be used +# instead of the .fromkeys() method. +keys = ("k1", "k2", "k3") +# Pass the keys from the keys tuple to +# the dictionary and set the value of each to 0. +zeros_dict = {key: 0 for key in keys} + +# ### Additional examples + +# #### lambda-functions, and `map()`, `zip()` functions + +# Example with `list()` + +# Lets take a list of words +words: list[str] = ["apple", "banana", "fig", "blackberry"] + +# Create a lambda function that calculates +# the length of the word passed to it. +# Using the map() function, apply the lambda function +# to each element of the words list +# and place the word lengths in a new list +# called length using the list() function. +length = list(map(len, words)) +length + +# Using the zip() function, we will concatenate +# both lists element by element +# and convert them into a dictionary. +from_zip_dict = dict(zip(words, length)) +print(from_zip_dict) + +# The same can be done using the zip() function +# and list comprehension. +zip_length_dict = dict(zip(words, [len(word) for word in words])) +print(zip_length_dict) + +# Example with `dictionary()` + +# let's take a dictionary with people's height in feet +height_feet: dict[str, float] = { + "Alex": 6.1, + "Jerry": 5.4, + "Ben": 5.8, +} + +# To convert feet to meters, let's create a lambda +# function lambda m: m * 0.3048 +# Apply this function to the dictionary +# values using the map() function +# Convert to a list +metres = list(map(lambda m: m * 0.3048, height_feet.values())) +metres + +# Using the zip() function, we will connect the keys +# of the source dictionary with the elements of the list metres. +dict(zip(height_feet.keys(), np.round(metres, 2))) + +# The same can be done using dict comprehensions. +# All in one line. +# We simply convert the dictionary values to meters. +students_heights_dict = { + key: np.round(value * 0.3048, 2) for (key, value) in height_feet.items() +} +print(students_heights_dict) + +# #### Nested dictionaries + +# let's take a dictionary with employee IDs as keys +employees: dict[str, dict[str, str | int | float]] = { + "id1": { + "first name": "Alexander", + "last name": "Ivanov", + "age": 30, + "job": "Programmer", + }, + "id2": { + "first name": "Olga", + "last name": "Petrova", + "age": 35, + "job": "ML-engineer", + }, +} + +# and values - nested dictionaries with information about them +for value_e in employees.values(): + print(value_e) + +# ##### Basics operations + +# To retrieve the value of an element in a nested dictionary, +# we will use a double key. +print(employees["id1"]["age"]) + +# + +# add information about the new employee +employees["id3"] = { + "first name": "Darya", + "last name": "Nekrasova", + "age": 27, + "job": "web-designer", +} + +# and display the updated dictionary using the pprint() function +pprint(employees) +# - + +# You can also change the value of a nested dictionary using a double key. +employees["id3"]["age"] = 26 +pprint(employees) + +# ##### `for` loops + +# + +# change the data type in the age information from int to float + +# To do this, we will first go through the nested dictionaries, +# i.e., the values of info in the external dictionary employees. +for info in employees.values(): + + # then by keys and values of the nested dictionary info + for key_info, value_info in info.items(): + + # if the key matches the word 'age' + if key_info == "age": + + # convert the value to float type + info[key_info] = float(value_info) + +pprint(employees) +# - + +# ##### Nested dictionaries and dict comprehension +# + +# convert back from float to int, but now using dict comprehension +# first, let's just print the employees dictionary without any changes +pprint({id: info for id, info in employees.items()}) + +# and then replace the value of the outer dictionary info +# (i.e., the nested dictionary) +# with another dict comprehension with an if-else condition +pprint( + { + id: { + key: (int(value_i) if key == "age" else value_i) + for key, value_i in info.items() + } + for id, info in employees.items() + } +) + +# #### Word frequency in the text + +# lets take a text corpus +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." +) + +# ##### Preliminary text processing + +# let's split into words +words = corpus.split() +print(words) + +# Using list comprehension, we will remove periods and commas +# and convert all words to lowercase. +words = [word.strip(".").strip(",").lower() for word in words] +print(words) + +# ##### Method 1. If-else condition + +# + +# Let's create an empty dictionary for the bag of words bow. +bow_1: dict[str, int] = {} + +# Let's go through the words in the text +for word in words: + + # if we encounter a word that is already in the dictionary + if word in bow_1: + + # increase its value (frequency) by 1 + bow_1[word] = bow_1[word] + 1 + + # otherwise, if the word appears for the first time + else: + + # set its value to 1 + bow_1[word] = 1 + +# sort the dictionary by meaning in descending order (reverse = True) +# and display the six most frequent words +print(sorted(bow_1.items(), key=lambda item: item[1], reverse=True)[:6]) +# - + +# ##### Method 2. The .get() method + +# + +bow_2: dict[str, int] = {} + +# Let's go through the for loop again by words +for word in words: + + # if the word is not yet in the dictionary, .get() will return the value 0, + # to which we will add one + # if the word exists, the .get() method will return the existing value, + # for example, 2 or 3, + # and we will also increase the counter by 1 + bow_2[word] = bow_2.get(word, 0) + 1 + +# let's list the most popular words +print(sorted(bow_2.items(), key=lambda item: item[1], reverse=True)[:6]) +# - + +# ##### Method 3. The collections module + +# + +# create an object of this class, passing it a list of words +bow_3 = Counter(words) + +# Let's extract the six most common words using the .most_common method. +bow_3.most_common(6) +# - + +# ### Additional materials + +# #### Mutable and immutable data types + +# Immutable data type + +# + +# let's create a string object +string = "Python" + +# let's look at identity, type, and value +# the id() function outputs the address of an object in the computer's memory +print(id(string), type(string), string) + +# + +# let's try to change this object +string = string + " is cool" + +# Let's look at the identity, type, and value +print(id(string), type(string), string) +# - + +# Mutable data type + +# + +# creating the list again +lst: list[int] = [1, 2, 3] + +# Let's look at the identity, type, and value +print(id(lst), type(lst), lst) + +# + +# add an item to the list +lst.append(4) + +# display the identity, type, and value again +print(id(lst), type(lst), lst) +# - + +# Copying objects + +# + +# let's create the string again +string = "Python" + +# # copy via assignment +string2 = string + +# changing the copy +string2 = string2 + " is cool" + +# let's see the result +print(string, string2) +# - + +# The == operator compares values. +# The is operator compares identities. +print(string == string2, string is string2) + +# + +# let's create a list again +lst = [1, 2, 3] + +# Copy it to a new variable through assignment +lst2 = lst + +# add a new item to the copied list +lst2.append(4) + +# let's display the original list and a copy +print(lst, lst2) +# - + +# let's make sure we're talking about the same thing +print(lst == lst2, lst is lst2) + +# + +# Let's create the list again +lst = [1, 2, 3] + +# # copy using the .copy() method +lst2 = lst.copy() + +# add a new item to the copied list +lst2.append(4) + +# let's display the original list and a copy +print(lst, lst2) + +# + +# now let's make the values of the lists the same +lst.append(4) + +# and make sure that these are still different objects +print(lst, lst2, lst == lst2, lst is lst2) diff --git a/python/makarov/chapter_10_numpy.ipynb b/python/makarov/chapter_10_numpy.ipynb new file mode 100644 index 00000000..5be0598b --- /dev/null +++ b/python/makarov/chapter_10_numpy.ipynb @@ -0,0 +1,5112 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 313, + "metadata": { + "id": "0AoPSXyUTTLc" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Numpy arrays.'" + ] + }, + "execution_count": 313, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Numpy arrays.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 315, + "metadata": { + "id": "-B6Os5J4V-my" + }, + "outputs": [], + "source": [ + "# again import matplotlib\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "# importing function csr_matrix()\n", + "from scipy.sparse import csr_matrix" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LKUY5Wkl4v8W" + }, + "source": [ + "#### np.array()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "x3wxNu5jthst", + "outputId": "379290cb-0f7f-4da9-dca3-306366f74994" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# creating array from list\n", + "arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n", + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tLWO1t--thwP", + "outputId": "84398ca8-90eb-4e8f-84b1-d558e59b2b2c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# array from tuple\n", + "arr = np.array((0, 1, 2, 3, 4, 5, 6, 7, 8, 9))\n", + "arr" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xTN_Etcv5EUM" + }, + "source": [ + "#### np.arange()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7m8RmMp_WfV1", + "outputId": "8a643468-4127-4819-ea12-b92d9216ff69" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# like range function but for arrays\n", + "# upper limit (not included in the sequence) is a mandatory parameter\n", + "arr = np.arange(10)\n", + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "pvAYZNQq7vdW", + "outputId": "384ffa69-bae2-4e16-8a6a-0d317c729fe5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 4, 6, 8])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# stop and step its not mandatory parameters\n", + "arr = np.arange(2, 10, 2)\n", + "\n", + "# When using the print() function, commas disappear.\n", + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 297, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 159 + }, + "id": "jXvlU2O7fn2b", + "outputId": "cf0384d7-24a6-407e-deaa-fbb7a2e53dd0" + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'float' object cannot be interpreted as an integer", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[297], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# range() differs in that the float type is not allowed.\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m2\u001b[39m, \u001b[38;5;241m5.5\u001b[39m, \u001b[38;5;241m0.5\u001b[39m))\n", + "\u001b[1;31mTypeError\u001b[0m: 'float' object cannot be interpreted as an integer" + ] + } + ], + "source": [ + "# range() differs in that the float type is not allowed.\n", + "list(range(2, 5.5, 0.5)) # type: ignore[call-overload]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iHWwIbO79gYb", + "outputId": "a8826c89-8f17-4620-f4b5-0af899b7acb3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.arange(2, 5.5, 0.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "4rqtyGhIlMY0" + }, + "source": [ + "#### Numpy arrays data types" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_8ep8dl-XYmd", + "outputId": "ded79fd0-23e4-4c1c-8011-03c56981e2f8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]\n", + "float64\n" + ] + } + ], + "source": [ + "# Although Numpy selects the data type itself it can be specified manually\n", + "arr_f = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], float)\n", + "\n", + "print(arr_f)\n", + "\n", + "# and also look at the data type of an individual element using dtype\n", + "print(arr_f.dtype)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "srNun-vzW8Ns" + }, + "source": [ + "### Properties (attributes) of an array" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OgCm8EQmCsBG", + "outputId": "36f25241-1397-415c-d461-61867660abd7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 4, 6, 8])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RqrBwqN0W_Bh", + "outputId": "82e79d38-c9c4-42ba-cf58-073378ec8bec" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# ndim allows you to find out the dimensions of the array\n", + "arr.ndim" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KXLx5xBIXFrV", + "outputId": "3170eb1c-f3f8-497b-91ff-6e800863aaea" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4,)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# shape outputs the number of elements in each dimension\n", + "arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ySepUZYCXJt2", + "outputId": "7d568e8a-2814-4819-af4a-937bc401a000" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# total number of elements in all dimensions\n", + "arr.size" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3bfjG3tBXVpv", + "outputId": "479e25a8-2421-44b3-da60-86b433a146d0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "dtype('int32')" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# data type of an individual element\n", + "# in our case, it is a 64-bit integer\n", + "arr.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "oc2nDHd4T9Ts", + "outputId": "a42d0eab-269c-4423-c0c8-25c1cab763fc" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# size in bytes (8 bits) of one element\n", + "# 64 / 8 bits = 8 bytes\n", + "arr.itemsize" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "js98UFM5MhK8", + "outputId": "ef1fb3b8-89f1-4a67-d8ef-8ea59eb78a9e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "16" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# total size of the array in bytes (4 elements x 8 bytes)\n", + "arr.nbytes" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "P_R5wQUfWEm8" + }, + "source": [ + "#### Array dimensions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zaTwTdR34QRV" + }, + "source": [ + "#### Zero-dimensional array" + ] + }, + { + "cell_type": "code", + "execution_count": 217, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mziFGTgZ9JA1", + "outputId": "ee06ce76-a3d8-489f-e772-809838e78b24" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array(42)" + ] + }, + "execution_count": 217, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# An array with zero dimension is\n", + "# a number (square brackets are not needed).\n", + "arr_0d = np.array(42)\n", + "arr_0d" + ] + }, + { + "cell_type": "code", + "execution_count": 218, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "uXg0E8lHQQNu", + "outputId": "70ba4a80-5e1f-4dbd-e8a8-2d44accd2abb" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "()\n", + "1\n" + ] + } + ], + "source": [ + "# Let's display the measurements,\n", + "# the elements in each of them,\n", + "# and the total number of elements.\n", + "print(arr_0d.ndim)\n", + "print(arr_0d.shape)\n", + "print(arr_0d.size)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5azGOwUd4T7G" + }, + "source": [ + "#### One-dimensional array (vector)" + ] + }, + { + "cell_type": "code", + "execution_count": 219, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "epa2EYJm9RCh", + "outputId": "21a6cbaf-9994-4e3c-c16f-c076fd423c36" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3])" + ] + }, + "execution_count": 219, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# # To create a vector you need square brackets.\n", + "arr_1d = np.array([1, 2, 3])\n", + "arr_1d" + ] + }, + { + "cell_type": "code", + "execution_count": 220, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RChZYx_rOzuc", + "outputId": "bc72269e-028d-4f7a-dbd0-54ed32a2432b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "(3,)\n", + "3\n" + ] + } + ], + "source": [ + "# lets display its measurements\n", + "print(arr_1d.ndim)\n", + "print(arr_1d.shape)\n", + "print(arr_1d.size)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Sya65bVc4W_0" + }, + "source": [ + "#### Two-dimensional array (matrix)" + ] + }, + { + "cell_type": "code", + "execution_count": 221, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fS1P0yHnWLg1", + "outputId": "6fa28f7d-4885-4ea3-d8d7-274e5aae592b" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 221, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# A two-dimensional array (matrix) is\n", + "# a one-dimensional array\n", + "# enclosed in a second set of square brackets.\n", + "arr_2d = np.array([[1, 2, 3], [4, 5, 6]])\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 222, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "RjtoWsiwW3_m", + "outputId": "47614132-8718-4b57-f634-d44473eba263" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "(2, 3)\n", + "6\n" + ] + } + ], + "source": [ + "print(arr_2d.ndim)\n", + "print(arr_2d.shape)\n", + "\n", + "# in this case, two elements of one dimension are\n", + "# multiplied by three elements of the second\n", + "print(arr_2d.size)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jDHqphcuPAJj", + "outputId": "567e9f1e-c992-40af-d1c8-560fcfcca668" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1],\n", + " [2],\n", + " [3]])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# such a matrix has three rows with one element in each\n", + "column = np.array([[1], [2], [3]])\n", + "column" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "es7zQS9oPtXh", + "outputId": "f9993a75-d488-44ba-913e-d30ba5dccfb8" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 1)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets look at its shape\n", + "column.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "IaY7z3pwPO9C", + "outputId": "c6e772d7-82d9-40b4-d847-2780c349db85" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3]])" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# in this one there is only one line with three elements\n", + "row = np.array([[1, 2, 3]])\n", + "row" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8_58yDDEU8lm", + "outputId": "43d51040-a168-4ba2-d4f8-6bc0bb1ed058" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "row.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fnBErM7T4bga" + }, + "source": [ + "#### Three-dimensional array" + ] + }, + { + "cell_type": "code", + "execution_count": 240, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Um2TRCK6Z0ki", + "outputId": "649d42d5-1fa9-43be-ece5-c26248bc477b" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 7, 8],\n", + " [ 9, 10, 11]]])" + ] + }, + "execution_count": 240, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# np.arange() creates a one-dimensional array,\n", + "# а np.reshape() distribute elements by measurements\n", + "arr_3d = np.arange(12).reshape(2, 2, 3)\n", + "arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 241, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "h4RWzeXmZ8J6", + "outputId": "5028537f-9ff6-4c18-a1a8-df6da6b2f380" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "(2, 2, 3)\n", + "12\n" + ] + } + ], + "source": [ + "# lets look at its attributes\n", + "print(arr_3d.ndim)\n", + "print(arr_3d.shape)\n", + "print(arr_3d.size)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "h509XfwIUesO" + }, + "source": [ + "### Another ways to create array" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "aE392Jb8Hk6-" + }, + "source": [ + "np.zeros()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "r5nHFPLpQC1D", + "outputId": "6c056dc1-eb5c-4053-c21c-c1ba05fe9248" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0., 0., 0., 0., 0.])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# we can pass a single value to create a\n", + "# one-dimensional array,\n", + "# filled with zeros\n", + "np.zeros(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JTb1Ig1k-_bo", + "outputId": "e1e60c66-cdfc-412a-d11a-c72f07551b8e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0., 0., 0.],\n", + " [0., 0., 0.]])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# or a tuple of numbers\n", + "# to indicate the number\n", + "# of zeros in each dimension\n", + "np.zeros((2, 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "O-WXRu7mIQ62" + }, + "source": [ + "np.ones()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WdGlNjuzSvfL", + "outputId": "6a1e9c6f-f58b-4de9-c0f1-beb9b2e79039" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.]]])" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Similarly, you can create an array filled with ones.\n", + "np.ones((2, 2, 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "U39nLsRDJKNK" + }, + "source": [ + "np.full()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7zQyai8dVarz", + "outputId": "7b157b74-0e53-40f6-a04a-545194e5d1bf" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 4, 4],\n", + " [4, 4, 4]])" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a 2 x 3 matrix\n", + "# and fill it with the number four.\n", + "np.full((2, 3), 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XfTmn-ptJQRq" + }, + "source": [ + "np.empty()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "E2nagZxo5f3X", + "outputId": "00917429-2e36-4aff-8ac5-c768e828cb4d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0., 0.],\n", + " [0., 0.],\n", + " [0., 0.]])" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create an empty 3 x 2 matrix.\n", + "np.empty((3, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xf3CFNnHIY0G" + }, + "source": [ + "np.zeros_like(), np.ones_like(), np.full_like(), np.empty_like()" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0wfGgIEz4y-M", + "outputId": "5a1c7b67-cbe3-4399-b541-08bfb210c5c6" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# creating a 2 x 3 array with numbers from 1 to 6.\n", + "arr = np.arange(1, 7).reshape(2, 3)\n", + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5pNjGqG8VvIz", + "outputId": "5d1f000c-1d35-41ea-8687-eb1b64241802" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0],\n", + " [0, 0, 0]])" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# convert it to an array of zeros\n", + "np.zeros_like(arr)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PZvMI1P5V0Bq", + "outputId": "c9bb6710-6510-4ef8-e160-d23c0b55e4ed" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 1, 1],\n", + " [1, 1, 1]])" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# ones array with the same shape as arr\n", + "np.ones_like(arr)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "i0yHlwAgJUzk", + "outputId": "61436c8b-0dae-4dc8-9699-fd8b6eeda0a7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 2, 2],\n", + " [2, 2, 2]])" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# fill it with twos\n", + "np.full_like(arr, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "96v3UMSuJhRH", + "outputId": "c54852df-e5f8-43e9-9368-ec8d47252c27" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1097887824, 351, 1121452944],\n", + " [ 351, 0, -2147483648]])" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and empty values\n", + "np.empty_like(arr)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zSv8QWc7J9Pw" + }, + "source": [ + "np.linspspace()" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DALGWhEq7nuE", + "outputId": "a5738826-c7e8-4df4-ab93-3c0c3e4886f5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a range from 0 to 0.9 and\n", + "# divide it into ten points, including 0 and 0.9\n", + "np.linspace(0, 0.9, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2BuvXAiOhauQ", + "outputId": "27b4414e-b38c-4260-a6f5-f1d6cd4339e0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# compare with np.arange (here we specify the step)\n", + "\n", + "np.arange(0, 1, 0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": 298, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 547 + }, + "id": "q-k6f1RfHVb8", + "outputId": "900b4c5b-2517-4ef6-e2e8-60d6efca1612" + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# set the graph size in inches\n", + "plt.figure(figsize=(8, 6))\n", + "\n", + "# Let's set an interval, for example, from -5 to 5,\n", + "# and generate 5000 points on it.\n", + "# These will be our coordinates on the x-axis.\n", + "x_val = np.linspace(-5, 5, 5000)\n", + "\n", + "# On the y-axis, we will plot a square of these points.\n", + "y_val = x_val**2\n", + "\n", + "# let's create a grid\n", + "plt.grid()\n", + "\n", + "# let's plot the curve and add labels to the graph\n", + "plt.plot(x_val, y_val)\n", + "plt.xlabel(\"x\", fontsize=14)\n", + "plt.ylabel(\"y\", fontsize=14)\n", + "\n", + "# the result will be a parabola\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 224, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BLKcZRmBU35X", + "outputId": "b3b899c0-b90a-4b68-c9b6-8f0828a1ca50" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-5. , -4.9979996, -4.9959992, -4.9939988, -4.9919984,\n", + " -4.989998 , -4.9879976, -4.9859972, -4.9839968, -4.9819964])" + ] + }, + "execution_count": 224, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# As an example, let's display the first ten points created\n", + "# by the np.linspace() function.\n", + "x_val[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "itXoryh5KI9A" + }, + "source": [ + "np.random.rand() и np.random.randint()" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "x_rMDmPcezrW", + "outputId": "22a51c5a-bd50-4a64-89a5-c2c3ecc59df1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.45130336, 0.72615221, 0.35353566],\n", + " [0.6500699 , 0.01454303, 0.1925176 ],\n", + " [0.3179418 , 0.5372128 , 0.26157588],\n", + " [0.40881207, 0.64669079, 0.51605532]])" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create an array of a given dimension,\n", + "# filled with numbers\n", + "# in the interval [0, 1)\n", + "np.random.rand(4, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "t7b_gs7kTfcX", + "outputId": "e70f02d1-2ca4-4ad6-ac1d-4a52d6116368" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[-3, 0],\n", + " [ 2, 0],\n", + " [-1, 0]],\n", + "\n", + " [[ 0, 1],\n", + " [ 1, -3],\n", + " [ 0, -2]]])" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create an array of integers in a given range\n", + "# (the upper limit is not included)\n", + "# and with a given dimension\n", + "np.random.randint(-3, 3, size=(2, 3, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QNwLPsETXLB9" + }, + "source": [ + "np.fromfunction()" + ] + }, + { + "cell_type": "code", + "execution_count": 300, + "metadata": { + "id": "SB2LUN9jlauX" + }, + "outputs": [], + "source": [ + "# Let's create our own function that takes two numbers\n", + "# and raises the first number to the power of the second.\n", + "\n", + "\n", + "def power(base: float, exponent: float) -> float:\n", + " \"\"\"Raise base to the power of exponent.\"\"\"\n", + " return base**exponent # type: ignore[no-any-return]" + ] + }, + { + "cell_type": "code", + "execution_count": 226, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fCHY1lRbkxCP", + "outputId": "f4ff1401-0904-45ba-9cb8-568092b522b7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1., 0., 0.],\n", + " [1., 1., 1.],\n", + " [1., 2., 4.]])" + ] + }, + "execution_count": 226, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# apply this function to each cell of the 3 x 3 array\n", + "np.fromfunction(power, (3, 3))" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BTNYb7dAlKDI", + "outputId": "dc80b2b7-573b-4dfd-997e-a60d75dd33e7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ True, False, False],\n", + " [False, True, False],\n", + " [False, False, True]])" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can also pass a lambda function that\n", + "# checks whether two numbers are equal.\n", + "np.fromfunction(lambda i, j: i == j, (3, 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ngd7-nTPlsE4" + }, + "source": [ + "Matrix in csr format and the .toarray() method" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "zBVZ-vMPogvd", + "outputId": "bb064796-9892-49ac-f76e-6877515f69dc" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 0, 0, 1, 0, 0, 0],\n", + " [0, 0, 3, 0, 0, 2, 0],\n", + " [0, 0, 0, 1, 0, 0, 0]])" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a matrix with predominantly zero values.\n", + "arr = np.array([[2, 0, 0, 1, 0, 0, 0], [0, 0, 3, 0, 0, 2, 0], [0, 0, 0, 1, 0, 0, 0]])\n", + "arr" + ] + }, + { + "cell_type": "code", + "execution_count": 316, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "T46-aB3Zyoa3", + "outputId": "e5b1a6c4-b3f8-4401-eb18-133e4472acae" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.7619047619047619" + ] + }, + "execution_count": 316, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# calculate the proportion of zero values\n", + "zero_proportion = 1.0 - np.count_nonzero(arr) / arr.size\n", + "zero_proportion" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "NburDJaKpTYS", + "outputId": "28ffeb34-ac91-4a8c-bb9e-549872a2e3fb" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " (0, 0)\t2\n", + " (0, 3)\t1\n", + " (1, 2)\t3\n", + " (1, 5)\t2\n", + " (2, 3)\t1\n" + ] + } + ], + "source": [ + "# It is convenient to store matrix A in csr format.\n", + "b_arr = csr_matrix(arr)\n", + "\n", + "# where the position of the non-zero value and\n", + "# the value itself are specified\n", + "print(b_arr)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-d2xgGl2tebr", + "outputId": "9f6dda4c-476c-48d4-afa5-7a355783a819" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 0, 0, 1, 0, 0, 0],\n", + " [0, 0, 3, 0, 0, 2, 0],\n", + " [0, 0, 0, 1, 0, 0, 0]])" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can restore a Numpy array using the .toarray() method.\n", + "c_arr = b_arr.toarray()\n", + "c_arr" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rgTp32HFZd3d" + }, + "source": [ + "### Indexing and Slicing" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NYWHFhT-PjiU" + }, + "source": [ + "#### Array element index" + ] + }, + { + "cell_type": "code", + "execution_count": 288, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1Vt97kwCUUV7", + "outputId": "bfac4448-455c-418d-ad0d-38a92bad9533" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 288, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's consider a two-dimensional array.\n", + "a_arr = np.array([[1, 2, 3], [4, 5, 6]])\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 289, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "SCqhT3latpsC", + "outputId": "844d74e8-97e4-4734-b500-88d62bb8677b" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 3)" + ] + }, + "execution_count": 289, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The first value of the shape attribute refers\n", + "# to the external dimension.\n", + "# The second refers to the internal dimension.\n", + "a_arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 290, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ed9G4uzjUf0G", + "outputId": "e16b2e6c-d05c-4e15-f0d9-808da326a443" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3])" + ] + }, + "execution_count": 290, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's display the first element of the external dimension\n", + "a_arr[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 291, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vjR_aJIYUqSs", + "outputId": "d0b9c140-5851-41c2-f12b-4c8ada829847" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 291, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The second index [0] allows you to access\n", + "# the elements of the inner dimension.\n", + "a_arr[0][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 292, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qo6zLndJPLfq", + "outputId": "5315e5f0-b141-411d-fe29-f5d862a535fe" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 292, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's display the value six\n", + "a_arr[1][2]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Hcpiis-3PtPo" + }, + "source": [ + "#### Array slicing" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Vt8Px4xyStn9" + }, + "source": [ + "Array 1D" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "k-qSMCTPPySo", + "outputId": "5e17ee36-27dd-40cb-bd16-664dfa7b8c48" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5, 6, 7, 8])" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's start with a one-dimensional array\n", + "b_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n", + "b_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "hC_cUN1XW_pd", + "outputId": "4d694bb4-356f-4bd1-e355-0ec64380e1ea" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 4, 6])" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# take every second element\n", + "# in the range from the 1st to the 6th index\n", + "b_arr[1:6:2]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "WAwm6TPkSxuO" + }, + "source": [ + "Array 2D" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VKNeFhlPXH30", + "outputId": "45583361-53d6-49fb-cf78-dde7ad3cb287" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3, 4],\n", + " [5, 6, 7, 8]])" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now let's take a two-dimensional array\n", + "c_arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])\n", + "c_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kpZdL8XBT2lI", + "outputId": "92a96147-d320-47b6-d2d9-4ad57085d175" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2])" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's slice from the first row and the first two columns\n", + "c_arr[0, :2]" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fSnEYbxwTqUL", + "outputId": "ffe6a4fb-e1ba-4ab4-8d64-30642956ac47" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 6])" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now take both lines in the second column.\n", + "c_arr[:, 1]" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0g_79-O3U4H2", + "outputId": "cb0f8788-f4f0-4648-cc34-80157df3fdb7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display the element in the first row and first column\n", + "c_arr[0, 0]" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "NULWFbsjU_Rs", + "outputId": "067c53ec-4833-483b-96a2-1551bc745828" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display the element in the last row and last column\n", + "c_arr[-1, -1]" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ZaGgo5XOxbEr", + "outputId": "0fed6ed3-5fb8-4562-fdd3-80346375e80a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([5, 7])" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# take every second element from the second row\n", + "c_arr[1, ::2]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JjVlHDMIS1YX" + }, + "source": [ + "3D array" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "gzo23jLttFiZ", + "outputId": "8c064cb8-202d-4318-d053-65975d1b3d58" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1],\n", + " [ 2, 3]],\n", + "\n", + " [[ 4, 5],\n", + " [ 6, 7]],\n", + "\n", + " [[ 8, 9],\n", + " [10, 11]],\n", + "\n", + " [[12, 13],\n", + " [14, 15]]])" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a three-dimensional array\n", + "d_arr = np.arange(16).reshape(4, 2, -1)\n", + "d_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dNp3j4Ngw3yo", + "outputId": "046107a5-005c-41e3-cc47-dafbd430f382" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# we will display the value 10\n", + "d_arr[2][1][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "uX4WPUoTUMN_", + "outputId": "b6d609a1-7a8d-43af-ec8b-b2c0d61f834d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[10, 11],\n", + " [14, 15]])" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's display the third and fourth matrices [2:]\n", + "# and in them the second row [1] and all columns [:]\n", + "d_arr[2:, 1, :]" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iV14zN0Lxcbu", + "outputId": "bdf33951-1dc8-4667-f2ca-97c6fb205d01" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[0, 1],\n", + " [2, 3]],\n", + "\n", + " [[4, 5],\n", + " [6, 7]]])" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# print the first two matrices of the array.\n", + "d_arr[:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kp0nMAmq_pPe", + "outputId": "3349705b-ec10-4436-8557-32249ebe29b5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1],\n", + " [ 4, 5],\n", + " [ 8, 9],\n", + " [12, 13]])" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display the first rows of each matrix\n", + "d_arr[:, 0, :]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZGtucKsnBvc3" + }, + "source": [ + "### Array axes" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "__XESBNh7s0_" + }, + "source": [ + "#### 2D array" + ] + }, + { + "cell_type": "code", + "execution_count": 227, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kyupod4IBzzn", + "outputId": "0454e6f1-6c5b-49ae-e89a-39dec3d330b9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2],\n", + " [3, 4]])" + ] + }, + "execution_count": 227, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's turn to a two-dimensional array\n", + "arr_2d = np.array([[1, 2], [3, 4]])\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 235, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "TxZjgULlENoZ", + "outputId": "aaba5b60-a819-4667-bb7a-847c361a6967" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 3)" + ] + }, + "execution_count": 235, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr_2d.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-IGUAfusJ7di" + }, + "source": [ + "Addition along the first axis (axis = 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 228, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Fmgnj8ikB4i8", + "outputId": "629bc194-d534-4487-dfd4-4586a16eec9d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([4, 6])" + ] + }, + "execution_count": 228, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# find the sum across columns (along the 0 axis)\n", + "np.sum(arr_2d, axis=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jFxAiXkRKJjW" + }, + "source": [ + "Addition along the second axis (axis = 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 236, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bXtqyfpcCmO6", + "outputId": "cbf9b9d0-2dfa-42a9-df48-65c737b19e76" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 7, 15])" + ] + }, + "execution_count": 236, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and the sum along the lines (along axis 1)\n", + "np.sum(arr_2d, axis=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ObrkD3rMKQuM" + }, + "source": [ + "Addition along both axes (axis = (0, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Xqr3GMkzC6Q1", + "outputId": "31b47f63-8d86-45e1-ac9d-d6be3365175e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 229, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if you pass a tuple specifying both axes (0, 1)\n", + "# the sum will be calculated first along axis 0,\n", + "# then along axis 1\n", + "np.sum(arr_2d, axis=(0, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 230, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QHr6-c7qGMN_", + "outputId": "706e9803-a895-4022-a30b-b0885265f5ee" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 230, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# if nothing is specified, the sum will also be calculated\n", + "# for all elements of the array\n", + "np.sum(arr_2d)" + ] + }, + { + "cell_type": "code", + "execution_count": 237, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "GiuTVmgCZsqd", + "outputId": "4e8bb0e3-0a36-43ed-fd59-7ca1736d160f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "22" + ] + }, + "execution_count": 237, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# in this case, the default value\n", + "# axis = None is used under the hood\n", + "np.sum(arr_2d, axis=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8-bynilMKe47" + }, + "source": [ + "Negative values in the axis parameter" + ] + }, + { + "cell_type": "code", + "execution_count": 231, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "MNzg2u6gx3EG", + "outputId": "fc14d08b-1d12-4eb3-9013-120d32ddf9f4" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([3, 7])" + ] + }, + "execution_count": 231, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# axis = -1 corresponds to the last axis of the array,\n", + "# in this case, axis = 1\n", + "np.sum(arr_2d, axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 232, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mlXISFzyzWWK", + "outputId": "03002606-fa22-4a8f-80d8-b68f8fb3831d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([4, 6])" + ] + }, + "execution_count": 232, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# axis = -2 indicates the first axis, i.e. axis = 0\n", + "np.sum(arr_2d, axis=-2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kOFFInXJ7zd6" + }, + "source": [ + "#### 3D array" + ] + }, + { + "cell_type": "code", + "execution_count": 242, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KoZxhwSX74QF", + "outputId": "9860de61-3e08-4024-db9f-e6f1d7971e42" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 7, 8],\n", + " [ 9, 10, 11]]])" + ] + }, + "execution_count": 242, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr_3d = np.arange(12).reshape(2, 2, 3)\n", + "arr_3d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YT1t3Gu1KlcX" + }, + "source": [ + "Addition along the first axis (axis = 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 243, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7U9erpuw3lji", + "outputId": "3679bbe2-ce55-4b80-b753-ee347202c003" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 6, 8, 10],\n", + " [12, 14, 16]])" + ] + }, + "execution_count": 243, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# apply np.sum() with the parameter axis = 0\n", + "np.sum(arr_3d, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 244, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vkoHAkYB4krO", + "outputId": "6ed105ad-119a-4838-a6df-74ec6ce6b179" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5]])" + ] + }, + "execution_count": 244, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets take the first matrix\n", + "arr_3d[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 245, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ohasOJz5GylS", + "outputId": "e0d5c3f8-a6a4-471b-df31-b3c827c59ef3" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 6, 7, 8],\n", + " [ 9, 10, 11]])" + ] + }, + "execution_count": 245, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# second matrix\n", + "arr_3d[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 246, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1uc6iXivG2db", + "outputId": "df64fa61-741e-4243-a37f-3ee8b4e01063" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 6, 8, 10],\n", + " [12, 14, 16]])" + ] + }, + "execution_count": 246, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and add them up piece by piece\n", + "arr_3d[0] + arr_3d[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 261, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "HwxOebzSJj49", + "outputId": "410447e2-7b11-4af6-d178-3945fa58a0b0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 6., 8., 10.],\n", + " [12., 14., 16.]])" + ] + }, + "execution_count": 261, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# same thing can be done using a for loop\n", + "\n", + "# create a zero matrix of size 2 x 3\n", + "total = np.zeros((2, 3))\n", + "\n", + "# and create a loop of two iterations\n", + "for i in range(2):\n", + "\n", + " # In the first iteration, we will\n", + " # write the first matrix to the zero array,\n", + " # and then add the second matrix to it.\n", + " total += arr_3d[i]\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3OHYIM4GKtwV" + }, + "source": [ + "Addition along the second axis (axis = 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 247, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nIeZkT8A7_Fj", + "outputId": "a5c82385-3064-4746-9fe4-e54a59f906cd" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 3, 5, 7],\n", + " [15, 17, 19]])" + ] + }, + "execution_count": 247, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# apply np.sum()\n", + "np.sum(arr_3d, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 248, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "l7qn51RWLIV9", + "outputId": "d18a347e-14ec-4d1a-ddc1-5ed5953e3354" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([3, 5, 7])" + ] + }, + "execution_count": 248, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add up the columns of the first\n", + "arr_3d[0][0] + arr_3d[0][1]" + ] + }, + { + "cell_type": "code", + "execution_count": 249, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Klvv3A6RMkfS", + "outputId": "04315883-b76b-4f4d-bd2f-7d530710f005" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([15, 17, 19])" + ] + }, + "execution_count": 249, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and the second matrix\n", + "arr_3d[1][0] + arr_3d[1][1]" + ] + }, + { + "cell_type": "code", + "execution_count": 312, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0l-g2FSjKznd", + "outputId": "41d1043c-dffb-489e-9631-f53ec224435c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 3., 5., 7.],\n", + " [15., 17., 19.]])" + ] + }, + "execution_count": 312, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a zero 2 x 3 matrix\n", + "total = np.zeros((2, 3))\n", + "\n", + "# First, let's go through the matrices.\n", + "for i in range(2):\n", + " # then along the rows of each matrix\n", + " for row_index in range(2):\n", + " # and in the first row of total, we write the\n", + " # sum of the columns of the first matrix arr_3D,\n", + " # and in the second row, we write\n", + " # the sum of the columns of the second matrix\n", + " total[i] += arr_3d[i][row_index]\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FlZ9BflvMu6H" + }, + "source": [ + "Addition along the third axis (axis = 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 251, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "oSfFaWwaMyZC", + "outputId": "c2dba270-4670-4331-f9a5-672564f02b46" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 3, 12],\n", + " [21, 30]])" + ] + }, + "execution_count": 251, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# apply np.sum()\n", + "np.sum(arr_3d, axis=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 252, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7KQ3voZNNiAP", + "outputId": "6232a32c-6f44-4562-88ee-19f0ccf198b9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 252, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add up the elements of the first row of the first matrix\n", + "arr_3d[0][0][0] + arr_3d[0][0][1] + arr_3d[0][0][2]" + ] + }, + { + "cell_type": "code", + "execution_count": 253, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rxRiuo2uN68S", + "outputId": "a45b4926-a648-400f-daa6-46cdb9b7e637" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "12" + ] + }, + "execution_count": 253, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# second row of the first matrix\n", + "arr_3d[0][1][0] + arr_3d[0][1][1] + arr_3d[0][1][2]" + ] + }, + { + "cell_type": "code", + "execution_count": 254, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ykcyLReqOC8w", + "outputId": "2c0698ca-af92-4068-f03f-3bcda574ed22" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "21" + ] + }, + "execution_count": 254, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# first row of the second matrix\n", + "arr_3d[1][0][0] + arr_3d[1][0][1] + arr_3d[1][0][2]" + ] + }, + { + "cell_type": "code", + "execution_count": 255, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cNrSMakqONNQ", + "outputId": "d18ce937-52f2-4d2c-b967-4ebdd57fa713" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "30" + ] + }, + "execution_count": 255, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# second row of the second matrix\n", + "arr_3d[1][1][0] + arr_3d[1][1][1] + arr_3d[1][1][2]" + ] + }, + { + "cell_type": "code", + "execution_count": 314, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8qSiW9RCOZ6e", + "outputId": "0b230e47-df7e-4552-eda2-c3369882aeae" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 3., 12.],\n", + " [21., 30.]])" + ] + }, + "execution_count": 314, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create a zero-based 2 x 2 array to record the results\n", + "total = np.zeros((2, 2))\n", + "\n", + "# let's go through the matrices\n", + "for matrix_idx in range(2):\n", + "\n", + " # by rows of the matrix\n", + " for row_idx in range(2):\n", + "\n", + " # and by columns (iterate values of the row)\n", + " for value in arr_3d[matrix_idx][row_idx]:\n", + "\n", + " # indices matrix_idx, row_idx will record the result of adding\n", + " # the elements of each row into a 2 x 2 result matrix\n", + " total[matrix_idx][row_idx] += value\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NJOn_OX4STxT" + }, + "source": [ + "Addition along the first and second axes (axis = (0, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 257, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "V5AFcjDZUZXr", + "outputId": "56aca382-ae24-441a-caac-44acd21c8df8" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([18, 22, 26])" + ] + }, + "execution_count": 257, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# apply the np.sum() function\n", + "np.sum(arr_3d, axis=(0, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 262, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "YH4jQsnPSts8", + "outputId": "423d5482-a8b8-42e4-fffc-eba724c5f61c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 6., 8., 10.],\n", + " [12., 14., 16.]])" + ] + }, + "execution_count": 262, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# when using two cycles, we first add the matrices together\n", + "total_0 = np.zeros((2, 3))\n", + "\n", + "for i in range(2):\n", + " total_0 += arr_3d[i]\n", + "\n", + "total_0" + ] + }, + { + "cell_type": "code", + "execution_count": 304, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_YR7xNRY1Go8", + "outputId": "375ae479-5d0e-4513-b9d8-58537acd4f0a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([18., 22., 26.])" + ] + }, + "execution_count": 304, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and then the columns of these matrices\n", + "total_1 = np.zeros(3)\n", + "\n", + "for i in range(2):\n", + " total_1 += total_0[i]\n", + "\n", + "total_1" + ] + }, + { + "cell_type": "code", + "execution_count": 305, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "YfJuRNyaVUq2", + "outputId": "d5362522-7c0e-452f-f4e4-dea0f4e03994" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([18., 22., 26.])" + ] + }, + "execution_count": 305, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = np.zeros(3)\n", + "\n", + "# In two cycles, we will go through the rows of each matrix.\n", + "for row_idx in range(2):\n", + " for col_idx in range(2):\n", + "\n", + " # and add them up piece by piece\n", + " total += arr_3d[row_idx][col_idx]\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_4FGHcALTiLi" + }, + "source": [ + "Addition along all three axes (axis = (0, 1, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": 259, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fmyV8teqTppB", + "outputId": "daa15507-2af2-4c38-d8e4-08067b4cb164" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "66" + ] + }, + "execution_count": 259, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(arr_3d, axis=(0, 1, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": 260, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qS-PIa-xg-F3", + "outputId": "c663a3e1-9466-4948-a06b-659f2c235ff9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "66" + ] + }, + "execution_count": 260, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(arr_3d)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fgA2VPOwZSpZ" + }, + "source": [ + "### Operations with arrays" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_hsyRA1bCBWD" + }, + "source": [ + "#### Function len()" + ] + }, + { + "cell_type": "code", + "execution_count": 264, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7xpKd_nBBkw2", + "outputId": "34892a8b-eb83-466e-830f-f893856d946a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 7, 8],\n", + " [ 9, 10, 11]]])" + ] + }, + "execution_count": 264, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets take a three-dimensional array\n", + "arr_3d = np.arange(12).reshape(2, 2, 3)\n", + "arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 265, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "dBaWPQ8EAAIC", + "outputId": "45862071-d01b-4877-dec0-16601d058c6d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 265, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# By default, the len() function outputs the\n", + "# length of the external dimension.\n", + "# these are outer brackets containing two matrices\n", + "len(arr_3d)" + ] + }, + { + "cell_type": "code", + "execution_count": 266, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vmOWiErJAZ1K", + "outputId": "1001ded4-fed3-48ba-b827-06e39bac873c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 266, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# To display the length of the internal\n", + "# measurement, i.e., a vector of three elements,\n", + "# you need to use indexes.\n", + "len(arr_3d[0][0])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XM6MaRtDQ9JS" + }, + "source": [ + "#### Entering an array" + ] + }, + { + "cell_type": "code", + "execution_count": 267, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rl5B8DpZQ8nG", + "outputId": "62500c7c-6eee-4e6d-8e9c-c22a7f9f5b8a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 267, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's check if the value 3 is included in the arr_3D array.\n", + "3 in arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 268, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6J3FVhfFRZmp", + "outputId": "6907a560-c43f-4f88-aac5-eb7653188c45" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 268, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's check if the value 11 is in the arr_3D array.\n", + "11 not in arr_3d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W8i50wrnIUWl" + }, + "source": [ + "#### Unpacking an array" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "C-1YKJLZIZXZ", + "outputId": "a3241449-8296-442c-98f4-42872c1e6dd2" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9],\n", + " [10, 11, 12, 13, 14, 15, 16, 17, 18],\n", + " [19, 20, 21, 22, 23, 24, 25, 26, 27]])" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's take a_val matrix with three rows and nine columns.\n", + "a_val = np.arange(1, 28).reshape(3, 9)\n", + "a_val" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Kdnv1BP6hDmz", + "outputId": "d85492d3-d5ae-45d5-9d01-d993814891df" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# each line can be unpacked into a separate variable\n", + "x_val, y_val, z_val = a_val\n", + "\n", + "# выведем первую переменную (строку)\n", + "x_val" + ] + }, + { + "cell_type": "code", + "execution_count": 295, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "MH5_vSynhr8t", + "outputId": "985466be-c664-4c33-9b6a-67257ecab405" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "[2, 3, 4, 5, 6, 7, 8]\n", + "9\n" + ] + } + ], + "source": [ + "# Now let's unpack the first, last, and remaining elements\n", + "# of the first line into separate variables\n", + "x_val, *y_val, z_val = a_val[0]\n", + "\n", + "# выведем каждую переменную\n", + "print(x_val)\n", + "print(y_val)\n", + "print(z_val)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "R_4d85uRyrIA" + }, + "source": [ + "#### Changing array elements" + ] + }, + { + "cell_type": "code", + "execution_count": 233, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0X12Qt4Oyukb", + "outputId": "964ee5b9-7dde-4ce8-bbcb-a1c93b6da6d1" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 233, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's turn to a two-dimensional array.\n", + "arr_2d = np.array([[1, 2, 3], [4, 5, 6]])\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 234, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bbJoLXWUy4Ra", + "outputId": "c2f65d2d-1f51-4829-a755-b3cefad8978a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 234, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# replace the first element of the first row by its index\n", + "arr_2d[0, 0] = 2\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 238, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mWrT49JnzBii", + "outputId": "885c00f8-c9f6-4c09-bd1c-dc50363ef1ce" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 1, 1],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 238, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# write the value 1 in the first row\n", + "arr_2d[0] = 1\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 239, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xctpzik00moR", + "outputId": "90867b91-a86d-40c4-dbec-b4ba6a1f6051" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 1, 0],\n", + " [4, 5, 0]])" + ] + }, + "execution_count": 239, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Write 0 in the third column of the array.\n", + "arr_2d[:, 2] = 0\n", + "arr_2d" + ] + }, + { + "cell_type": "code", + "execution_count": 269, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xILTEo4lzKgS", + "outputId": "7ff6e8a0-74cb-4d10-c4c4-be855e158754" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 7, 8],\n", + " [ 9, 10, 11]]])" + ] + }, + "execution_count": 269, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's turn to the three-dimensional array\n", + "arr_3d = np.arange(12).reshape(2, 2, 3)\n", + "arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 270, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7vTRDmPaYUXH", + "outputId": "e6385650-46fe-4260-ba66-f151001af59a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 0, 8],\n", + " [ 9, 1, 11]]])" + ] + }, + "execution_count": 270, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# select the second column of the second matrix and\n", + "# replace the values in columns 7 and 10 with 0 and 1\n", + "arr_3d[1, :, 1] = [0, 1]\n", + "\n", + "# in such an operation, the cut size must match\n", + "# the number of values being transferred\n", + "arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 271, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3UAnqAAgTYgj", + "outputId": "26c30c7d-b31e-4e03-8e23-68bf7d8a5a45" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[7, 7, 7],\n", + " [7, 7, 7]],\n", + "\n", + " [[7, 7, 7],\n", + " [7, 7, 7]]])" + ] + }, + "execution_count": 271, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# replace all elements of the array with the number seven\n", + "arr_3d.fill(7)\n", + "arr_3d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "e5FEAOF-IT9j" + }, + "source": [ + "#### Sorting an array and reversing the order of its elements" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SGwCDYOcbcWP" + }, + "source": [ + "Function np.sort()" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rkl_4UPjZUoi", + "outputId": "37037391-b45a-447b-cb4d-449f9b886338" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 8, 2],\n", + " [2, 3, 1]])" + ] + }, + "execution_count": 144, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets take a two-dimensional array\n", + "a_arr = np.array([[4, 8, 2], [2, 3, 1]])\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Jou-S9fAZeKB", + "outputId": "f227a3c5-3a51-4df7-b447-6b3c1713caac" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 4, 8],\n", + " [1, 2, 3]])" + ] + }, + "execution_count": 145, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# By default, sorting is performed with the parameter axis = -1\n", + "np.sort(a_arr)" + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DX9GYNEebtjo", + "outputId": "dd4ad1bd-5d32-4eb5-9908-b23eb19b52e9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 4, 8],\n", + " [1, 2, 3]])" + ] + }, + "execution_count": 146, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# for a two-dimensional array, this is axis 1\n", + "np.sort(a_arr, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fFJG6i4gcdmu", + "outputId": "72244588-0c5c-4694-e59b-5e3adb9b0cce" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 3, 1],\n", + " [4, 8, 2]])" + ] + }, + "execution_count": 147, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's look at sorting along the 0 axis.\n", + "np.sort(a_arr, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mj4N3QO6dB1P", + "outputId": "5d3ace1e-3113-459b-a041-9995176fbf93" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 2, 3, 4, 8])" + ] + }, + "execution_count": 148, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# axis = None initially returns a\n", + "# one-dimensional array,\n", + "# and then sorts it\n", + "np.sort(a_arr, axis=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ravVjzHrbgGw" + }, + "source": [ + "Reversing the order of array elements using the slice operator" + ] + }, + { + "cell_type": "code", + "execution_count": 317, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KREB12x8uX_P", + "outputId": "47bdd7fc-d135-45df-8747-ae0f38eb7d39" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])" + ] + }, + "execution_count": 317, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# slice operator with step parameter -1\n", + "# sets the reverse order of array elements\n", + "reversed_arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[::-1]\n", + "reversed_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 319, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fL5U479ckXWr", + "outputId": "ed8294bb-ece9-45a1-b9ce-c3a41c9b82ec" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([7, 6, 5, 4])" + ] + }, + "execution_count": 319, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The reverse order can be combined with cuts.\n", + "reverse_slice = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[-3:3:-1]\n", + "reverse_slice" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bG36HK6tkgXv", + "outputId": "f3cdf9b2-c85d-4257-8eb1-8c3c83fe306f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 8, 2],\n", + " [2, 3, 1],\n", + " [1, 7, 2]])" + ] + }, + "execution_count": 149, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# in two-dimensional array\n", + "a_arr = np.array([[4, 8, 2], [2, 3, 1], [1, 7, 2]])\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_LQLDaEvkFjf", + "outputId": "f12e7741-ed9d-44be-f7b4-2cf28a34d0f8" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 7, 1],\n", + " [1, 3, 2],\n", + " [2, 8, 4]])" + ] + }, + "execution_count": 150, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you can set the reverse order for\n", + "# two dimensions (axis = (0, 1))\n", + "a_arr[::-1, ::-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8xwMOXyYIhaP", + "outputId": "79553a94-fe3d-41fa-be77-96855f8c96ca" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 7, 2],\n", + " [2, 3, 1],\n", + " [4, 8, 2]])" + ] + }, + "execution_count": 152, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# reverse order by external (axis = 0)\n", + "a_arr[::-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xjr5Ry_ylilb", + "outputId": "90c7b416-45dc-4b3c-876a-95dd336f9e02" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 8, 4],\n", + " [1, 3, 2],\n", + " [2, 7, 1]])" + ] + }, + "execution_count": 154, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# and internal dimension (axis = 1)\n", + "a_arr[:, ::-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KIaaq06Hlorc" + }, + "source": [ + "Reverse order using the np.flip() function" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_70NGScrvJg8", + "outputId": "14142a72-b846-4164-bf5e-84e5141fcfe9" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 7, 1],\n", + " [1, 3, 2],\n", + " [2, 8, 4]])" + ] + }, + "execution_count": 156, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# by default, sets the reverse order for two dimensions\n", + "# same as axis = (0, 1)\n", + "np.flip(a_arr)" + ] + }, + { + "cell_type": "code", + "execution_count": 161, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9WUe2UsKLhTD", + "outputId": "5cffb5a7-c1f5-4011-9645-ffab1d09b53c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([3, 2, 1])" + ] + }, + "execution_count": 161, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you can also set the reverse order by external\n", + "np.flip(a_arr, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 162, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XxOnrRG7IpsO", + "outputId": "2b62b82f-04ca-4d51-8e1c-44886c6b3d57" + }, + "outputs": [ + { + "ename": "AxisError", + "evalue": "axis 1 is out of bounds for array of dimension 1", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mAxisError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[162], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# and internal measurements\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m np\u001b[38;5;241m.\u001b[39mflip(a_arr, axis \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m)\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\numpy\\lib\\function_base.py:340\u001b[0m, in \u001b[0;36mflip\u001b[1;34m(m, axis)\u001b[0m\n\u001b[0;32m 338\u001b[0m indexer \u001b[38;5;241m=\u001b[39m (np\u001b[38;5;241m.\u001b[39ms_[::\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m],) \u001b[38;5;241m*\u001b[39m m\u001b[38;5;241m.\u001b[39mndim\n\u001b[0;32m 339\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 340\u001b[0m axis \u001b[38;5;241m=\u001b[39m _nx\u001b[38;5;241m.\u001b[39mnormalize_axis_tuple(axis, m\u001b[38;5;241m.\u001b[39mndim)\n\u001b[0;32m 341\u001b[0m indexer \u001b[38;5;241m=\u001b[39m [np\u001b[38;5;241m.\u001b[39ms_[:]] \u001b[38;5;241m*\u001b[39m m\u001b[38;5;241m.\u001b[39mndim\n\u001b[0;32m 342\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m ax \u001b[38;5;129;01min\u001b[39;00m axis:\n", + "File \u001b[1;32mc:\\anaconda3\\Lib\\site-packages\\numpy\\core\\numeric.py:1380\u001b[0m, in \u001b[0;36mnormalize_axis_tuple\u001b[1;34m(axis, ndim, argname, allow_duplicate)\u001b[0m\n\u001b[0;32m 1378\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[0;32m 1379\u001b[0m \u001b[38;5;66;03m# Going via an iterator directly is slower than via list comprehension.\u001b[39;00m\n\u001b[1;32m-> 1380\u001b[0m axis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mtuple\u001b[39m([normalize_axis_index(ax, ndim, argname) \u001b[38;5;28;01mfor\u001b[39;00m ax \u001b[38;5;129;01min\u001b[39;00m axis])\n\u001b[0;32m 1381\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m allow_duplicate \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(axis)) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mlen\u001b[39m(axis):\n\u001b[0;32m 1382\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m argname:\n", + "\u001b[1;31mAxisError\u001b[0m: axis 1 is out of bounds for array of dimension 1" + ] + } + ], + "source": [ + "# and internal measurements\n", + "np.flip(a_arr, axis=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "k2vY1VBtm40F" + }, + "source": [ + "Sorting in descending order" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": { + "id": "ObKaGNpQm8y_" + }, + "outputs": [], + "source": [ + "# to sort an array in descending order\n", + "a_arr = np.array([4, 2, 6, 1, 7, 3, 5])" + ] + }, + { + "cell_type": "code", + "execution_count": 320, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "wN7fbuGynLms", + "outputId": "2b2bf0b1-29b5-4b5b-aa07-c21933c43412" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 5, 6],\n", + " [1, 2, 3]])" + ] + }, + "execution_count": 320, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# we can sequentially apply np.sort() and the slice operator\n", + "sorted_desc = np.sort(a_arr)[::-1]\n", + "sorted_desc" + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "R-zBn8aon-8_", + "outputId": "53766ee8-b86d-4b72-ecb7-8b148da7d078" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([4, 2, 6, 1, 7, 3, 5])" + ] + }, + "execution_count": 168, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the original array has not changed\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": { + "id": "SiucRoJ3npZW" + }, + "outputs": [], + "source": [ + "# You can do it in reverse order, but using the .sort() method.\n", + "a_arr[::-1].sort()" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FdRdATESoDPM", + "outputId": "d1e96dec-f085-41b4-bf60-e2bdbb9655b7" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([7, 6, 5, 4, 3, 2, 1])" + ] + }, + "execution_count": 170, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the change has become permanent\n", + "a_arr" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "unLH1uedFIma" + }, + "source": [ + "#### Change in dimension" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mihFAkws4Bal" + }, + "source": [ + ".reshape()" + ] + }, + { + "cell_type": "code", + "execution_count": 272, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6K7B1rUmaWOm", + "outputId": "be48732f-6121-4d5f-8dad-f5b8adb57f5a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0, 1, 2],\n", + " [ 3, 4, 5]],\n", + "\n", + " [[ 6, 7, 8],\n", + " [ 9, 10, 11]]])" + ] + }, + "execution_count": 272, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets take a three-dimensional array\n", + "arr_3d = np.arange(12).reshape(2, 2, 3)\n", + "arr_3d" + ] + }, + { + "cell_type": "code", + "execution_count": 273, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KSLEgGwkFSrW", + "outputId": "f8dfae22-4499-4a30-d9bf-91f36a1a57fc" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "12" + ] + }, + "execution_count": 273, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# it has 12 elements\n", + "arr_3d.size" + ] + }, + { + "cell_type": "code", + "execution_count": 274, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Kb82LETQal45", + "outputId": "328124fc-0dbc-43ba-846c-be96bddeb564" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10, 11]])" + ] + }, + "execution_count": 274, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# change the dimension while keeping the total number\n", + "# of elements the same\n", + "arr_2d = arr_3d.reshape(2, 6)\n", + "arr_2d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DEI_PaK74E-o" + }, + "source": [ + "np.resize() and .resize()" + ] + }, + { + "cell_type": "code", + "execution_count": 275, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "hadxMWoqHjE2", + "outputId": "5038f220-ab81-4966-a2d5-dfe9a515881d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10, 11],\n", + " [ 0, 1, 2, 3, 4, 5]])" + ] + }, + "execution_count": 275, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The np.resize() function allows you\n", + "# to not keep the previous number of elements.\n", + "# Existing elements are copied to new cells.\n", + "np.resize(arr_2d, (3, 6))" + ] + }, + { + "cell_type": "code", + "execution_count": 307, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UDCssU5Iq_Df", + "outputId": "816387e7-e0e6-465c-8480-6327c5bea0e5" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10, 11],\n", + " [ 0, 0, 0, 0, 0, 0],\n", + " [ 0, 0, 0, 0, 0, 0]])" + ] + }, + "execution_count": 307, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# arr_2D refers to another array, so you first need to make a copy of it\n", + "arr_2d_copy = arr_2d.copy()\n", + "\n", + "# The .resize() method will make a copy, change the dimensions,\n", + "# and fill in the gaps with zeros.\n", + "arr_2d_copy.resize(4, 6)\n", + "arr_2d_copy" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "y2N-1WQt4UW8" + }, + "source": [ + ".flatten() and .ravel()" + ] + }, + { + "cell_type": "code", + "execution_count": 277, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KNhay4zYavYo", + "outputId": "e5472734-6094-4094-c474-a1189674f392" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" + ] + }, + "execution_count": 277, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# .flatten() converts (\"flattens\") an array into\n", + "# a one-dimensional array and\n", + "# creates a copy of the original array\n", + "# (like the .copy() method).\n", + "arr_3d.flatten()" + ] + }, + { + "cell_type": "code", + "execution_count": 278, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_VFCbIwNayxf", + "outputId": "73e4c5f9-30b4-4150-af12-2aad68babd32" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" + ] + }, + "execution_count": 278, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# .ravel() does the same thing,\n", + "# but does not create a copy of the original\n", + "# array and is therefore faster than .flatten().\n", + "arr_3d.ravel()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "n3r53-OA5ez-" + }, + "source": [ + "np.newaxis" + ] + }, + { + "cell_type": "code", + "execution_count": 179, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tpFz3REUTq_K", + "outputId": "d252b4fc-9ee1-401f-c440-c684b2c065be" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 179, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# np.newaxis adds a dimension to the array\n", + "a_arr = np.array([1, 2, 3])\n", + "a_arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cTGAhGCK3Pxw", + "outputId": "414d4bef-ea0c-458c-f030-ba9fcea4a0ee" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 2 3]]\n", + "(1, 3)\n" + ] + } + ], + "source": [ + "# add the first dimension\n", + "b_arr = a_arr[np.newaxis, :]\n", + "\n", + "print(b_arr)\n", + "print(b_arr.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1Gy-K6qbUBxW", + "outputId": "706e24c3-323b-405a-f2a2-46b00e98cebf" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1]\n", + " [2]\n", + " [3]]\n", + "(3, 1)\n" + ] + } + ], + "source": [ + "# добавим второе измерение\n", + "c_arr = a_arr[:, np.newaxis]\n", + "\n", + "print(c_arr)\n", + "print(c_arr.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "H8amricZ9YqS" + }, + "source": [ + "np.expand_dims()" + ] + }, + { + "cell_type": "code", + "execution_count": 184, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PuKcFZol8SRe", + "outputId": "425d2f0d-9ab7-49a9-a546-a53e1cdbd4b0" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2],\n", + " [3, 4]])" + ] + }, + "execution_count": 184, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# lets take a two-dimensional array\n", + "a_arr = np.array([[1, 2], [3, 4]])\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 185, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7t6X9ctx9g_y", + "outputId": "baa007bf-9a30-4c6c-f978-65ffe624696c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[1, 2],\n", + " [3, 4]]])" + ] + }, + "execution_count": 185, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add an external dimension\n", + "np.expand_dims(a_arr, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 186, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "c7vxGb199huI", + "outputId": "65ed2504-8fe7-422e-afb9-54dd61fd43b4" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[1, 2]],\n", + "\n", + " [[3, 4]]])" + ] + }, + "execution_count": 186, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add a \"middle\" measurement\n", + "np.expand_dims(a_arr, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 187, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "MTVCMo4r9iE6", + "outputId": "ec752b18-b9ef-4ae2-a98f-3ca9e2968903" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[1],\n", + " [2]],\n", + "\n", + " [[3],\n", + " [4]]])" + ] + }, + "execution_count": 187, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# add internal dimension\n", + "np.expand_dims(a_arr, axis=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BBtuRRw354vL" + }, + "source": [ + "np.squeeze()" + ] + }, + { + "cell_type": "code", + "execution_count": 280, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Zl6F7tOeLLRi", + "outputId": "c010ad76-f80d-4ede-9aa2-0af136ff2043" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[[0],\n", + " [1],\n", + " [2]],\n", + "\n", + " [[3],\n", + " [4],\n", + " [5]],\n", + "\n", + " [[6],\n", + " [7],\n", + " [8]]]])" + ] + }, + "execution_count": 280, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's take a 4D array in which\n", + "# the first and last dimensions contain one element each.\n", + "arr_4d = np.arange(9).reshape(1, 3, 3, 1)\n", + "arr_4d" + ] + }, + { + "cell_type": "code", + "execution_count": 281, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KyKRrMPJ6Zx7", + "outputId": "765493d2-10b6-41e5-c147-0c3085e458dd" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5],\n", + " [6, 7, 8]])" + ] + }, + "execution_count": 281, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Remove these measurements using the np.squeeze() function.\n", + "np.squeeze(arr_4d)" + ] + }, + { + "cell_type": "code", + "execution_count": 321, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "70RxxgPV6haV", + "outputId": "9dcfe835-ea39-4a6a-9700-6394283a8f83" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 3)" + ] + }, + "execution_count": 321, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the new array has only two dimensions\n", + "squeezed_shape = np.squeeze(arr_4d).shape\n", + "squeezed_shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PtqD2BdXsu0y" + }, + "source": [ + "#### Merging arrays" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XDsl7KSEO3c0" + }, + "source": [ + "np.concatenate()" + ] + }, + { + "cell_type": "code", + "execution_count": 191, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6RMdsyreZXFs", + "outputId": "a2f39d63-882e-4021-d9e7-408bf7d7c90c" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1],\n", + " [2, 3]])" + ] + }, + "execution_count": 191, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's create two square arrays.\n", + "a_arr = np.arange(4).reshape(2, 2)\n", + "a_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 192, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "28XOIs_xAVf9", + "outputId": "08c2701d-0a54-4c4a-9489-217aa1e219ad" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 5],\n", + " [6, 7]])" + ] + }, + "execution_count": 192, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b_arr = np.arange(4, 8).reshape(2, 2)\n", + "b_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 194, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "K5sNt0cbAdpm", + "outputId": "90b38327-912a-4bdb-c896-a811504cd492" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1],\n", + " [2, 3],\n", + " [4, 5],\n", + " [6, 7]])" + ] + }, + "execution_count": 194, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Merging arrays\n", + "np.concatenate((a_arr, b_arr), axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 195, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "CAO8aBIFAiNS", + "outputId": "9690ecf3-ce39-4e11-a0d7-059c3e63e09b" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 4, 5],\n", + " [2, 3, 6, 7]])" + ] + }, + "execution_count": 195, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the same along axis 1\n", + "np.concatenate((a_arr, b_arr), axis=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zRHowMnjBUeV" + }, + "source": [ + "np.stack()" + ] + }, + { + "cell_type": "code", + "execution_count": 196, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jmkCrwiuBXRs", + "outputId": "b5101b90-ab19-4852-9ae9-982a0287acd8" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[0, 1],\n", + " [2, 3]],\n", + "\n", + " [[4, 5],\n", + " [6, 7]]])" + ] + }, + "execution_count": 196, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The difference here is that we are\n", + "# adding a new axis (dimension).\n", + "np.stack((a_arr, b_arr), axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 197, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "4VhZ5Zr_BpgX", + "outputId": "aad63240-163e-47d7-9e7c-6298acc4083e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[0, 1],\n", + " [4, 5]],\n", + "\n", + " [[2, 3],\n", + " [6, 7]]])" + ] + }, + "execution_count": 197, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.stack((a_arr, b_arr), axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 198, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "o9H7eB7hCW8z", + "outputId": "bcbb5271-7409-430b-8cdd-f717b9718ecd" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[0, 4],\n", + " [1, 5]],\n", + "\n", + " [[2, 6],\n", + " [3, 7]]])" + ] + }, + "execution_count": 198, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.stack((a_arr, b_arr), axis=2)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/python/makarov/chapter_10_numpy.py b/python/makarov/chapter_10_numpy.py new file mode 100644 index 00000000..ce605cd0 --- /dev/null +++ b/python/makarov/chapter_10_numpy.py @@ -0,0 +1,837 @@ +"""Numpy arrays.""" + +# + +# again import matplotlib +import matplotlib.pyplot as plt +import numpy as np + +# importing function csr_matrix() +from scipy.sparse import csr_matrix + +# - + +# #### np.array() + +# creating array from list +arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) +arr + +# array from tuple +arr = np.array((0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) +arr + +# #### np.arange() + +# like range function but for arrays +# upper limit (not included in the sequence) is a mandatory parameter +arr = np.arange(10) +arr + +# + +# stop and step its not mandatory parameters +arr = np.arange(2, 10, 2) + +# When using the print() function, commas disappear. +arr +# - + +# range() differs in that the float type is not allowed. +list(range(2, 5.5, 0.5)) # type: ignore[call-overload] + +np.arange(2, 5.5, 0.5) + +# #### Numpy arrays data types + +# + +# Although Numpy selects the data type itself it can be specified manually +arr_f = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], float) + +print(arr_f) + +# and also look at the data type of an individual element using dtype +print(arr_f.dtype) +# - + +# ### Properties (attributes) of an array + +arr + +# ndim allows you to find out the dimensions of the array +arr.ndim + +# shape outputs the number of elements in each dimension +arr.shape + +# total number of elements in all dimensions +arr.size + +# data type of an individual element +# in our case, it is a 64-bit integer +arr.dtype + +# size in bytes (8 bits) of one element +# 64 / 8 bits = 8 bytes +arr.itemsize + +# total size of the array in bytes (4 elements x 8 bytes) +arr.nbytes + +# #### Array dimensions + +# #### Zero-dimensional array + +# An array with zero dimension is +# a number (square brackets are not needed). +arr_0d = np.array(42) +arr_0d + +# Let's display the measurements, +# the elements in each of them, +# and the total number of elements. +print(arr_0d.ndim) +print(arr_0d.shape) +print(arr_0d.size) + +# #### One-dimensional array (vector) + +# # To create a vector you need square brackets. +arr_1d = np.array([1, 2, 3]) +arr_1d + +# lets display its measurements +print(arr_1d.ndim) +print(arr_1d.shape) +print(arr_1d.size) + +# #### Two-dimensional array (matrix) + +# A two-dimensional array (matrix) is +# a one-dimensional array +# enclosed in a second set of square brackets. +arr_2d = np.array([[1, 2, 3], [4, 5, 6]]) +arr_2d + +# + +print(arr_2d.ndim) +print(arr_2d.shape) + +# in this case, two elements of one dimension are +# multiplied by three elements of the second +print(arr_2d.size) +# - + +# such a matrix has three rows with one element in each +column = np.array([[1], [2], [3]]) +column + +# lets look at its shape +column.shape + +# in this one there is only one line with three elements +row = np.array([[1, 2, 3]]) +row + +row.shape + +# #### Three-dimensional array + +# np.arange() creates a one-dimensional array, +# а np.reshape() distribute elements by measurements +arr_3d = np.arange(12).reshape(2, 2, 3) +arr_3d + +# lets look at its attributes +print(arr_3d.ndim) +print(arr_3d.shape) +print(arr_3d.size) + +# ### Another ways to create array + +# np.zeros() + +# we can pass a single value to create a +# one-dimensional array, +# filled with zeros +np.zeros(5) + +# or a tuple of numbers +# to indicate the number +# of zeros in each dimension +np.zeros((2, 3)) + +# np.ones() + +# Similarly, you can create an array filled with ones. +np.ones((2, 2, 3)) + +# np.full() + +# Let's create a 2 x 3 matrix +# and fill it with the number four. +np.full((2, 3), 4) + +# np.empty() + +# Let's create an empty 3 x 2 matrix. +np.empty((3, 2)) + +# np.zeros_like(), np.ones_like(), np.full_like(), np.empty_like() + +# creating a 2 x 3 array with numbers from 1 to 6. +arr = np.arange(1, 7).reshape(2, 3) +arr + +# convert it to an array of zeros +np.zeros_like(arr) + +# ones array with the same shape as arr +np.ones_like(arr) + +# fill it with twos +np.full_like(arr, 2) + +# and empty values +np.empty_like(arr) + +# np.linspspace() + +# create a range from 0 to 0.9 and +# divide it into ten points, including 0 and 0.9 +np.linspace(0, 0.9, 10) + +# + +# compare with np.arange (here we specify the step) + +np.arange(0, 1, 0.1) + +# + +# set the graph size in inches +plt.figure(figsize=(8, 6)) + +# Let's set an interval, for example, from -5 to 5, +# and generate 5000 points on it. +# These will be our coordinates on the x-axis. +x_val = np.linspace(-5, 5, 5000) + +# On the y-axis, we will plot a square of these points. +y_val = x_val**2 + +# let's create a grid +plt.grid() + +# let's plot the curve and add labels to the graph +plt.plot(x_val, y_val) +plt.xlabel("x", fontsize=14) +plt.ylabel("y", fontsize=14) + +# the result will be a parabola +plt.show() +# - + +# As an example, let's display the first ten points created +# by the np.linspace() function. +x_val[:10] + +# np.random.rand() и np.random.randint() + +# create an array of a given dimension, +# filled with numbers +# in the interval [0, 1) +np.random.rand(4, 3) + +# create an array of integers in a given range +# (the upper limit is not included) +# and with a given dimension +np.random.randint(-3, 3, size=(2, 3, 2)) + +# np.fromfunction() + +# + +# Let's create our own function that takes two numbers +# and raises the first number to the power of the second. + + +def power(base: float, exponent: float) -> float: + """Raise base to the power of exponent.""" + return base**exponent # type: ignore[no-any-return] + + +# - + +# apply this function to each cell of the 3 x 3 array +np.fromfunction(power, (3, 3)) + +# You can also pass a lambda function that +# checks whether two numbers are equal. +np.fromfunction(lambda i, j: i == j, (3, 3)) + +# Matrix in csr format and the .toarray() method + +# Let's create a matrix with predominantly zero values. +arr = np.array([[2, 0, 0, 1, 0, 0, 0], [0, 0, 3, 0, 0, 2, 0], [0, 0, 0, 1, 0, 0, 0]]) +arr + +# calculate the proportion of zero values +zero_proportion = 1.0 - np.count_nonzero(arr) / arr.size +zero_proportion + +# + +# It is convenient to store matrix A in csr format. +b_arr = csr_matrix(arr) + +# where the position of the non-zero value and +# the value itself are specified +print(b_arr) +# - + +# You can restore a Numpy array using the .toarray() method. +c_arr = b_arr.toarray() +c_arr + +# ### Indexing and Slicing + +# #### Array element index + +# Let's consider a two-dimensional array. +a_arr = np.array([[1, 2, 3], [4, 5, 6]]) +a_arr + +# The first value of the shape attribute refers +# to the external dimension. +# The second refers to the internal dimension. +a_arr.shape + +# let's display the first element of the external dimension +a_arr[0] + +# The second index [0] allows you to access +# the elements of the inner dimension. +a_arr[0][0] + +# let's display the value six +a_arr[1][2] + +# #### Array slicing + +# Array 1D + +# Let's start with a one-dimensional array +b_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8]) +b_arr + +# take every second element +# in the range from the 1st to the 6th index +b_arr[1:6:2] + +# Array 2D + +# Now let's take a two-dimensional array +c_arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) +c_arr + +# let's slice from the first row and the first two columns +c_arr[0, :2] + +# Now take both lines in the second column. +c_arr[:, 1] + +# display the element in the first row and first column +c_arr[0, 0] + +# display the element in the last row and last column +c_arr[-1, -1] + +# take every second element from the second row +c_arr[1, ::2] + +# 3D array + +# create a three-dimensional array +d_arr = np.arange(16).reshape(4, 2, -1) +d_arr + +# we will display the value 10 +d_arr[2][1][0] + +# Let's display the third and fourth matrices [2:] +# and in them the second row [1] and all columns [:] +d_arr[2:, 1, :] + +# print the first two matrices of the array. +d_arr[:2] + +# display the first rows of each matrix +d_arr[:, 0, :] + +# ### Array axes + +# #### 2D array + +# Let's turn to a two-dimensional array +arr_2d = np.array([[1, 2], [3, 4]]) +arr_2d + +arr_2d.shape + +# Addition along the first axis (axis = 0) + +# find the sum across columns (along the 0 axis) +np.sum(arr_2d, axis=0) + +# Addition along the second axis (axis = 1) + +# and the sum along the lines (along axis 1) +np.sum(arr_2d, axis=1) + +# Addition along both axes (axis = (0, 1)) + +# if you pass a tuple specifying both axes (0, 1) +# the sum will be calculated first along axis 0, +# then along axis 1 +np.sum(arr_2d, axis=(0, 1)) + +# if nothing is specified, the sum will also be calculated +# for all elements of the array +np.sum(arr_2d) + +# in this case, the default value +# axis = None is used under the hood +np.sum(arr_2d, axis=None) + +# Negative values in the axis parameter + +# axis = -1 corresponds to the last axis of the array, +# in this case, axis = 1 +np.sum(arr_2d, axis=-1) + +# axis = -2 indicates the first axis, i.e. axis = 0 +np.sum(arr_2d, axis=-2) + +# #### 3D array + +arr_3d = np.arange(12).reshape(2, 2, 3) +arr_3d + +# Addition along the first axis (axis = 0) + +# apply np.sum() with the parameter axis = 0 +np.sum(arr_3d, axis=0) + +# lets take the first matrix +arr_3d[0] + +# second matrix +arr_3d[1] + +# and add them up piece by piece +arr_3d[0] + arr_3d[1] + +# + +# same thing can be done using a for loop + +# create a zero matrix of size 2 x 3 +total = np.zeros((2, 3)) + +# and create a loop of two iterations +for i in range(2): + + # In the first iteration, we will + # write the first matrix to the zero array, + # and then add the second matrix to it. + total += arr_3d[i] + +total +# - + +# Addition along the second axis (axis = 1) + +# apply np.sum() +np.sum(arr_3d, axis=1) + +# add up the columns of the first +arr_3d[0][0] + arr_3d[0][1] + +# and the second matrix +arr_3d[1][0] + arr_3d[1][1] + +# + +# Let's create a zero 2 x 3 matrix +total = np.zeros((2, 3)) + +# First, let's go through the matrices. +for i in range(2): + # then along the rows of each matrix + for row_index in range(2): + # and in the first row of total, we write the + # sum of the columns of the first matrix arr_3D, + # and in the second row, we write + # the sum of the columns of the second matrix + total[i] += arr_3d[i][row_index] + +total +# - + +# Addition along the third axis (axis = 2) + +# apply np.sum() +np.sum(arr_3d, axis=2) + +# add up the elements of the first row of the first matrix +arr_3d[0][0][0] + arr_3d[0][0][1] + arr_3d[0][0][2] + +# second row of the first matrix +arr_3d[0][1][0] + arr_3d[0][1][1] + arr_3d[0][1][2] + +# first row of the second matrix +arr_3d[1][0][0] + arr_3d[1][0][1] + arr_3d[1][0][2] + +# second row of the second matrix +arr_3d[1][1][0] + arr_3d[1][1][1] + arr_3d[1][1][2] + +# + +# Let's create a zero-based 2 x 2 array to record the results +total = np.zeros((2, 2)) + +# let's go through the matrices +for matrix_idx in range(2): + + # by rows of the matrix + for row_idx in range(2): + + # and by columns (iterate values of the row) + for value in arr_3d[matrix_idx][row_idx]: + + # indices matrix_idx, row_idx will record the result of adding + # the elements of each row into a 2 x 2 result matrix + total[matrix_idx][row_idx] += value + +total +# - + +# Addition along the first and second axes (axis = (0, 1)) + +# apply the np.sum() function +np.sum(arr_3d, axis=(0, 1)) + +# + +# when using two cycles, we first add the matrices together +total_0 = np.zeros((2, 3)) + +for i in range(2): + total_0 += arr_3d[i] + +total_0 + +# + +# and then the columns of these matrices +total_1 = np.zeros(3) + +for i in range(2): + total_1 += total_0[i] + +total_1 + +# + +total = np.zeros(3) + +# In two cycles, we will go through the rows of each matrix. +for row_idx in range(2): + for col_idx in range(2): + + # and add them up piece by piece + total += arr_3d[row_idx][col_idx] + +total +# - + +# Addition along all three axes (axis = (0, 1, 2)) + +np.sum(arr_3d, axis=(0, 1, 2)) + +np.sum(arr_3d) + +# ### Operations with arrays + +# #### Function len() + +# lets take a three-dimensional array +arr_3d = np.arange(12).reshape(2, 2, 3) +arr_3d + +# By default, the len() function outputs the +# length of the external dimension. +# these are outer brackets containing two matrices +len(arr_3d) + +# To display the length of the internal +# measurement, i.e., a vector of three elements, +# you need to use indexes. +len(arr_3d[0][0]) + +# #### Entering an array + +# Let's check if the value 3 is included in the arr_3D array. +3 in arr_3d + +# Let's check if the value 11 is in the arr_3D array. +11 not in arr_3d + +# #### Unpacking an array + +# Let's take a_val matrix with three rows and nine columns. +a_val = np.arange(1, 28).reshape(3, 9) +a_val + +# + +# each line can be unpacked into a separate variable +x_val, y_val, z_val = a_val + +# выведем первую переменную (строку) +x_val + +# + +# Now let's unpack the first, last, and remaining elements +# of the first line into separate variables +x_val, *y_val, z_val = a_val[0] + +# выведем каждую переменную +print(x_val) +print(y_val) +print(z_val) +# - + +# #### Changing array elements + +# Let's turn to a two-dimensional array. +arr_2d = np.array([[1, 2, 3], [4, 5, 6]]) +arr_2d + +# replace the first element of the first row by its index +arr_2d[0, 0] = 2 +arr_2d + +# write the value 1 in the first row +arr_2d[0] = 1 +arr_2d + +# Write 0 in the third column of the array. +arr_2d[:, 2] = 0 +arr_2d + +# let's turn to the three-dimensional array +arr_3d = np.arange(12).reshape(2, 2, 3) +arr_3d + +# + +# select the second column of the second matrix and +# replace the values in columns 7 and 10 with 0 and 1 +arr_3d[1, :, 1] = [0, 1] + +# in such an operation, the cut size must match +# the number of values being transferred +arr_3d +# - + +# replace all elements of the array with the number seven +arr_3d.fill(7) +arr_3d + +# #### Sorting an array and reversing the order of its elements + +# Function np.sort() + +# lets take a two-dimensional array +a_arr = np.array([[4, 8, 2], [2, 3, 1]]) +a_arr + +# By default, sorting is performed with the parameter axis = -1 +np.sort(a_arr) + +# for a two-dimensional array, this is axis 1 +np.sort(a_arr, axis=1) + +# Let's look at sorting along the 0 axis. +np.sort(a_arr, axis=0) + +# axis = None initially returns a +# one-dimensional array, +# and then sorts it +np.sort(a_arr, axis=None) + +# Reversing the order of array elements using the slice operator + +# slice operator with step parameter -1 +# sets the reverse order of array elements +reversed_arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[::-1] +reversed_arr + +# The reverse order can be combined with cuts. +reverse_slice = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[-3:3:-1] +reverse_slice + +# in two-dimensional array +a_arr = np.array([[4, 8, 2], [2, 3, 1], [1, 7, 2]]) +a_arr + +# you can set the reverse order for +# two dimensions (axis = (0, 1)) +a_arr[::-1, ::-1] + +# reverse order by external (axis = 0) +a_arr[::-1] + +# and internal dimension (axis = 1) +a_arr[:, ::-1] + +# Reverse order using the np.flip() function + +# by default, sets the reverse order for two dimensions +# same as axis = (0, 1) +np.flip(a_arr) + +# you can also set the reverse order by external +np.flip(a_arr, axis=0) + +# and internal measurements +np.flip(a_arr, axis=1) + +# Sorting in descending order + +# to sort an array in descending order +a_arr = np.array([4, 2, 6, 1, 7, 3, 5]) + +# we can sequentially apply np.sort() and the slice operator +sorted_desc = np.sort(a_arr)[::-1] +sorted_desc + +# the original array has not changed +a_arr + +# You can do it in reverse order, but using the .sort() method. +a_arr[::-1].sort() + +# the change has become permanent +a_arr + +# #### Change in dimension + +# .reshape() + +# lets take a three-dimensional array +arr_3d = np.arange(12).reshape(2, 2, 3) +arr_3d + +# it has 12 elements +arr_3d.size + +# change the dimension while keeping the total number +# of elements the same +arr_2d = arr_3d.reshape(2, 6) +arr_2d + +# np.resize() and .resize() + +# The np.resize() function allows you +# to not keep the previous number of elements. +# Existing elements are copied to new cells. +np.resize(arr_2d, (3, 6)) + +# + +# arr_2D refers to another array, so you first need to make a copy of it +arr_2d_copy = arr_2d.copy() + +# The .resize() method will make a copy, change the dimensions, +# and fill in the gaps with zeros. +arr_2d_copy.resize(4, 6) +arr_2d_copy +# - + +# .flatten() and .ravel() + +# .flatten() converts ("flattens") an array into +# a one-dimensional array and +# creates a copy of the original array +# (like the .copy() method). +arr_3d.flatten() + +# .ravel() does the same thing, +# but does not create a copy of the original +# array and is therefore faster than .flatten(). +arr_3d.ravel() + +# np.newaxis + +# np.newaxis adds a dimension to the array +a_arr = np.array([1, 2, 3]) +a_arr.shape + +# + +# add the first dimension +b_arr = a_arr[np.newaxis, :] + +print(b_arr) +print(b_arr.shape) + +# + +# добавим второе измерение +c_arr = a_arr[:, np.newaxis] + +print(c_arr) +print(c_arr.shape) +# - + +# np.expand_dims() + +# lets take a two-dimensional array +a_arr = np.array([[1, 2], [3, 4]]) +a_arr + +# add an external dimension +np.expand_dims(a_arr, axis=0) + +# add a "middle" measurement +np.expand_dims(a_arr, axis=1) + +# add internal dimension +np.expand_dims(a_arr, axis=2) + +# np.squeeze() + +# Let's take a 4D array in which +# the first and last dimensions contain one element each. +arr_4d = np.arange(9).reshape(1, 3, 3, 1) +arr_4d + +# Remove these measurements using the np.squeeze() function. +np.squeeze(arr_4d) + +# the new array has only two dimensions +squeezed_shape = np.squeeze(arr_4d).shape +squeezed_shape + +# #### Merging arrays + +# np.concatenate() + +# Let's create two square arrays. +a_arr = np.arange(4).reshape(2, 2) +a_arr + +b_arr = np.arange(4, 8).reshape(2, 2) +b_arr + +# Merging arrays +np.concatenate((a_arr, b_arr), axis=0) + +# the same along axis 1 +np.concatenate((a_arr, b_arr), axis=1) + +# np.stack() + +# The difference here is that we are +# adding a new axis (dimension). +np.stack((a_arr, b_arr), axis=0) + +np.stack((a_arr, b_arr), axis=1) + +np.stack((a_arr, b_arr), axis=2) diff --git a/python/makarov/chapter_11_pandas_intro.ipynb b/python/makarov/chapter_11_pandas_intro.ipynb new file mode 100644 index 00000000..9388a3df --- /dev/null +++ b/python/makarov/chapter_11_pandas_intro.ipynb @@ -0,0 +1,3502 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "3c9dc453", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Pandas library.'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Pandas library.\"\"\"" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "e158cac9", + "metadata": {}, + "source": [ + "## DataFrame and Series\n", + "\n", + "Pandas has two main objects: DataFrame and Series. To simplify things a little, we can say that DataFrame is a table (and therefore a two-dimensional array), while Series is a column in this table (and therefore a one-dimensional array).\n", + "![image.png](attachment:image.png)\n", + "\n", + "### Creating a DataFrame\n", + "#### Method 1. Creating a DataFrame from file" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6a672643", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "id": "f2793b85", + "metadata": {}, + "source": [ + "```\n", + "import pandas as pd\n", + "csv_zip = pd.read_csv(\"/Users/Downloads/train.csv\")\n", + "csv_zip.head(3) \n", + "\n", + "```\n", + "\n", + "A dataframe can be created by importing files in various formats. We have already done this with .csv files using the pd.read_csv() function. Similarly, files in other formats, such as MS Excel or html, can be imported." + ] + }, + { + "cell_type": "markdown", + "id": "5d3befdf", + "metadata": {}, + "source": [ + "```\n", + "excel_data = pd.read_excel(\"/Users/dayal/Downloads/iris.xlsx\", sheet_name=0)\n", + "excel_data.head(3)\n", + "```\n", + "\n", + "MS Excel. Similarly, we can import files in Excel format.\n", + "\n", + "In example above method .head(3) will display first 3 lines of DataFrame" + ] + }, + { + "cell_type": "markdown", + "id": "57ffa94c", + "metadata": {}, + "source": [ + "```\n", + "html_data = pd.read_html(\n", + " \"https://en.wikipedia.org/wiki/World_population\",\n", + " storage_options={\"User-Agent\": \"Mozilla/5.0\"},\n", + ")\n", + "html_data[0]\n", + "```\n", + "\n", + " Data can be loaded not only from a file, but also from the Internet. The read_html() function is suitable for this purpose. By and large, this is an example of simple web scraping, i.e., obtaining information from web pages in an automated mode." + ] + }, + { + "cell_type": "markdown", + "id": "1f7c0261", + "metadata": {}, + "source": [ + "#### Method 2. Connecting to SQL\n" + ] + }, + { + "cell_type": "markdown", + "id": "4f03e908", + "metadata": {}, + "source": [ + "```\n", + "conn = sql.connect(\"/Users/dayal/Downloads/chinook.db\")\n", + "\n", + "sql_data = pd.read_sql(\"SELECT * FROM tracks;\", conn)\n", + "\n", + "sql_data.head(3)\n", + "```\n", + "\n", + "The Pandas library allows you to retrieve information directly from an SQL database. As an example, let's take the popular Chinook training database, which contains information about a digital media store." + ] + }, + { + "cell_type": "markdown", + "id": "2eba7e23", + "metadata": {}, + "source": [ + "#### Method 3. Creating a DataFrame from `dict()` type\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "841a651d", + "metadata": {}, + "outputs": [], + "source": [ + "country: np.ndarray = np.array(\n", + " [\n", + " \"China\",\n", + " \"Vietnam\",\n", + " \"United Kingdom\",\n", + " \"Russia\",\n", + " \"Argentina\",\n", + " \"Bolivia\",\n", + " \"South Africa\",\n", + " ]\n", + ")\n", + "capital: list[str] = [\n", + " \"Beijing\",\n", + " \"Hanoi\",\n", + " \"London\",\n", + " \"Moscow\",\n", + " \"Buenos Aires\",\n", + " \"Sucre\",\n", + " \"Pretoria\",\n", + "]\n", + "population: list[int] = [1400, 97, 67, 144, 45, 12, 59]\n", + "area: list[float] = [9.6, 0.3, 0.2, 17.1, 2.8, 1.1, 1.2]\n", + "sea: list[int] = [1] * 5 + [0, 1]\n", + "# country: NumPy array of country names (7 entries)\n", + "# capital: list of capital city names\n", + "# corresponding to each country\n", + "# population: list of population values\n", + "# aligned with the country order\n", + "# area: list of area values aligned with\n", + "# the country order (units not specified)\n", + "# sea: list of binary flags where 1 indicates\n", + "# access to the sea and 0 indicates no sea access\n", + "# These parallel sequences will be combined\n", + "# into a dictionary/DataFrame in the following cell." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "95fa6206", + "metadata": {}, + "outputs": [], + "source": [ + "countries_dict: dict[str, list[str] | list[int] | list[float]] = {}\n", + "\n", + "countries_dict[\"country\"] = list(country)\n", + "countries_dict[\"capital\"] = capital\n", + "countries_dict[\"population\"] = population\n", + "countries_dict[\"area\"] = area\n", + "countries_dict[\"sea\"] = sea\n", + "# Initialize an empty dictionary to hold columns for the DataFrame.\n", + "# Convert the NumPy array `country` to\n", + "# Python list and store it under the 'country' key.\n", + "# Store the list of capital city names under the 'capital' key.\n", + "# Store the population values under the 'population' key.\n", + "# Store the area values under the 'area' key.\n", + "# Store the binary sea-access flags under the 'sea' key.\n", + "# Ensure all columns have equal length\n", + "# to prevent errors when creating the DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6b59f59f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
0ChinaBeijing14009.61
1VietnamHanoi970.31
2United KingdomLondon670.21
3RussiaMoscow14417.11
4ArgentinaBuenos Aires452.81
5BoliviaSucre121.10
6South AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "0 China Beijing 1400 9.6 1\n", + "1 Vietnam Hanoi 97 0.3 1\n", + "2 United Kingdom London 67 0.2 1\n", + "3 Russia Moscow 144 17.1 1\n", + "4 Argentina Buenos Aires 45 2.8 1\n", + "5 Bolivia Sucre 12 1.1 0\n", + "6 South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create a Pandas DataFrame from the dictionary and display it.\n", + "countries = pd.DataFrame(countries_dict)\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "8ab512ee", + "metadata": {}, + "source": [ + "#### Method 4. Creating a DataFrame from Numpy 2D(2 dimensional) array\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8ef37d52", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012
0111
1222
2333
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "0 1 1 1\n", + "1 2 2 2\n", + "2 3 3 3" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])\n", + "\n", + "pd.DataFrame(arr)" + ] + }, + { + "cell_type": "markdown", + "id": "0d5a3ae7", + "metadata": {}, + "source": [ + "## DataFrame structure and properties\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c0816402", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['country', 'capital', 'population', 'area', 'sea'], dtype='object')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display columns of dataframe object\n", + "countries.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7982c280", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "RangeIndex(start=0, stop=7, step=1)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display index of dataframe object\n", + "countries.index" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "2ad80058", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([['China', 'Beijing', 1400, 9.6, 1],\n", + " ['Vietnam', 'Hanoi', 97, 0.3, 1],\n", + " ['United Kingdom', 'London', 67, 0.2, 1],\n", + " ['Russia', 'Moscow', 144, 17.1, 1],\n", + " ['Argentina', 'Buenos Aires', 45, 2.8, 1],\n", + " ['Bolivia', 'Sucre', 12, 1.1, 0],\n", + " ['South Africa', 'Pretoria', 59, 1.2, 1]], dtype=object)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# display values of dataframe object\n", + "countries.values" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8210d8ea", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "RangeIndex(start=0, stop=7, step=1)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# We can also obtain the index and column\n", + "# names using the axes attribute (plural of axis) with\n", + "# indices [0] and [1], respectively.\n", + "countries.axes[0]" + ] + }, + { + "cell_type": "markdown", + "id": "4e8fbdd6", + "metadata": {}, + "source": [ + "In general, it is useful to remember that axis = 0 allows you to apply any method to the rows of a data frame, and axis = 1, respectively, to the columns." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4189e447", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['country', 'capital', 'population', 'area', 'sea'], dtype='object')" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.axes[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "17a568db", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, (7, 5), 35)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.ndim, countries.shape, countries.size" + ] + }, + { + "cell_type": "markdown", + "id": "dd41a2eb", + "metadata": {}, + "source": [ + "We can also view the number of measurements, the dimension, and the total number of elements in the data frame using the ndim, shape, and size attributes, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "063beee3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "country object\n", + "capital object\n", + "population int64\n", + "area float64\n", + "sea int64\n", + "dtype: object" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Returns the data type of each column.\n", + "countries.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "a7a81b65", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index 132\n", + "country 56\n", + "capital 56\n", + "population 56\n", + "area 56\n", + "sea 56\n", + "dtype: int64" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.memory_usage()" + ] + }, + { + "cell_type": "markdown", + "id": "bd70514b", + "metadata": {}, + "source": [ + "Using the `.memory_usage()` method, we can view the amount of memory occupied by columns in bytes." + ] + }, + { + "cell_type": "markdown", + "id": "3335bf25", + "metadata": {}, + "source": [ + "## Index\n", + "### Assigning an index\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b8d8876f", + "metadata": {}, + "outputs": [], + "source": [ + "custom_index: list[str] = [\"CN\", \"VN\", \"GB\", \"RU\", \"AR\", \"BO\", \"ZA\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "20756fd9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
RURussiaMoscow14417.11
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries = pd.DataFrame(countries_dict, index=custom_index)\n", + "countries" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "eec6aac3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
indexcountrycapitalpopulationareasea
0CNChinaBeijing14009.61
1VNVietnamHanoi970.31
2GBUnited KingdomLondon670.21
3RURussiaMoscow14417.11
4ARArgentinaBuenos Aires452.81
5BOBoliviaSucre121.10
6ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " index country capital population area sea\n", + "0 CN China Beijing 1400 9.6 1\n", + "1 VN Vietnam Hanoi 97 0.3 1\n", + "2 GB United Kingdom London 67 0.2 1\n", + "3 RU Russia Moscow 144 17.1 1\n", + "4 AR Argentina Buenos Aires 45 2.8 1\n", + "5 BO Bolivia Sucre 12 1.1 0\n", + "6 ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The index can be reset using the\n", + "# .reset_index() method.\n", + "countries.reset_index(inplace=True)\n", + "countries" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "6a667dae", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
index
CNChinaBeijing14009.61
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
RURussiaMoscow14417.11
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "index \n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# As we can see, the previous index has become\n", + "# a separate column. Let's make this column\n", + "# an index again using the .set_index() method.\n", + "countries.set_index(\"index\", inplace=True)\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "8dd99d84", + "metadata": {}, + "source": [ + "Let's reset the index again, but this time we won't make it a separate column. To do this, we'll pass the parameter drop = True to the .`reset_index()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "07d8e2c6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
0ChinaBeijing14009.61
1VietnamHanoi970.31
2United KingdomLondon670.21
3RussiaMoscow14417.11
4ArgentinaBuenos Aires452.81
5BoliviaSucre121.10
6South AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "0 China Beijing 1400 9.6 1\n", + "1 Vietnam Hanoi 97 0.3 1\n", + "2 United Kingdom London 67 0.2 1\n", + "3 Russia Moscow 144 17.1 1\n", + "4 Argentina Buenos Aires 45 2.8 1\n", + "5 Bolivia Sucre 12 1.1 0\n", + "6 South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.reset_index(drop=True, inplace=True)\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "045182f9", + "metadata": {}, + "source": [ + "You can create your own index by simply placing new values in the index attribute." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "c67a1fac", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
RURussiaMoscow14417.11
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.index = pd.Index(custom_index)\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "20ebe559", + "metadata": {}, + "source": [ + "## MultiIndex\n", + "\n", + "A multi-level (MultiIndex) or hierarchical index allows you to specify multiple levels for indexing rows or columns. An \"external\" index combines several elements of an \"internal\" index." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "20a37055", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namesdata
countrycapitalpopulationareasea
(Asia, CN)ChinaBeijing14009.61
(Asia, VN)VietnamHanoi970.31
(Europe, GB)United KingdomLondon670.21
(Europe, RU)RussiaMoscow14417.11
(S. America, AR)ArgentinaBuenos Aires452.81
(S. America, BO)BoliviaSucre121.10
(Africa, ZA)South AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " names data \n", + " country capital population area sea\n", + "(Asia, CN) China Beijing 1400 9.6 1\n", + "(Asia, VN) Vietnam Hanoi 97 0.3 1\n", + "(Europe, GB) United Kingdom London 67 0.2 1\n", + "(Europe, RU) Russia Moscow 144 17.1 1\n", + "(S. America, AR) Argentina Buenos Aires 45 2.8 1\n", + "(S. America, BO) Bolivia Sucre 12 1.1 0\n", + "(Africa, ZA) South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a list of tuples with\n", + "# name of the continent and the country code\n", + "rows: list[tuple[str, str]] = [\n", + " (\"Asia\", \"CN\"),\n", + " (\"Asia\", \"VN\"),\n", + " (\"Europe\", \"GB\"),\n", + " (\"Europe\", \"RU\"),\n", + " (\"S. America\", \"AR\"),\n", + " (\"S. America\", \"BO\"),\n", + " (\"Africa\", \"ZA\"),\n", + "]\n", + "\n", + "# In the columns, we will combine the names of\n", + "# countries and capitals into the category names.\n", + "# Population size, area, and access to\n", + "# the sea will be combined into the category data.\n", + "cols: list[tuple[str, str]] = [\n", + " (\"names\", \"country\"),\n", + " (\"names\", \"capital\"),\n", + " (\"data\", \"population\"),\n", + " (\"data\", \"area\"),\n", + " (\"data\", \"sea\"),\n", + "]\n", + "\n", + "# Now let's create a hierarchical index for\n", + "# rows and columns using the pd.MultiIndex.from_tuples() function.\n", + "custom_multindex = pd.MultiIndex.from_tuples(rows, names=[\"region\", \"code\"])\n", + "# # Let's do the same for columns\n", + "custom_multicols = pd.MultiIndex.from_tuples(cols)\n", + "\n", + "# Finally, we need to transfer these indexes to\n", + "# the index and columns attributes and display it\n", + "countries.index = pd.Index(custom_multindex)\n", + "countries.columns = custom_multicols\n", + "\n", + "countries" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ec279325", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
RURussiaMoscow14417.11
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's return to the usual index and column names.\n", + "custom_cols = [\"country\", \"capital\", \"population\", \"area\", \"sea\"]\n", + "\n", + "countries.index = pd.Index(custom_index)\n", + "countries.columns = custom_cols\n", + "\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "c99e0468", + "metadata": {}, + "source": [ + "## Conversion to other formats\n" + ] + }, + { + "cell_type": "markdown", + "id": "ad7580b0", + "metadata": {}, + "source": [ + "A datetime frame can be converted to a dictionary using the .to_dict() method." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "bc3b5b4f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'country': {'CN': 'China', 'VN': 'Vietnam', 'GB': 'United Kingdom', 'RU': 'Russia', 'AR': 'Argentina', 'BO': 'Bolivia', 'ZA': 'South Africa'}, 'capital': {'CN': 'Beijing', 'VN': 'Hanoi', 'GB': 'London', 'RU': 'Moscow', 'AR': 'Buenos Aires', 'BO': 'Sucre', 'ZA': 'Pretoria'}, 'population': {'CN': 1400, 'VN': 97, 'GB': 67, 'RU': 144, 'AR': 45, 'BO': 12, 'ZA': 59}, 'area': {'CN': 9.6, 'VN': 0.3, 'GB': 0.2, 'RU': 17.1, 'AR': 2.8, 'BO': 1.1, 'ZA': 1.2}, 'sea': {'CN': 1, 'VN': 1, 'GB': 1, 'RU': 1, 'AR': 1, 'BO': 0, 'ZA': 1}}\n" + ] + } + ], + "source": [ + "print(countries.to_dict())" + ] + }, + { + "cell_type": "markdown", + "id": "ac9d875e", + "metadata": {}, + "source": [ + "Similarly, the .to_numpy() method converts data into a Numpy array." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "4468b272", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([['China', 'Beijing', 1400, 9.6, 1],\n", + " ['Vietnam', 'Hanoi', 97, 0.3, 1],\n", + " ['United Kingdom', 'London', 67, 0.2, 1],\n", + " ['Russia', 'Moscow', 144, 17.1, 1],\n", + " ['Argentina', 'Buenos Aires', 45, 2.8, 1],\n", + " ['Bolivia', 'Sucre', 12, 1.1, 0],\n", + " ['South Africa', 'Pretoria', 59, 1.2, 1]], dtype=object)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.to_numpy()" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "d4f8cce1", + "metadata": {}, + "source": [ + "```\n", + "countries.to_csv(\"countries.csv\", index=False)\n", + "```\n", + "\n", + "In addition, we can save the dataframe to a file (in Google Colab, it will appear in session storage). For example, this could be a file in .csv format, in which case we need to use the .to_csv() function.\n", + "\n", + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "id": "193f3e6e", + "metadata": {}, + "source": [ + "The .to_list() method allows you to convert a Series object (a dataframe column) into a list." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "db26f235", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['China',\n", + " 'Vietnam',\n", + " 'United Kingdom',\n", + " 'Russia',\n", + " 'Argentina',\n", + " 'Bolivia',\n", + " 'South Africa']" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.country.tolist()" + ] + }, + { + "cell_type": "markdown", + "id": "fa5f8b7d", + "metadata": {}, + "source": [ + "## Creating Series\n", + "### Creating Series from `list()` type\n" + ] + }, + { + "cell_type": "markdown", + "id": "53660b6c", + "metadata": {}, + "source": [ + "A Series object can be created from a list. Let's take the following list with country names." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "421a18d9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 China\n", + "1 South Africa\n", + "2 United Kingdom\n", + "3 Russia\n", + "4 Argentina\n", + "5 Vietnam\n", + "6 Australia\n", + "dtype: object" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "country_list: list[str] = [\n", + " \"China\",\n", + " \"South Africa\",\n", + " \"United Kingdom\",\n", + " \"Russia\",\n", + " \"Argentina\",\n", + " \"Vietnam\",\n", + " \"Australia\",\n", + "]\n", + "\n", + "country_series = pd.Series(country_list, dtype=str)\n", + "country_series" + ] + }, + { + "cell_type": "markdown", + "id": "9006da08", + "metadata": {}, + "source": [ + "Please note that a numeric index was automatically created for the Series object. We can use it to access the elements of this object." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "4d9bef8f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'China'" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "country_series.iloc[0]" + ] + }, + { + "cell_type": "markdown", + "id": "7ee4814b", + "metadata": {}, + "source": [ + "## Доступ к строкам и столбцам\n", + "### Циклы в датафрейме\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba80c06a", + "metadata": {}, + "outputs": [], + "source": [ + "for column in countries:\n", + " print(column)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a8a5523", + "metadata": {}, + "outputs": [], + "source": [ + "for index, row in countries.iterrows():\n", + " print(index)\n", + " print(row)\n", + " print(\"...\")\n", + " print(type(row))\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbf0ada3", + "metadata": {}, + "outputs": [], + "source": [ + "for _, row in countries.iterrows():\n", + " print(row[\"capital\"] + \" is the capital if \" + row[\"country\"])\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "d0b78e49", + "metadata": {}, + "source": [ + "## Доступ к столбцам\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c5726eb", + "metadata": {}, + "outputs": [], + "source": [ + "countries[\"capital\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ccfb612", + "metadata": {}, + "outputs": [], + "source": [ + "countries.capital" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5dfc4f16", + "metadata": {}, + "outputs": [], + "source": [ + "type(countries.capital)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57886a88", + "metadata": {}, + "outputs": [], + "source": [ + "countries[[\"capital\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "72eaa805", + "metadata": {}, + "outputs": [], + "source": [ + "countries[[\"capital\", \"area\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e4d7c4f", + "metadata": {}, + "outputs": [], + "source": [ + "countries.filter(items=[\"capital\", \"population\"])" + ] + }, + { + "cell_type": "markdown", + "id": "2025fef2", + "metadata": {}, + "source": [ + "## Доступ к строкам\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e98ef47e", + "metadata": {}, + "outputs": [], + "source": [ + "countries[1:5]" + ] + }, + { + "cell_type": "markdown", + "id": "db3c76a6", + "metadata": {}, + "source": [ + "## Методы .loc[] и .iloc[]\n", + "### Метод .loc[]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "369583af", + "metadata": {}, + "outputs": [], + "source": [ + "countries.loc[[\"CN\", \"RU\", \"VN\"], [\"capital\", \"population\", \"area\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e058e623", + "metadata": {}, + "outputs": [], + "source": [ + "countries.loc[:, [\"capital\", \"population\", \"area\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dd242e9", + "metadata": {}, + "outputs": [], + "source": [ + "countries.loc[:, [False, False, False, False, True]]" + ] + }, + { + "cell_type": "markdown", + "id": "6b475413", + "metadata": {}, + "source": [ + "## Метод .get_loc()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f823381e", + "metadata": {}, + "outputs": [], + "source": [ + "countries.index.get_loc(\"RU\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbc3cf21", + "metadata": {}, + "outputs": [], + "source": [ + "countries.columns.get_loc(\"country\")" + ] + }, + { + "cell_type": "markdown", + "id": "eccf5fc5", + "metadata": {}, + "source": [ + "## Метод .iloc[]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f838b8e7", + "metadata": {}, + "outputs": [], + "source": [ + "countries.iloc[[0, 3, 5], [0, 1, 2]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae5515e6", + "metadata": {}, + "outputs": [], + "source": [ + "countries.iloc[:3, -2:]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7e2fc8a", + "metadata": {}, + "outputs": [], + "source": [ + "countries[[\"population\", \"area\"]].iloc[[0, 3]]" + ] + }, + { + "cell_type": "markdown", + "id": "20c986b9", + "metadata": {}, + "source": [ + "### Creating Series from `dict` type" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "0f78b649", + "metadata": {}, + "outputs": [], + "source": [ + "country_dict: dict[str, str] = {\n", + " \"CN\": \"China\",\n", + " \"ZA\": \"South Africa\",\n", + " \"GB\": \"United Kingdom\",\n", + " \"RU\": \"Russia\",\n", + " \"AR\": \"Argentina\",\n", + " \"VN\": \"Vietnam\",\n", + " \"AU\": \"Australia\",\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "089cdfce", + "metadata": {}, + "source": [ + "Let's convert dict to `pd.Series()` " + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "137050e3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "CN China\n", + "ZA South Africa\n", + "GB United Kingdom\n", + "RU Russia\n", + "AR Argentina\n", + "VN Vietnam\n", + "AU Australia\n", + "dtype: object" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "country_series_2 = pd.Series(country_dict)\n", + "country_series_2" + ] + }, + { + "cell_type": "markdown", + "id": "1e58bcb8", + "metadata": {}, + "source": [ + "## Access via multilevel index" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "0501825a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namesdata
countrycapitalpopulationareasea
(Asia, CN)ChinaBeijing14009.61
(Asia, VN)VietnamHanoi970.31
(Europe, GB)United KingdomLondon670.21
(Europe, RU)RussiaMoscow14417.11
(S. America, AR)ArgentinaBuenos Aires452.81
(S. America, BO)BoliviaSucre121.10
(Africa, ZA)South AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " names data \n", + " country capital population area sea\n", + "(Asia, CN) China Beijing 1400 9.6 1\n", + "(Asia, VN) Vietnam Hanoi 97 0.3 1\n", + "(Europe, GB) United Kingdom London 67 0.2 1\n", + "(Europe, RU) Russia Moscow 144 17.1 1\n", + "(S. America, AR) Argentina Buenos Aires 45 2.8 1\n", + "(S. America, BO) Bolivia Sucre 12 1.1 0\n", + "(Africa, ZA) South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Assign the hierarchical index `custom_multindex` to the DataFrame `countries`\n", + "countries.index = pd.Index(custom_multindex)\n", + "# Assign the hierarchical columns `custom_multicols` to the DataFrame `countries`\n", + "countries.columns = custom_multicols\n", + "# Display the DataFrame `countries` so its contents are shown in the notebook output\n", + "countries" + ] + }, + { + "cell_type": "markdown", + "id": "44fb621b", + "metadata": {}, + "source": [ + "## Method .at[]\n", + "\n", + "The .at[] method is suitable for retrieving or writing a single data frame value.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "a4c0e62d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Beijing'" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.at[\"CN\", \"capital\"]" + ] + }, + { + "cell_type": "markdown", + "id": "96181ddb", + "metadata": {}, + "source": [ + "## Filters\n", + "### Logical mask\n" + ] + }, + { + "cell_type": "markdown", + "id": "a5b79f96", + "metadata": {}, + "source": [ + "As with the Numpy array, we can create a Boolean mask for the dataframe, in which unwanted values will be marked as False." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "66146a08", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "CN True\n", + "VN False\n", + "GB False\n", + "RU False\n", + "AR False\n", + "BO False\n", + "ZA False\n", + "Name: population, dtype: bool" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.population > 1000" + ] + }, + { + "cell_type": "markdown", + "id": "ec7f6c4c", + "metadata": {}, + "source": [ + "By applying this mask to the original data frame, we will obtain only those values that are marked as True." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "575cb9f9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries[countries.population > 1000]" + ] + }, + { + "cell_type": "markdown", + "id": "ea78367a", + "metadata": {}, + "source": [ + "We can apply two masks to the data frame, combined, for example, with the logical AND operator." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "2ae7ba6a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries[(countries.population > 50) & (countries.area < 2)]" + ] + }, + { + "cell_type": "markdown", + "id": "fe761df7", + "metadata": {}, + "source": [ + "Here is another syntax option. It is convenient to use if you have many conditions by which you want to filter the data frame." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "0a9c7615", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
VNVietnamHanoi970.31
RURussiaMoscow14417.11
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "RU Russia Moscow 144 17.1 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# First, create the masks we need.\n", + "population_mask = countries.population > 70\n", + "area_mask = countries.population < 50\n", + "# then combine them according to\n", + "# the necessary conditions (in this case OR)\n", + "mask = population_mask | area_mask\n", + "\n", + "# and apply the mask to the original data frame\n", + "countries[mask]" + ] + }, + { + "cell_type": "markdown", + "id": "3e9aa091", + "metadata": {}, + "source": [ + "## Method .query()\n" + ] + }, + { + "cell_type": "markdown", + "id": "1337b3a3", + "metadata": {}, + "source": [ + "The .query() method allows you to specify a filtering condition \"in your own words.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "5fa73113", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# For example, let's select countries with a population\n", + "# more than 50 million people and an area\n", + "# less than two million square kilometers.\n", + "\n", + "countries.query(\"population > 50 and area < 2\")" + ] + }, + { + "cell_type": "markdown", + "id": "1ab4d278", + "metadata": {}, + "source": [ + "When filtering by string values (which are enclosed in quotation marks), you must use different quotation marks: double quotation marks for the .query() method and single quotation marks for string values, or vice versa." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "7bb113ed", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
GBUnited KingdomLondon670.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "GB United Kingdom London 67 0.2 1" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# let's display data for the United Kingdom\n", + "countries.query('country == \"United Kingdom\"')" + ] + }, + { + "cell_type": "markdown", + "id": "3b5820e3", + "metadata": {}, + "source": [ + "## Other filtering methods\n" + ] + }, + { + "cell_type": "markdown", + "id": "569264fd", + "metadata": {}, + "source": [ + "Using the .isin() method, we can check for the presence of multiple values in a specific column and then use the result as a logical mask." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "7298a4d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "RU Russia Moscow 144 17.1 1\n" + ] + } + ], + "source": [ + "keyword_list = [\"Beijing\", \"Moscow\", \"Hanoi\"]\n", + "\n", + "print(countries[countries.capital.isin(keyword_list)])" + ] + }, + { + "cell_type": "markdown", + "id": "47078966", + "metadata": {}, + "source": [ + "Similarly, you can use the .startswith() method." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "5ddff5aa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "ZA South Africa Pretoria 59 1.2 1\n" + ] + } + ], + "source": [ + "print(countries[~countries.country.str.startswith(\"A\")])" + ] + }, + { + "cell_type": "markdown", + "id": "81c52d73", + "metadata": {}, + "source": [ + "The .nlargest() method allows you to find the rows with the highest value in a specific column." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "d7303d18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
RURussiaMoscow14417.11
VNVietnamHanoi970.31
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "RU Russia Moscow 144 17.1 1\n", + "VN Vietnam Hanoi 97 0.3 1" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.nlargest(3, \"population\")" + ] + }, + { + "cell_type": "markdown", + "id": "129ba3d6", + "metadata": {}, + "source": [ + "The .argmax() method returns the index of the row containing the highest value in a specified column." + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "82468def", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.area.argmax()" + ] + }, + { + "cell_type": "markdown", + "id": "e124551b", + "metadata": {}, + "source": [ + "Let's see which country corresponds to this index." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "acfbd12f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
RURussiaMoscow14417.11
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "RU Russia Moscow 144 17.1 1" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "largest_area_country = countries.iloc[[countries.area.argmax()]]\n", + "largest_area_country" + ] + }, + { + "cell_type": "markdown", + "id": "0e8c278a", + "metadata": {}, + "source": [ + "Recall that the .loc[] method can accept Boolean data types. Let's use this property to create a filter." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "04d5ef94", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
CNChinaBeijing14009.61
VNVietnamHanoi970.31
RURussiaMoscow14417.11
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "CN China Beijing 1400 9.6 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "RU Russia Moscow 144 17.1 1" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.loc[countries.population > 90, :]" + ] + }, + { + "cell_type": "markdown", + "id": "4a006843", + "metadata": {}, + "source": [ + "The .filter() method, when using the like parameter, searches for matches with the desired phrase in the index (if axis = 0) or column names (if axis = 1)." + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "01e0002c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.filter(like=\"ZA\", axis=0)" + ] + }, + { + "cell_type": "markdown", + "id": "bb25ba4b", + "metadata": {}, + "source": [ + "## Sorting\n" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "b572e696", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
BOBoliviaSucre121.10
ARArgentinaBuenos Aires452.81
ZASouth AfricaPretoria591.21
GBUnited KingdomLondon670.21
VNVietnamHanoi970.31
RURussiaMoscow14417.11
CNChinaBeijing14009.61
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "BO Bolivia Sucre 12 1.1 0\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "ZA South Africa Pretoria 59 1.2 1\n", + "GB United Kingdom London 67 0.2 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "RU Russia Moscow 144 17.1 1\n", + "CN China Beijing 1400 9.6 1" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# sort by the population column without saving changes,\n", + "# in ascending order (default value)\n", + "countries.sort_values(by=\"population\", inplace=False, ascending=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "f75dcbeb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
RURussiaMoscow14417.11
CNChinaBeijing14009.61
ARArgentinaBuenos Aires452.81
ZASouth AfricaPretoria591.21
BOBoliviaSucre121.10
VNVietnamHanoi970.31
GBUnited KingdomLondon670.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "RU Russia Moscow 144 17.1 1\n", + "CN China Beijing 1400 9.6 1\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "ZA South Africa Pretoria 59 1.2 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "GB United Kingdom London 67 0.2 1" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now let's sort by two columns in descending order\n", + "countries.sort_values(by=[\"area\", \"population\"], inplace=False, ascending=False)" + ] + }, + { + "cell_type": "markdown", + "id": "efa6f851", + "metadata": {}, + "source": [ + "In addition, you can sort rows by index using the .sort_index() method." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "4cfb597c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrycapitalpopulationareasea
ARArgentinaBuenos Aires452.81
BOBoliviaSucre121.10
CNChinaBeijing14009.61
GBUnited KingdomLondon670.21
RURussiaMoscow14417.11
VNVietnamHanoi970.31
ZASouth AfricaPretoria591.21
\n", + "
" + ], + "text/plain": [ + " country capital population area sea\n", + "AR Argentina Buenos Aires 45 2.8 1\n", + "BO Bolivia Sucre 12 1.1 0\n", + "CN China Beijing 1400 9.6 1\n", + "GB United Kingdom London 67 0.2 1\n", + "RU Russia Moscow 144 17.1 1\n", + "VN Vietnam Hanoi 97 0.3 1\n", + "ZA South Africa Pretoria 59 1.2 1" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "countries.sort_index()" + ] + } + ], + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/makarov/chapter_11_pandas_intro.py b/python/makarov/chapter_11_pandas_intro.py new file mode 100644 index 00000000..d89daec4 --- /dev/null +++ b/python/makarov/chapter_11_pandas_intro.py @@ -0,0 +1,480 @@ +"""Pandas library.""" + +# ## DataFrame and Series +# +# Pandas has two main objects: DataFrame and Series. To simplify things a little, we can say that DataFrame is a table (and therefore a two-dimensional array), while Series is a column in this table (and therefore a one-dimensional array). +# ![image.png](attachment:image.png) +# +# ### Creating a DataFrame +# #### Method 1. Creating a DataFrame from file + +import numpy as np +import pandas as pd + +# ``` +# import pandas as pd +# csv_zip = pd.read_csv("/Users/Downloads/train.csv") +# csv_zip.head(3) +# +# ``` +# +# A dataframe can be created by importing files in various formats. We have already done this with .csv files using the pd.read_csv() function. Similarly, files in other formats, such as MS Excel or html, can be imported. + +# ``` +# excel_data = pd.read_excel("/Users/dayal/Downloads/iris.xlsx", sheet_name=0) +# excel_data.head(3) +# ``` +# +# MS Excel. Similarly, we can import files in Excel format. +# +# In example above method .head(3) will display first 3 lines of DataFrame + +# ``` +# html_data = pd.read_html( +# "https://en.wikipedia.org/wiki/World_population", +# storage_options={"User-Agent": "Mozilla/5.0"}, +# ) +# html_data[0] +# ``` +# +# Data can be loaded not only from a file, but also from the Internet. The read_html() function is suitable for this purpose. By and large, this is an example of simple web scraping, i.e., obtaining information from web pages in an automated mode. + +# #### Method 2. Connecting to SQL +# + +# ``` +# conn = sql.connect("/Users/dayal/Downloads/chinook.db") +# +# sql_data = pd.read_sql("SELECT * FROM tracks;", conn) +# +# sql_data.head(3) +# ``` +# +# The Pandas library allows you to retrieve information directly from an SQL database. As an example, let's take the popular Chinook training database, which contains information about a digital media store. + +# #### Method 3. Creating a DataFrame from `dict()` type +# + +country: np.ndarray = np.array( + [ + "China", + "Vietnam", + "United Kingdom", + "Russia", + "Argentina", + "Bolivia", + "South Africa", + ] +) +capital: list[str] = [ + "Beijing", + "Hanoi", + "London", + "Moscow", + "Buenos Aires", + "Sucre", + "Pretoria", +] +population: list[int] = [1400, 97, 67, 144, 45, 12, 59] +area: list[float] = [9.6, 0.3, 0.2, 17.1, 2.8, 1.1, 1.2] +sea: list[int] = [1] * 5 + [0, 1] +# country: NumPy array of country names (7 entries) +# capital: list of capital city names +# corresponding to each country +# population: list of population values +# aligned with the country order +# area: list of area values aligned with +# the country order (units not specified) +# sea: list of binary flags where 1 indicates +# access to the sea and 0 indicates no sea access +# These parallel sequences will be combined +# into a dictionary/DataFrame in the following cell. + +# + +countries_dict: dict[str, list[str] | list[int] | list[float]] = {} + +countries_dict["country"] = list(country) +countries_dict["capital"] = capital +countries_dict["population"] = population +countries_dict["area"] = area +countries_dict["sea"] = sea +# Initialize an empty dictionary to hold columns for the DataFrame. +# Convert the NumPy array `country` to +# Python list and store it under the 'country' key. +# Store the list of capital city names under the 'capital' key. +# Store the population values under the 'population' key. +# Store the area values under the 'area' key. +# Store the binary sea-access flags under the 'sea' key. +# Ensure all columns have equal length +# to prevent errors when creating the DataFrame. +# - + +# Create a Pandas DataFrame from the dictionary and display it. +countries = pd.DataFrame(countries_dict) +countries + +# #### Method 4. Creating a DataFrame from Numpy 2D(2 dimensional) array +# + +# + +arr = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]) + +pd.DataFrame(arr) +# - + +# ## DataFrame structure and properties +# + +# display columns of dataframe object +countries.columns + +# display index of dataframe object +countries.index + +# display values of dataframe object +countries.values + +# We can also obtain the index and column +# names using the axes attribute (plural of axis) with +# indices [0] and [1], respectively. +countries.axes[0] + +# In general, it is useful to remember that axis = 0 allows you to apply any method to the rows of a data frame, and axis = 1, respectively, to the columns. + +countries.axes[1] + +countries.ndim, countries.shape, countries.size + +# We can also view the number of measurements, the dimension, and the total number of elements in the data frame using the ndim, shape, and size attributes, respectively. + +# Returns the data type of each column. +countries.dtypes + +countries.memory_usage() + +# Using the `.memory_usage()` method, we can view the amount of memory occupied by columns in bytes. + +# ## Index +# ### Assigning an index +# + +custom_index: list[str] = ["CN", "VN", "GB", "RU", "AR", "BO", "ZA"] + +countries = pd.DataFrame(countries_dict, index=custom_index) +countries + +# The index can be reset using the +# .reset_index() method. +countries.reset_index(inplace=True) +countries + +# As we can see, the previous index has become +# a separate column. Let's make this column +# an index again using the .set_index() method. +countries.set_index("index", inplace=True) +countries + +# Let's reset the index again, but this time we won't make it a separate column. To do this, we'll pass the parameter drop = True to the .`reset_index()` method. + +countries.reset_index(drop=True, inplace=True) +countries + +# You can create your own index by simply placing new values in the index attribute. + +countries.index = pd.Index(custom_index) +countries + +# ## MultiIndex +# +# A multi-level (MultiIndex) or hierarchical index allows you to specify multiple levels for indexing rows or columns. An "external" index combines several elements of an "internal" index. + +# + +# create a list of tuples with +# name of the continent and the country code +rows: list[tuple[str, str]] = [ + ("Asia", "CN"), + ("Asia", "VN"), + ("Europe", "GB"), + ("Europe", "RU"), + ("S. America", "AR"), + ("S. America", "BO"), + ("Africa", "ZA"), +] + +# In the columns, we will combine the names of +# countries and capitals into the category names. +# Population size, area, and access to +# the sea will be combined into the category data. +cols: list[tuple[str, str]] = [ + ("names", "country"), + ("names", "capital"), + ("data", "population"), + ("data", "area"), + ("data", "sea"), +] + +# Now let's create a hierarchical index for +# rows and columns using the pd.MultiIndex.from_tuples() function. +custom_multindex = pd.MultiIndex.from_tuples(rows, names=["region", "code"]) +# # Let's do the same for columns +custom_multicols = pd.MultiIndex.from_tuples(cols) + +# Finally, we need to transfer these indexes to +# the index and columns attributes and display it +countries.index = pd.Index(custom_multindex) +countries.columns = custom_multicols + +countries + +# + +# Let's return to the usual index and column names. +custom_cols = ["country", "capital", "population", "area", "sea"] + +countries.index = pd.Index(custom_index) +countries.columns = custom_cols + +countries +# - + +# ## Conversion to other formats +# + +# A datetime frame can be converted to a dictionary using the .to_dict() method. + +print(countries.to_dict()) + +# Similarly, the .to_numpy() method converts data into a Numpy array. + +countries.to_numpy() + +# ``` +# countries.to_csv("countries.csv", index=False) +# ``` +# +# In addition, we can save the dataframe to a file (in Google Colab, it will appear in session storage). For example, this could be a file in .csv format, in which case we need to use the .to_csv() function. +# +# ![image.png](attachment:image.png) + +# The .to_list() method allows you to convert a Series object (a dataframe column) into a list. + +countries.country.tolist() + +# ## Creating Series +# ### Creating Series from `list()` type +# + +# A Series object can be created from a list. Let's take the following list with country names. + +# + +country_list: list[str] = [ + "China", + "South Africa", + "United Kingdom", + "Russia", + "Argentina", + "Vietnam", + "Australia", +] + +country_series = pd.Series(country_list, dtype=str) +country_series +# - + +# Please note that a numeric index was automatically created for the Series object. We can use it to access the elements of this object. + +country_series.iloc[0] + +# ## Доступ к строкам и столбцам +# ### Циклы в датафрейме +# + +for column in countries: + print(column) + +for index, row in countries.iterrows(): + print(index) + print(row) + print("...") + print(type(row)) + break + +for _, row in countries.iterrows(): + print(row["capital"] + " is the capital if " + row["country"]) + break + +# ## Доступ к столбцам +# + +countries["capital"] + +countries.capital + +type(countries.capital) + +countries[["capital"]] + +countries[["capital", "area"]] + +countries.filter(items=["capital", "population"]) + +# ## Доступ к строкам +# + +countries[1:5] + +# ## Методы .loc[] и .iloc[] +# ### Метод .loc[] +# + +countries.loc[["CN", "RU", "VN"], ["capital", "population", "area"]] + +countries.loc[:, ["capital", "population", "area"]] + +countries.loc[:, [False, False, False, False, True]] + +# ## Метод .get_loc() +# + +countries.index.get_loc("RU") + +countries.columns.get_loc("country") + +# ## Метод .iloc[] +# + +countries.iloc[[0, 3, 5], [0, 1, 2]] + +countries.iloc[:3, -2:] + +countries[["population", "area"]].iloc[[0, 3]] + +# ### Creating Series from `dict` type + +country_dict: dict[str, str] = { + "CN": "China", + "ZA": "South Africa", + "GB": "United Kingdom", + "RU": "Russia", + "AR": "Argentina", + "VN": "Vietnam", + "AU": "Australia", +} + +# Let's convert dict to `pd.Series()` + +country_series_2 = pd.Series(country_dict) +country_series_2 + +# ## Access via multilevel index + +# Assign the hierarchical index `custom_multindex` to the DataFrame `countries` +countries.index = pd.Index(custom_multindex) +# Assign the hierarchical columns `custom_multicols` to the DataFrame `countries` +countries.columns = custom_multicols +# Display the DataFrame `countries` so its contents are shown in the notebook output +countries + +# ## Method .at[] +# +# The .at[] method is suitable for retrieving or writing a single data frame value. +# + +countries.at["CN", "capital"] + +# ## Filters +# ### Logical mask +# + +# As with the Numpy array, we can create a Boolean mask for the dataframe, in which unwanted values will be marked as False. + +countries.population > 1000 + +# By applying this mask to the original data frame, we will obtain only those values that are marked as True. + +countries[countries.population > 1000] + +# We can apply two masks to the data frame, combined, for example, with the logical AND operator. + +countries[(countries.population > 50) & (countries.area < 2)] + +# Here is another syntax option. It is convenient to use if you have many conditions by which you want to filter the data frame. + +# + +# First, create the masks we need. +population_mask = countries.population > 70 +area_mask = countries.population < 50 +# then combine them according to +# the necessary conditions (in this case OR) +mask = population_mask | area_mask + +# and apply the mask to the original data frame +countries[mask] +# - + +# ## Method .query() +# + +# The .query() method allows you to specify a filtering condition "in your own words." + +# + +# For example, let's select countries with a population +# more than 50 million people and an area +# less than two million square kilometers. + +countries.query("population > 50 and area < 2") +# - + +# When filtering by string values (which are enclosed in quotation marks), you must use different quotation marks: double quotation marks for the .query() method and single quotation marks for string values, or vice versa. + +# let's display data for the United Kingdom +countries.query('country == "United Kingdom"') + +# ## Other filtering methods +# + +# Using the .isin() method, we can check for the presence of multiple values in a specific column and then use the result as a logical mask. + +# + +keyword_list = ["Beijing", "Moscow", "Hanoi"] + +print(countries[countries.capital.isin(keyword_list)]) +# - + +# Similarly, you can use the .startswith() method. + +print(countries[~countries.country.str.startswith("A")]) + +# The .nlargest() method allows you to find the rows with the highest value in a specific column. + +countries.nlargest(3, "population") + +# The .argmax() method returns the index of the row containing the highest value in a specified column. + +countries.area.argmax() + +# Let's see which country corresponds to this index. + +largest_area_country = countries.iloc[[countries.area.argmax()]] +largest_area_country + +# Recall that the .loc[] method can accept Boolean data types. Let's use this property to create a filter. + +countries.loc[countries.population > 90, :] + +# The .filter() method, when using the like parameter, searches for matches with the desired phrase in the index (if axis = 0) or column names (if axis = 1). + +countries.filter(like="ZA", axis=0) + +# ## Sorting +# + +# sort by the population column without saving changes, +# in ascending order (default value) +countries.sort_values(by="population", inplace=False, ascending=True) + +# Now let's sort by two columns in descending order +countries.sort_values(by=["area", "population"], inplace=False, ascending=False) + +# In addition, you can sort rows by index using the .sort_index() method. + +countries.sort_index() diff --git a/python/makarov/chapter_15_iterators.ipynb b/python/makarov/chapter_15_iterators.ipynb new file mode 100644 index 00000000..defaac6c --- /dev/null +++ b/python/makarov/chapter_15_iterators.ipynb @@ -0,0 +1,723 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "58f7ecce", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Iterators and generators.\"\"\"\n", + "from itertools import chain, count, cycle\n", + "\n", + "# pylint: disable=invalid-name" + ] + }, + { + "cell_type": "markdown", + "id": "57f18b54", + "metadata": {}, + "source": [ + "## Итерируемый объект и итератор\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6f6766b9", + "metadata": {}, + "outputs": [], + "source": [ + "for value_1 in [1, 2, 3]:\n", + " print(value_1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09964b64", + "metadata": {}, + "outputs": [], + "source": [ + "temp_iterator = iter([1, 2, 3])\n", + "print(temp_iterator)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf8dcf10", + "metadata": {}, + "outputs": [], + "source": [ + "iterable_object: list[int] = [1, 2, 3]\n", + "\n", + "list_iterator = iter(iterable_object)\n", + "print(list_iterator)\n", + "print()\n", + "\n", + "print(next(list_iterator))\n", + "print(next(list_iterator))\n", + "print(next(list_iterator))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c5735da", + "metadata": {}, + "outputs": [], + "source": [ + "for element in iterable_object:\n", + " print(element)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bf07293", + "metadata": {}, + "outputs": [], + "source": [ + "iterable_numbers: list[int] = [1, 2, 3]\n", + "\n", + "iterator_a = iter(iterable_numbers)\n", + "iterator_b = iter(iterable_numbers)\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": null, + "id": "08ce2066", + "metadata": {}, + "outputs": [], + "source": [ + "print(iterable_numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f9ecce69", + "metadata": {}, + "outputs": [], + "source": [ + "iterator_a_list: list[int] = list(iterator_a)\n", + "iterator_b_list: list[int] = list(iterator_b)\n", + "print(iterator_a_list, iterator_b_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3836617", + "metadata": {}, + "outputs": [], + "source": [ + "for number_value in [1, 1, 2, 3]:\n", + " print(number_value)" + ] + }, + { + "cell_type": "markdown", + "id": "6ca38c0a", + "metadata": {}, + "source": [ + "## Отсутствие \"обратного хода\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb16d415", + "metadata": {}, + "outputs": [], + "source": [ + "iterator_c = iter(iterable_numbers)\n", + "\n", + "for first_item in iterator_c:\n", + " print(first_item)\n", + " break\n", + "\n", + "for remaining_item in iterator_c:\n", + " print(remaining_item)" + ] + }, + { + "cell_type": "markdown", + "id": "d9142478", + "metadata": {}, + "source": [ + "## Функция zip()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f445d9ad", + "metadata": {}, + "outputs": [], + "source": [ + "zipped_pairs = zip(iterable_numbers, iterable_numbers)\n", + "print(zipped_pairs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5761f5df", + "metadata": {}, + "outputs": [], + "source": [ + "iterator_tuple = zip(iterable_numbers, iterable_numbers)\n", + "\n", + "print(next(iterator_tuple))\n", + "print(next(iterator_tuple))\n", + "print(next(iterator_tuple))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e3a9fb4", + "metadata": {}, + "outputs": [], + "source": [ + "for pair in zip(iterable_numbers, iterable_numbers):\n", + " print(pair)" + ] + }, + { + "cell_type": "markdown", + "id": "3da8f42d", + "metadata": {}, + "source": [ + "## Примеры итераторов\n", + "### Возведение в квадрат\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46d25ccc", + "metadata": {}, + "outputs": [], + "source": [ + "class Square:\n", + " \"\"\"Iterator returning squared values from a sequence.\"\"\"\n", + "\n", + " def __init__(self, seq: list[int] | tuple[int, ...]) -> None:\n", + " \"\"\"Initialize iterator with sequence.\"\"\"\n", + " self._seq = seq\n", + " self._idx = 0\n", + "\n", + " def __iter__(self): # type: ignore[no-untyped-def]\n", + " \"\"\"Return self as iterator.\"\"\"\n", + " return self\n", + "\n", + " def __next__(self) -> int:\n", + " \"\"\"Return next squared value or raise StopIteration.\"\"\"\n", + " if self._idx >= len(self._seq):\n", + " raise StopIteration\n", + " square_result: int = self._seq[self._idx] ** 2\n", + " self._idx += 1\n", + " return square_result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "82565b86", + "metadata": {}, + "outputs": [], + "source": [ + "square_iterator: Square = Square([1, 2, 3, 4, 5])\n", + "print(square_iterator)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46643a50", + "metadata": {}, + "outputs": [], + "source": [ + "for square_value in square_iterator:\n", + " print(square_value)" + ] + }, + { + "cell_type": "markdown", + "id": "3fb22da3", + "metadata": {}, + "source": [ + "## Счетчик\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b4922c6", + "metadata": {}, + "outputs": [], + "source": [ + "class Counter:\n", + " \"\"\"Simple iterator that counts from start up to stop (exclusive).\"\"\"\n", + "\n", + " def __init__(self, start: int = 3, stop: int = 9) -> None:\n", + " \"\"\"Initialize with bounds.\"\"\"\n", + " self._current = start - 1\n", + " self._stop = stop\n", + "\n", + " def __iter__(self): # type: ignore[no-untyped-def]\n", + " \"\"\"Return self as iterator.\"\"\"\n", + " return self\n", + "\n", + " def __next__(self) -> int:\n", + " \"\"\"Return next number or raise StopIteration.\"\"\"\n", + " self._current += 1\n", + " if self._current >= self._stop:\n", + " raise StopIteration\n", + " return self._current" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ccb2999", + "metadata": {}, + "outputs": [], + "source": [ + "counter_instance: Counter = Counter()\n", + "print(counter_instance)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "770265e3", + "metadata": {}, + "outputs": [], + "source": [ + "print(next(counter_instance))\n", + "print(next(counter_instance))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee306597", + "metadata": {}, + "outputs": [], + "source": [ + "for count_value in counter_instance:\n", + " print(count_value)" + ] + }, + { + "cell_type": "markdown", + "id": "01bab639", + "metadata": {}, + "source": [ + "## Класс Iterator модуля collections.abc\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1975251", + "metadata": {}, + "outputs": [], + "source": [ + "class Counter2:\n", + " \"\"\"Iterator implementing the Iterator protocol explicitly.\"\"\"\n", + "\n", + " def __init__(self, start: int = 3, stop: int = 9) -> None:\n", + " \"\"\"Initialize with bounds.\"\"\"\n", + " self._current = start - 1\n", + " self._stop = stop\n", + "\n", + " def __iter__(self): # type: ignore[no-untyped-def]\n", + " \"\"\"Return self as iterator.\"\"\"\n", + " return self\n", + "\n", + " def __next__(self) -> int:\n", + " \"\"\"Return next number or raise StopIteration.\"\"\"\n", + " self._current += 1\n", + " if self._current >= self._stop:\n", + " raise StopIteration\n", + " return self._current" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52b01a80", + "metadata": {}, + "outputs": [], + "source": [ + "for count_value in Counter2():\n", + " print(count_value)" + ] + }, + { + "cell_type": "markdown", + "id": "237d708c", + "metadata": {}, + "source": [ + "## Бесконечный итератор\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "620a3c8b", + "metadata": {}, + "outputs": [], + "source": [ + "class FibIterator:\n", + " \"\"\"Iterator producing Fibonacci numbers.\"\"\"\n", + "\n", + " def __init__(self) -> None:\n", + " \"\"\"Initialize starting values.\"\"\"\n", + " self._idx = 0\n", + " self._current = 0\n", + " self._next = 1\n", + "\n", + " def __iter__(self): # type: ignore[no-untyped-def]\n", + " \"\"\"Return self as iterator.\"\"\"\n", + " return self\n", + "\n", + " def __next__(self) -> int:\n", + " \"\"\"Return next Fibonacci number.\"\"\"\n", + " if self._idx < 0:\n", + " raise StopIteration\n", + " self._idx += 1\n", + " self._current, self._next = (self._next, self._current + self._next)\n", + " return self._current" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79860182", + "metadata": {}, + "outputs": [], + "source": [ + "fib_limit: int = 10\n", + "\n", + "for fib_value in FibIterator():\n", + " print(fib_value)\n", + " fib_limit -= 1\n", + " if fib_limit == 0:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "fdb84369", + "metadata": {}, + "source": [ + "## Генератор\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4d0c329", + "metadata": {}, + "outputs": [], + "source": [ + "def sequence(count_limit: int) -> list[int]:\n", + " \"\"\"Return list of integers from 1 to n inclusive.\"\"\"\n", + " res: list[int] = [x for x in range(1, count_limit + 1)]\n", + " return res\n", + "\n", + "\n", + "sequence(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37f2fd0d", + "metadata": {}, + "outputs": [], + "source": [ + "def sequence_gen(count_limit: int): # type: ignore[no-untyped-def]\n", + " \"\"\"Yield integers from 1 to n inclusive.\"\"\"\n", + " yield from range(1, count_limit + 1)\n", + "\n", + "\n", + "sequence_gen(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9e44491", + "metadata": {}, + "outputs": [], + "source": [ + "seq_5 = sequence_gen(5)\n", + "\n", + "print(next(seq_5))\n", + "print(next(seq_5))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48001c18", + "metadata": {}, + "outputs": [], + "source": [ + "for number in seq_5:\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "id": "f6a55569", + "metadata": {}, + "source": [ + "## Generator comprehension\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91fa49cc", + "metadata": {}, + "outputs": [], + "source": [ + "gen_expr = (x for x in range(1, 5 + 1))\n", + "print(gen_expr)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f3f0878", + "metadata": {}, + "outputs": [], + "source": [ + "gen_expr_list: list[int] = list(x for x in range(1, 5 + 1))\n", + "print(gen_expr_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ec456aa3", + "metadata": {}, + "outputs": [], + "source": [ + "sum_gen: int = sum(x for x in range(1, 5 + 1))\n", + "print(sum_gen)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9efb9190", + "metadata": {}, + "outputs": [], + "source": [ + "contains_value: bool = 5 in (x for x in range(1, 5 + 1))\n", + "print(contains_value)" + ] + }, + { + "cell_type": "markdown", + "id": "8da60232", + "metadata": {}, + "source": [ + "## Модуль itertools\n" + ] + }, + { + "cell_type": "markdown", + "id": "28a2d3a5", + "metadata": {}, + "source": [ + "## Функция count()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7235a24c", + "metadata": {}, + "outputs": [], + "source": [ + "natural_numbers = count(start=1, step=0.5)\n", + "\n", + "for num in natural_numbers:\n", + " print(num)\n", + " if num == 2:\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f89a03d7", + "metadata": {}, + "outputs": [], + "source": [ + "list_let: list[str] = [\"a\", \"b\", \"c\", \"d\"]\n", + "for enumerated_letter in zip(count(start=1), list_let):\n", + " print(enumerated_letter)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b4d12c9", + "metadata": {}, + "outputs": [], + "source": [ + "def quadratic(value: int | float) -> float:\n", + " \"\"\"Return quadratic expression result.\"\"\"\n", + " return value**2 + value - 2\n", + "\n", + "\n", + "f_x = map(quadratic, count())\n", + "print(next(f_x), next(f_x), next(f_x))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b321bf7", + "metadata": {}, + "outputs": [], + "source": [ + "for mapped_value in f_x:\n", + " print(mapped_value)\n", + " if mapped_value > 10:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "99f73ccc", + "metadata": {}, + "source": [ + "??????? ???????? ? ???????????? ?? ???????.\n" + ] + }, + { + "cell_type": "markdown", + "id": "a16f632d", + "metadata": {}, + "source": [ + "???? ?? ?????? ? ?????????????? cycle (?????? ????).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c92c7d9", + "metadata": {}, + "outputs": [], + "source": [ + "cycle_numbers: list[int] = [1, 2, 3]\n", + "cycle_iterator_numbers = cycle(cycle_numbers)\n", + "\n", + "cycle_nums_limit: int = 5\n", + "for number in cycle_iterator_numbers:\n", + " print(number)\n", + " cycle_nums_limit -= 1\n", + " if cycle_nums_limit == 0:\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54f9b097", + "metadata": {}, + "outputs": [], + "source": [ + "string_value: str = \"Python\"\n", + "cycle_iterator_chars = cycle(string_value)\n", + "\n", + "cycle_chars_limit: int = 10\n", + "for char in cycle_iterator_chars:\n", + " print(char)\n", + " cycle_chars_limit -= 1\n", + " if cycle_chars_limit == 0:\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6b540fd", + "metadata": {}, + "outputs": [], + "source": [ + "chain_iterator = chain([\"abc\", \"d\", \"e\", \"f\"], \"abc\", [1, 2, 3])\n", + "print(chain_iterator)" + ] + }, + { + "cell_type": "markdown", + "id": "eb6d9465", + "metadata": {}, + "source": [ + "????????? ???????? ????????? chain ???????.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "696ce36d", + "metadata": {}, + "outputs": [], + "source": [ + "flatten_letters: list[str] = list(chain.from_iterable([\"abc\", \"def\"]))\n", + "print(flatten_letters)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e05b7cbd", + "metadata": {}, + "outputs": [], + "source": [ + "sum_numbers: int = sum(chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))\n", + "print(sum_numbers)" + ] + } + ], + "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.14.1" + } + }, + "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..b50cb4c4 --- /dev/null +++ b/python/makarov/chapter_15_iterators.py @@ -0,0 +1,339 @@ +# + +"""Iterators and generators.""" +from itertools import chain, count, cycle + +# pylint: disable=invalid-name +# - + +# ## Итерируемый объект и итератор +# + +for value_1 in [1, 2, 3]: + print(value_1) + +temp_iterator = iter([1, 2, 3]) +print(temp_iterator) + +# + +iterable_object: list[int] = [1, 2, 3] + +list_iterator = iter(iterable_object) +print(list_iterator) +print() + +print(next(list_iterator)) +print(next(list_iterator)) +print(next(list_iterator)) +# - + +for element in iterable_object: + print(element) + +# + +iterable_numbers: list[int] = [1, 2, 3] + +iterator_a = iter(iterable_numbers) +iterator_b = iter(iterable_numbers) + +print(f"A: {next(iterator_a)}") +print(f"A: {next(iterator_a)}") +print(f"A: {next(iterator_a)}") +print(f"B: {next(iterator_b)}") +# - + +print(iterable_numbers) + +iterator_a_list: list[int] = list(iterator_a) +iterator_b_list: list[int] = list(iterator_b) +print(iterator_a_list, iterator_b_list) + +for number_value in [1, 1, 2, 3]: + print(number_value) + +# ## Отсутствие "обратного хода" +# + +# + +iterator_c = iter(iterable_numbers) + +for first_item in iterator_c: + print(first_item) + break + +for remaining_item in iterator_c: + print(remaining_item) +# - + +# ## Функция zip() +# + +zipped_pairs = zip(iterable_numbers, iterable_numbers) +print(zipped_pairs) + +# + +iterator_tuple = zip(iterable_numbers, iterable_numbers) + +print(next(iterator_tuple)) +print(next(iterator_tuple)) +print(next(iterator_tuple)) +# - + +for pair in zip(iterable_numbers, iterable_numbers): + print(pair) + + +# ## Примеры итераторов +# ### Возведение в квадрат +# + + +class Square: + """Iterator returning squared values from a sequence.""" + + def __init__(self, seq: list[int] | tuple[int, ...]) -> None: + """Initialize iterator with sequence.""" + self._seq = seq + self._idx = 0 + + def __iter__(self): # type: ignore[no-untyped-def] + """Return self as iterator.""" + return self + + def __next__(self) -> int: + """Return next squared value or raise StopIteration.""" + if self._idx >= len(self._seq): + raise StopIteration + square_result: int = self._seq[self._idx] ** 2 + self._idx += 1 + return square_result + + +square_iterator: Square = Square([1, 2, 3, 4, 5]) +print(square_iterator) + +for square_value in square_iterator: + print(square_value) + + +# ## Счетчик +# + + +class Counter: + """Simple iterator that counts from start up to stop (exclusive).""" + + def __init__(self, start: int = 3, stop: int = 9) -> None: + """Initialize with bounds.""" + self._current = start - 1 + self._stop = stop + + def __iter__(self): # type: ignore[no-untyped-def] + """Return self as iterator.""" + return self + + def __next__(self) -> int: + """Return next number or raise StopIteration.""" + self._current += 1 + if self._current >= self._stop: + raise StopIteration + return self._current + + +counter_instance: Counter = Counter() +print(counter_instance) + +print(next(counter_instance)) +print(next(counter_instance)) + +for count_value in counter_instance: + print(count_value) + + +# ## Класс Iterator модуля collections.abc +# + + +class Counter2: + """Iterator implementing the Iterator protocol explicitly.""" + + def __init__(self, start: int = 3, stop: int = 9) -> None: + """Initialize with bounds.""" + self._current = start - 1 + self._stop = stop + + def __iter__(self): # type: ignore[no-untyped-def] + """Return self as iterator.""" + return self + + def __next__(self) -> int: + """Return next number or raise StopIteration.""" + self._current += 1 + if self._current >= self._stop: + raise StopIteration + return self._current + + +for count_value in Counter2(): + print(count_value) + + +# ## Бесконечный итератор +# + + +class FibIterator: + """Iterator producing Fibonacci numbers.""" + + def __init__(self) -> None: + """Initialize starting values.""" + self._idx = 0 + self._current = 0 + self._next = 1 + + def __iter__(self): # type: ignore[no-untyped-def] + """Return self as iterator.""" + return self + + def __next__(self) -> int: + """Return next Fibonacci number.""" + if self._idx < 0: + raise StopIteration + self._idx += 1 + self._current, self._next = (self._next, self._current + self._next) + return self._current + + +# + +fib_limit: int = 10 + +for fib_value in FibIterator(): + print(fib_value) + fib_limit -= 1 + if fib_limit == 0: + break + + +# - + +# ## Генератор +# + + +# + +def sequence(count_limit: int) -> list[int]: + """Return list of integers from 1 to n inclusive.""" + res: list[int] = [x for x in range(1, count_limit + 1)] + return res + + +sequence(5) + + +# + +def sequence_gen(count_limit: int): # type: ignore[no-untyped-def] + """Yield integers from 1 to n inclusive.""" + yield from range(1, count_limit + 1) + + +sequence_gen(5) + +# + +seq_5 = sequence_gen(5) + +print(next(seq_5)) +print(next(seq_5)) +# - + +for number in seq_5: + print(number) + +# ## Generator comprehension +# + +gen_expr = (x for x in range(1, 5 + 1)) +print(gen_expr) + +gen_expr_list: list[int] = list(x for x in range(1, 5 + 1)) +print(gen_expr_list) + +sum_gen: int = sum(x for x in range(1, 5 + 1)) +print(sum_gen) + +contains_value: bool = 5 in (x for x in range(1, 5 + 1)) +print(contains_value) + +# ## Модуль itertools +# + +# ## Функция count() +# + +# + +natural_numbers = count(start=1, step=0.5) + +for num in natural_numbers: + print(num) + if num == 2: + break +# - + +list_let: list[str] = ["a", "b", "c", "d"] +for enumerated_letter in zip(count(start=1), list_let): + print(enumerated_letter) + + +# + +def quadratic(value: int | float) -> float: + """Return quadratic expression result.""" + return value**2 + value - 2 + + +f_x = map(quadratic, count()) +print(next(f_x), next(f_x), next(f_x)) +# - + +for mapped_value in f_x: + print(mapped_value) + if mapped_value > 10: + break + +# ??????? ???????? ? ???????????? ?? ???????. +# + +# ???? ?? ?????? ? ?????????????? cycle (?????? ????). +# + +# + +cycle_numbers: list[int] = [1, 2, 3] +cycle_iterator_numbers = cycle(cycle_numbers) + +cycle_nums_limit: int = 5 +for number in cycle_iterator_numbers: + print(number) + cycle_nums_limit -= 1 + if cycle_nums_limit == 0: + break + +# + +string_value: str = "Python" +cycle_iterator_chars = cycle(string_value) + +cycle_chars_limit: int = 10 +for char in cycle_iterator_chars: + print(char) + cycle_chars_limit -= 1 + if cycle_chars_limit == 0: + break +# - + +chain_iterator = chain(["abc", "d", "e", "f"], "abc", [1, 2, 3]) +print(chain_iterator) + +# ????????? ???????? ????????? chain ???????. +# + +flatten_letters: list[str] = list(chain.from_iterable(["abc", "def"])) +print(flatten_letters) + +sum_numbers: int = sum(chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) +print(sum_numbers) diff --git a/python/makarov/chapter_16_decorators.ipynb b/python/makarov/chapter_16_decorators.ipynb new file mode 100644 index 00000000..a8f423ba --- /dev/null +++ b/python/makarov/chapter_16_decorators.ipynb @@ -0,0 +1,1285 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "28839556", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Decorators.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ec50d3e", + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import annotations\n", + "\n", + "import functools\n", + "import time\n", + "from collections.abc import Callable\n", + "from typing import ParamSpec, Protocol, TypeVar\n", + "\n", + "Params = ParamSpec(\"Params\")\n", + "Arguments = TypeVar(\"Arguments\")\n", + "T = TypeVar(\"T\")" + ] + }, + { + "cell_type": "markdown", + "id": "1e12dbbb", + "metadata": {}, + "source": [ + "## Декораторы\n", + "### Объекты первого класса\n", + "#### Присвоение функции переменной" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0214f716", + "metadata": {}, + "outputs": [], + "source": [ + "def say_hello_basic(name: str) -> None:\n", + " \"\"\"Print greeting with provided name.\"\"\"\n", + " print(f\"Hello, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20a6b837", + "metadata": {}, + "outputs": [], + "source": [ + "say_hello_function = say_hello_basic\n", + "say_hello_function(\"Alexey\")" + ] + }, + { + "cell_type": "markdown", + "id": "06728021", + "metadata": {}, + "source": [ + "## Передача функции в качестве аргумента другой функции\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a8444af7", + "metadata": {}, + "outputs": [], + "source": [ + "def simple_calculator(\n", + " operation: Callable[[float, float], float],\n", + " first_number: float,\n", + " second_number: float,\n", + ") -> float:\n", + " \"\"\"Calculate result using provided binary operation.\"\"\"\n", + " return operation(first_number, second_number)\n", + "\n", + "\n", + "def add(first_number: float, second_number: float) -> float:\n", + " \"\"\"Return sum of numbers.\"\"\"\n", + " return first_number + second_number\n", + "\n", + "\n", + "def subtract(first_number: float, second_number: float) -> float:\n", + " \"\"\"Return difference of numbers.\"\"\"\n", + " return first_number - second_number\n", + "\n", + "\n", + "def multiply(first_number: float, second_number: float) -> float:\n", + " \"\"\"Return product of numbers.\"\"\"\n", + " return first_number * second_number\n", + "\n", + "\n", + "def divide(first_number: float, second_number: float) -> float:\n", + " \"\"\"Return division result of numbers.\"\"\"\n", + " return first_number / second_number" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1722c926", + "metadata": {}, + "outputs": [], + "source": [ + "print(simple_calculator(divide, 33, 3))" + ] + }, + { + "cell_type": "markdown", + "id": "02e19d58", + "metadata": {}, + "source": [ + "## Внутренние функции\n", + "### Вызов внутренней функции\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e133dbf1", + "metadata": {}, + "outputs": [], + "source": [ + "def outer() -> None:\n", + " \"\"\"Print messages from outer and inner functions.\"\"\"\n", + " print(\"out function call\")\n", + "\n", + " def inner() -> None:\n", + " \"\"\"Print inner function call message.\"\"\"\n", + " print(\"inner function call\")\n", + "\n", + " inner()\n", + "\n", + "\n", + "outer()" + ] + }, + { + "cell_type": "markdown", + "id": "9ae979bc", + "metadata": {}, + "source": [ + "## Возвращение функции из функции и замыкание\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edac3ce3", + "metadata": {}, + "outputs": [], + "source": [ + "class MultiplierCallable(Protocol):\n", + " \"\"\"Protocol defining callable multiplier function.\"\"\"\n", + "\n", + " def __call__(self, number: int) -> int:\n", + " \"\"\"Callable signature defining multiplier behavior.\"\"\"\n", + " raise NotImplementedError\n", + "\n", + "\n", + "def create_multiplier(factor: int) -> MultiplierCallable:\n", + " \"\"\"Create multiplier closure for demonstration purposes.\"\"\"\n", + "\n", + " def multiplier(number: int) -> int:\n", + " \"\"\"Multiply number by predefined factor.\"\"\"\n", + " return number * factor\n", + "\n", + " return multiplier\n", + "\n", + "\n", + "double_multiplier: MultiplierCallable = create_multiplier(factor=2)\n", + "triple_multiplier: MultiplierCallable = create_multiplier(factor=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce851649", + "metadata": {}, + "outputs": [], + "source": [ + "print(double_multiplier)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9d48b77", + "metadata": {}, + "outputs": [], + "source": [ + "print((double_multiplier(number=2), triple_multiplier(number=2)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca25e61c", + "metadata": {}, + "outputs": [], + "source": [ + "def create_multiplier_2(factor: int) -> Callable[[int], int]:\n", + " \"\"\"Create multiplier using a nested function for demonstration purposes.\"\"\"\n", + "\n", + " def multiplier(number: int) -> int:\n", + " \"\"\"Multiply number by predefined factor.\"\"\"\n", + " return factor * number\n", + "\n", + " return multiplier" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dbf2ed83", + "metadata": {}, + "outputs": [], + "source": [ + "triple_multiplier_v2 = create_multiplier_2(factor=3)\n", + "print(triple_multiplier_v2(2))" + ] + }, + { + "cell_type": "markdown", + "id": "c2d0ea41", + "metadata": {}, + "source": [ + "## Знакомство с декораторами\n", + "### Простой декоратор\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3fef06a6", + "metadata": {}, + "outputs": [], + "source": [ + "def simple_decorator(\n", + " func: Callable[Params, Arguments],\n", + ") -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function by adding text before and after execution.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call and print surrounding text.\"\"\"\n", + " print(\"Text before func().\")\n", + " result = func(*args, **kwargs)\n", + " print(\"Text after func().\")\n", + " return result\n", + "\n", + " return wrapper\n", + "\n", + "\n", + "def say_hello_decorated() -> None:\n", + " \"\"\"Print simple greeting.\"\"\"\n", + " print(\"Hello!\")\n", + "\n", + "\n", + "say_hello_decorated = simple_decorator(say_hello_decorated)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8226560", + "metadata": {}, + "outputs": [], + "source": [ + "say_hello_decorated()" + ] + }, + { + "cell_type": "markdown", + "id": "fe7fa7bd", + "metadata": {}, + "source": [ + "## Конструкция @decorator\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f61132fa", + "metadata": {}, + "outputs": [], + "source": [ + "@simple_decorator\n", + "def say_hi() -> None:\n", + " \"\"\"Print repeated greeting.\"\"\"\n", + " print(\"Hello, again...\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31e80f06", + "metadata": {}, + "outputs": [], + "source": [ + "say_hi()" + ] + }, + { + "cell_type": "markdown", + "id": "80824ed5", + "metadata": {}, + "source": [ + "## Функции с аргументами\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "920f91e6", + "metadata": {}, + "outputs": [], + "source": [ + "@simple_decorator\n", + "def say_hello_with_name_simple(name: str) -> None:\n", + " \"\"\"Print greeting with provided name.\"\"\"\n", + " print(f\"Hello, {name}!\")\n", + "\n", + "\n", + "say_hello_with_name_simple(\"Alex\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79183218", + "metadata": {}, + "outputs": [], + "source": [ + "def decorator_with_name_argument(func: Callable[[str], None]) -> Callable[[str], None]:\n", + " \"\"\"Decorate function expecting a single name argument.\"\"\"\n", + "\n", + " def wrapper(name: str) -> None:\n", + " \"\"\"Wrap function call and print surrounding text.\"\"\"\n", + " print(\"Text before func().\")\n", + " func(name)\n", + " print(\"Text after func().\")\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "817a2b89", + "metadata": {}, + "outputs": [], + "source": [ + "@decorator_with_name_argument\n", + "def say_hello_with_name_logged(name: str) -> None:\n", + " \"\"\"Print greeting with provided name.\"\"\"\n", + " print(f\"Hello, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03031dcd", + "metadata": {}, + "outputs": [], + "source": [ + "say_hello_with_name_logged(\"Alex\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a401d87", + "metadata": {}, + "outputs": [], + "source": [ + "def decorator_with_arguments(\n", + " func: Callable[Params, Arguments],\n", + ") -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function printing text before and after call.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call and print surrounding text.\"\"\"\n", + " print(\"Text before func().\")\n", + " result = func(*args, **kwargs)\n", + " print(\"Text after func().\")\n", + " return result\n", + "\n", + " return wrapper\n", + "\n", + "\n", + "@decorator_with_arguments\n", + "def say_hello_with_argument(name: str) -> None:\n", + " \"\"\"Print greeting with provided name.\"\"\"\n", + " print(f\"Hello, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "748e1665", + "metadata": {}, + "outputs": [], + "source": [ + "say_hello_with_argument(\"Alex\")" + ] + }, + { + "cell_type": "markdown", + "id": "88a0fc1c", + "metadata": {}, + "source": [ + "## Возвращение значения декорируемой функции\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2e0a712", + "metadata": {}, + "outputs": [], + "source": [ + "def another_decorator(func: Callable[[str], str]) -> Callable[[str], None]:\n", + " \"\"\"Decorate function by printing text before call.\"\"\"\n", + "\n", + " def wrapper(name: str) -> None:\n", + " \"\"\"Wrap function call and print inner text.\"\"\"\n", + " print(\"Inner function text\")\n", + " func(name)\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4185f61", + "metadata": {}, + "outputs": [], + "source": [ + "@another_decorator\n", + "def return_name_silent(name: str) -> str:\n", + " \"\"\"Return provided name.\"\"\"\n", + " return name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00d46a93", + "metadata": {}, + "outputs": [], + "source": [ + "returned_value: str | None = return_name_silent(\"Alex\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b0062fb", + "metadata": {}, + "outputs": [], + "source": [ + "print(returned_value)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "990a7275", + "metadata": {}, + "outputs": [], + "source": [ + "def another_decorator_verbose(\n", + " func: Callable[[str], Arguments],\n", + ") -> Callable[[str], Arguments]:\n", + " \"\"\"Decorate function by printing text and returning result.\"\"\"\n", + "\n", + " def wrapper(name: str) -> Arguments:\n", + " \"\"\"Wrap function call, print text, and return result.\"\"\"\n", + " print(\"����� ���������� �������.\")\n", + " return func(name)\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8556b18d", + "metadata": {}, + "outputs": [], + "source": [ + "@another_decorator_verbose\n", + "def return_name_verbose(name: str) -> str:\n", + " \"\"\"Return provided name.\"\"\"\n", + " return name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "091e8e3d", + "metadata": {}, + "outputs": [], + "source": [ + "returned_value_verbose: str = return_name_verbose(\"Alex\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4bbefa5", + "metadata": {}, + "outputs": [], + "source": [ + "print(returned_value_verbose)" + ] + }, + { + "cell_type": "markdown", + "id": "381ce1b7", + "metadata": {}, + "source": [ + "## Декоратор @functools.wraps\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a352897", + "metadata": {}, + "outputs": [], + "source": [ + "def square_basic(value: int) -> int:\n", + " \"\"\"Return square of the given number.\"\"\"\n", + " return value * value" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71e9fb56", + "metadata": {}, + "outputs": [], + "source": [ + "print((square_basic.__name__, square_basic.__doc__))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1992ae6", + "metadata": {}, + "outputs": [], + "source": [ + "def repeat_twice(\n", + " func: Callable[Params, Arguments],\n", + ") -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function to run twice.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " result = func(*args, **kwargs)\n", + " return result\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8db5d417", + "metadata": {}, + "outputs": [], + "source": [ + "@repeat_twice\n", + "def square_repeated(value: int) -> int:\n", + " \"\"\"Return square of the given number.\"\"\"\n", + " return value * value" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f389b3d9", + "metadata": {}, + "outputs": [], + "source": [ + "square_repeated(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "192e3d0c", + "metadata": {}, + "outputs": [], + "source": [ + "print((square_repeated.__name__, square_repeated.__doc__))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6edfefd", + "metadata": {}, + "outputs": [], + "source": [ + "def repeat_twice_with_wraps(\n", + " func: Callable[Params, Arguments],\n", + ") -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function by repeating execution twice with wraps.\"\"\"\n", + "\n", + " @functools.wraps(func)\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call, execute twice, and return result.\"\"\"\n", + " func(*args, **kwargs)\n", + " return func(*args, **kwargs)\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c98e8e98", + "metadata": {}, + "outputs": [], + "source": [ + "@repeat_twice_with_wraps\n", + "def square_wrapped(value: int) -> None:\n", + " \"\"\"Return square of the given number.\"\"\"\n", + " print(value * value)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ac9eb47", + "metadata": {}, + "outputs": [], + "source": [ + "print((square_wrapped.__name__, square_wrapped.__doc__))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "834bb144", + "metadata": {}, + "outputs": [], + "source": [ + "print(getattr(square_wrapped, \"__wrapped__\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d64a9c28", + "metadata": {}, + "outputs": [], + "source": [ + "def repeat_twice_updated(\n", + " func: Callable[Params, Arguments],\n", + ") -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function by repeating execution twice and preserving metadata.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call, execute twice, and return result.\"\"\"\n", + " func(*args, **kwargs)\n", + " return func(*args, **kwargs)\n", + "\n", + " functools.update_wrapper(wrapper, func)\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bba41989", + "metadata": {}, + "outputs": [], + "source": [ + "@repeat_twice_updated\n", + "def power_repeated(base_value: float, exponent: float) -> int | float:\n", + " \"\"\"Return base raised to exponent.\"\"\"\n", + " result: int | float = base_value**exponent\n", + " return result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20a0ea56", + "metadata": {}, + "outputs": [], + "source": [ + "power_repeated(2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8e90370", + "metadata": {}, + "outputs": [], + "source": [ + "print(power_repeated.__doc__)" + ] + }, + { + "cell_type": "markdown", + "id": "258ce396", + "metadata": {}, + "source": [ + "## Примеры декораторов\n", + "### Создание логов\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ae8990f", + "metadata": {}, + "outputs": [], + "source": [ + "def logging(func: Callable[Params, Arguments]) -> Callable[Params, Arguments]:\n", + " \"\"\"Decorate function with logging.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call and log arguments and result.\"\"\"\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": null, + "id": "6328baf0", + "metadata": {}, + "outputs": [], + "source": [ + "@logging\n", + "def power_logged(base_value: int, exponent: int) -> int | float:\n", + " \"\"\"Return power of a number.\"\"\"\n", + " result: int | float = base_value**exponent\n", + " return result\n", + "\n", + "\n", + "power_logged(5, 3)" + ] + }, + { + "cell_type": "markdown", + "id": "c5a456fb", + "metadata": {}, + "source": [ + "## Время исполнения функции\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73d8eb90", + "metadata": {}, + "outputs": [], + "source": [ + "def timer(func: Callable[Params, Arguments]) -> Callable[Params, Arguments]:\n", + " \"\"\"Wrap function to measure execution time.\"\"\"\n", + "\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments:\n", + " \"\"\"Wrap function call, measure duration, and return result.\"\"\"\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} seconds\")\n", + " return result\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d99fe88a", + "metadata": {}, + "outputs": [], + "source": [ + "@timer\n", + "def delayed_function_timed(delay_time: float) -> str:\n", + " \"\"\"Delay execution for specified time.\"\"\"\n", + " time.sleep(delay_time)\n", + " return \"execution completed\"\n", + "\n", + "\n", + "delayed_function_timed(2)" + ] + }, + { + "cell_type": "markdown", + "id": "03c807f2", + "metadata": {}, + "source": [ + "## Типы методов\n", + "### Методы экземпляра\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7aa92785", + "metadata": {}, + "outputs": [], + "source": [ + "class CatClassBasic:\n", + " \"\"\"Represent basic cat data.\"\"\"\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color: str = color\n", + " self.type_: str = \"cat\"\n", + "\n", + " def info(self) -> None:\n", + " \"\"\"Print cat information.\"\"\"\n", + " print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2472f049", + "metadata": {}, + "outputs": [], + "source": [ + "cat_basic = CatClassBasic(color=\"black\")\n", + "cat_basic.info()" + ] + }, + { + "cell_type": "markdown", + "id": "d30c89c6", + "metadata": {}, + "source": [ + "## Методы класса\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b13c7d37", + "metadata": {}, + "outputs": [], + "source": [ + "class CatClassWithSpecies:\n", + " \"\"\"Represent cat data with species information.\"\"\"\n", + "\n", + " species: str = \"Cat\"\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color: str = color\n", + "\n", + " def info(self) -> None:\n", + " \"\"\"Print cat color.\"\"\"\n", + " print(self.color)\n", + "\n", + " @classmethod\n", + " def get_species(cls) -> None:\n", + " \"\"\"Print species name.\"\"\"\n", + " print(cls.species)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85c64955", + "metadata": {}, + "outputs": [], + "source": [ + "print(CatClassWithSpecies.species)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46690f45", + "metadata": {}, + "outputs": [], + "source": [ + "CatClassWithSpecies.get_species()" + ] + }, + { + "cell_type": "markdown", + "id": "c09a8edf", + "metadata": {}, + "source": [ + "## Статические методы\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8adf1cbc", + "metadata": {}, + "outputs": [], + "source": [ + "class CatClassWithConverter:\n", + " \"\"\"Represent cat data with conversion utility.\"\"\"\n", + "\n", + " species: str = \"Cat\"\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color: str = color\n", + "\n", + " def info(self) -> None:\n", + " \"\"\"Print cat color.\"\"\"\n", + " print(self.color)\n", + "\n", + " @classmethod\n", + " def get_species(cls) -> None:\n", + " \"\"\"Print species name.\"\"\"\n", + " print(cls.species)\n", + "\n", + " @staticmethod\n", + " def convert_to_pounds(weight_kg: float) -> None:\n", + " \"\"\"Convert kilograms to pounds and print result.\"\"\"\n", + " print(f\"{weight_kg} kg is approximately {weight_kg * 2.205} pounds\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1da5aa35", + "metadata": {}, + "outputs": [], + "source": [ + "CatClassWithConverter.convert_to_pounds(4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48e4eae4", + "metadata": {}, + "outputs": [], + "source": [ + "cat_with_converter = CatClassWithConverter(\"gray\")\n", + "cat_with_converter.convert_to_pounds(12)" + ] + }, + { + "cell_type": "markdown", + "id": "43cb14dd", + "metadata": {}, + "source": [ + "## Декорирование класса\n", + "### Декорирование методов\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd8d6001", + "metadata": {}, + "outputs": [], + "source": [ + "class CatClassDecorated:\n", + " \"\"\"Represent cat data with decorated methods.\"\"\"\n", + "\n", + " color: str\n", + " type_: str\n", + "\n", + " @logging\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color = color\n", + " self.type_ = \"cat\"\n", + "\n", + " @timer\n", + " def info(self) -> None:\n", + " \"\"\"Print cat information with delay.\"\"\"\n", + " time.sleep(2)\n", + " print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52fc21b1", + "metadata": {}, + "outputs": [], + "source": [ + "cat_decorated = CatClassDecorated(\"black\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f324709d", + "metadata": {}, + "outputs": [], + "source": [ + "cat_decorated.info()" + ] + }, + { + "cell_type": "markdown", + "id": "34406ca4", + "metadata": {}, + "source": [ + "## Декорирование всего класса\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9a8c99a", + "metadata": {}, + "outputs": [], + "source": [ + "@timer\n", + "class CatClassTimed:\n", + " \"\"\"Represent cat data with timed methods.\"\"\"\n", + "\n", + " weight: float | int | None = None\n", + " color: str\n", + " type_: str\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color = color\n", + " self.type_ = \"cat\"\n", + "\n", + " def info(self) -> None:\n", + " \"\"\"Print cat information with delay.\"\"\"\n", + " time.sleep(2)\n", + " print(self.color, self.type_, sep=\", \")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0e63abb", + "metadata": {}, + "outputs": [], + "source": [ + "cat_timed = CatClassTimed(\"grey\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2da29db8", + "metadata": {}, + "outputs": [], + "source": [ + "cat_timed.info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b781159", + "metadata": {}, + "outputs": [], + "source": [ + "setattr(cat_timed, \"weight\", 5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75083940", + "metadata": {}, + "outputs": [], + "source": [ + "print((cat_timed.weight, getattr(cat_timed, \"weight\")))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad42ce6d", + "metadata": {}, + "outputs": [], + "source": [ + "def add_attribute(\n", + " attribute_name: str, attribute_value: str\n", + ") -> Callable[[type[T]], type[T]]:\n", + " \"\"\"Decorate class by adding specified attribute.\"\"\"\n", + "\n", + " def wrapper(cls: type[T]) -> type[T]:\n", + " \"\"\"Attach attribute to class and return the class.\"\"\"\n", + " setattr(cls, attribute_name, attribute_value)\n", + " return cls\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37e55be4", + "metadata": {}, + "outputs": [], + "source": [ + "@add_attribute(\"species\", \"cat\")\n", + "class CatClassAttributed:\n", + " \"\"\"Represent cat data with added attributes.\"\"\"\n", + "\n", + " species: str = \"cat\"\n", + " color: str\n", + " type_: str\n", + "\n", + " def __init__(self, color: str) -> None:\n", + " \"\"\"Initialize instance attributes.\"\"\"\n", + " self.color = color\n", + " self.type_ = \"cat\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "072a2df0", + "metadata": {}, + "outputs": [], + "source": [ + "print(CatClassAttributed.species)" + ] + }, + { + "cell_type": "markdown", + "id": "93b21995", + "metadata": {}, + "source": [ + "## Несколько декораторов\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9176367", + "metadata": {}, + "outputs": [], + "source": [ + "@logging\n", + "@timer\n", + "def delayed_function_logged_timed(delay_time: float) -> str:\n", + " \"\"\"Delay execution with logging and timing.\"\"\"\n", + " time.sleep(delay_time)\n", + " return \"execution completed\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2f046ea9", + "metadata": {}, + "outputs": [], + "source": [ + "delayed_function_logged_timed(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67fbc7bf", + "metadata": {}, + "outputs": [], + "source": [ + "def delayed_function_plain(delay_time: float) -> str:\n", + " \"\"\"Delay execution for specified time.\"\"\"\n", + " time.sleep(delay_time)\n", + " return \"execution completed\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef1aa482", + "metadata": {}, + "outputs": [], + "source": [ + "delayed_function_wrapped = logging(timer(delayed_function_plain))\n", + "delayed_function_wrapped(2)" + ] + }, + { + "cell_type": "markdown", + "id": "6f358cd8", + "metadata": {}, + "source": [ + "## Декораторы с аргументами\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "390d0049", + "metadata": {}, + "outputs": [], + "source": [ + "def repeat(\n", + " repeat_count: int,\n", + ") -> Callable[[Callable[Params, None]], Callable[Params, None]]:\n", + " \"\"\"Create decorator repeating function calls.\"\"\"\n", + "\n", + " def inner_decorator(func: Callable[Params, None]) -> Callable[Params, None]:\n", + " \"\"\"Wrap function to repeat calls the specified number of times.\"\"\"\n", + "\n", + " @functools.wraps(func)\n", + " def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> None:\n", + " \"\"\"Wrap function call and repeat execution.\"\"\"\n", + " for _ in range(repeat_count):\n", + " func(*args, **kwargs)\n", + "\n", + " return wrapper\n", + "\n", + " return inner_decorator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ab2974aa", + "metadata": {}, + "outputs": [], + "source": [ + "@repeat(repeat_count=3)\n", + "def say_hello_repeated(name: str) -> None:\n", + " \"\"\"Print greeting with provided name.\"\"\"\n", + " print(f\"Hello, {name}!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eea52157", + "metadata": {}, + "outputs": [], + "source": [ + "say_hello_repeated(\"Alex\")" + ] + } + ], + "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.14.1" + } + }, + "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..6f7df151 --- /dev/null +++ b/python/makarov/chapter_16_decorators.py @@ -0,0 +1,679 @@ +"""Decorators.""" + +# + +from __future__ import annotations + +import functools +import time +from collections.abc import Callable +from typing import ParamSpec, Protocol, TypeVar + +Params = ParamSpec("Params") +Arguments = TypeVar("Arguments") +T = TypeVar("T") + + +# - + +# ## Декораторы +# ### Объекты первого класса +# #### Присвоение функции переменной + + +def say_hello_basic(name: str) -> None: + """Print greeting with provided name.""" + print(f"Hello, {name}!") + + +say_hello_function = say_hello_basic +say_hello_function("Alexey") + + +# ## Передача функции в качестве аргумента другой функции +# + + +# + +def simple_calculator( + operation: Callable[[float, float], float], + first_number: float, + second_number: float, +) -> float: + """Calculate result using provided binary operation.""" + return operation(first_number, second_number) + + +def add(first_number: float, second_number: float) -> float: + """Return sum of numbers.""" + return first_number + second_number + + +def subtract(first_number: float, second_number: float) -> float: + """Return difference of numbers.""" + return first_number - second_number + + +def multiply(first_number: float, second_number: float) -> float: + """Return product of numbers.""" + return first_number * second_number + + +def divide(first_number: float, second_number: float) -> float: + """Return division result of numbers.""" + return first_number / second_number + + +# - + +print(simple_calculator(divide, 33, 3)) + + +# ## Внутренние функции +# ### Вызов внутренней функции +# +# + + +# + +def outer() -> None: + """Print messages from outer and inner functions.""" + print("out function call") + + def inner() -> None: + """Print inner function call message.""" + print("inner function call") + + inner() + + +outer() + + +# - + +# ## Возвращение функции из функции и замыкание +# + + +# + +class MultiplierCallable(Protocol): + """Protocol defining callable multiplier function.""" + + def __call__(self, number: int) -> int: + """Callable signature defining multiplier behavior.""" + raise NotImplementedError + + +def create_multiplier(factor: int) -> MultiplierCallable: + """Create multiplier closure for demonstration purposes.""" + + def multiplier(number: int) -> int: + """Multiply number by predefined factor.""" + return number * factor + + return multiplier + + +double_multiplier: MultiplierCallable = create_multiplier(factor=2) +triple_multiplier: MultiplierCallable = create_multiplier(factor=3) +# - + +print(double_multiplier) + +print((double_multiplier(number=2), triple_multiplier(number=2))) + + +def create_multiplier_2(factor: int) -> Callable[[int], int]: + """Create multiplier using a nested function for demonstration purposes.""" + + def multiplier(number: int) -> int: + """Multiply number by predefined factor.""" + return factor * number + + return multiplier + + +triple_multiplier_v2 = create_multiplier_2(factor=3) +print(triple_multiplier_v2(2)) + + +# ## Знакомство с декораторами +# ### Простой декоратор +# + + +# + +def simple_decorator( + func: Callable[Params, Arguments], +) -> Callable[Params, Arguments]: + """Decorate function by adding text before and after execution.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call and print surrounding text.""" + print("Text before func().") + result = func(*args, **kwargs) + print("Text after func().") + return result + + return wrapper + + +def say_hello_decorated() -> None: + """Print simple greeting.""" + print("Hello!") + + +say_hello_decorated = simple_decorator(say_hello_decorated) +# - + +say_hello_decorated() + + +# ## Конструкция @decorator +# + + +@simple_decorator +def say_hi() -> None: + """Print repeated greeting.""" + print("Hello, again...") + + +say_hi() + + +# ## Функции с аргументами +# + + +# + +@simple_decorator +def say_hello_with_name_simple(name: str) -> None: + """Print greeting with provided name.""" + print(f"Hello, {name}!") + + +say_hello_with_name_simple("Alex") + + +# - + + +def decorator_with_name_argument(func: Callable[[str], None]) -> Callable[[str], None]: + """Decorate function expecting a single name argument.""" + + def wrapper(name: str) -> None: + """Wrap function call and print surrounding text.""" + print("Text before func().") + func(name) + print("Text after func().") + + return wrapper + + +@decorator_with_name_argument +def say_hello_with_name_logged(name: str) -> None: + """Print greeting with provided name.""" + print(f"Hello, {name}!") + + +say_hello_with_name_logged("Alex") + + +# + +def decorator_with_arguments( + func: Callable[Params, Arguments], +) -> Callable[Params, Arguments]: + """Decorate function printing text before and after call.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call and print surrounding text.""" + print("Text before func().") + result = func(*args, **kwargs) + print("Text after func().") + return result + + return wrapper + + +@decorator_with_arguments +def say_hello_with_argument(name: str) -> None: + """Print greeting with provided name.""" + print(f"Hello, {name}!") + + +# - + +say_hello_with_argument("Alex") + + +# ## Возвращение значения декорируемой функции +# + + +def another_decorator(func: Callable[[str], str]) -> Callable[[str], None]: + """Decorate function by printing text before call.""" + + def wrapper(name: str) -> None: + """Wrap function call and print inner text.""" + print("Inner function text") + func(name) + + return wrapper + + +@another_decorator +def return_name_silent(name: str) -> str: + """Return provided name.""" + return name + + +returned_value: str | None = return_name_silent("Alex") + +print(returned_value) + + +def another_decorator_verbose( + func: Callable[[str], Arguments], +) -> Callable[[str], Arguments]: + """Decorate function by printing text and returning result.""" + + def wrapper(name: str) -> Arguments: + """Wrap function call, print text, and return result.""" + print("����� ���������� �������.") + return func(name) + + return wrapper + + +@another_decorator_verbose +def return_name_verbose(name: str) -> str: + """Return provided name.""" + return name + + +returned_value_verbose: str = return_name_verbose("Alex") + +print(returned_value_verbose) + + +# ## Декоратор @functools.wraps +# + + +def square_basic(value: int) -> int: + """Return square of the given number.""" + return value * value + + +print((square_basic.__name__, square_basic.__doc__)) + + +def repeat_twice( + func: Callable[Params, Arguments], +) -> Callable[Params, Arguments]: + """Decorate function to run twice.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + result = func(*args, **kwargs) + return result + + return wrapper + + +@repeat_twice +def square_repeated(value: int) -> int: + """Return square of the given number.""" + return value * value + + +square_repeated(3) + +print((square_repeated.__name__, square_repeated.__doc__)) + + +def repeat_twice_with_wraps( + func: Callable[Params, Arguments], +) -> Callable[Params, Arguments]: + """Decorate function by repeating execution twice with wraps.""" + + @functools.wraps(func) + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call, execute twice, and return result.""" + func(*args, **kwargs) + return func(*args, **kwargs) + + return wrapper + + +@repeat_twice_with_wraps +def square_wrapped(value: int) -> None: + """Return square of the given number.""" + print(value * value) + + +print((square_wrapped.__name__, square_wrapped.__doc__)) + +print(getattr(square_wrapped, "__wrapped__")) + + +def repeat_twice_updated( + func: Callable[Params, Arguments], +) -> Callable[Params, Arguments]: + """Decorate function by repeating execution twice and preserving + metadata.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call, execute twice, and return result.""" + func(*args, **kwargs) + return func(*args, **kwargs) + + functools.update_wrapper(wrapper, func) + return wrapper + + +@repeat_twice_updated +def power_repeated(base_value: float, exponent: float) -> int | float: + """Return base raised to exponent.""" + result: int | float = base_value**exponent + return result + + +power_repeated(2, 3) + +print(power_repeated.__doc__) + + +# ## Примеры декораторов +# ### Создание логов +# + + +def logging(func: Callable[Params, Arguments]) -> Callable[Params, Arguments]: + """Decorate function with logging.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call and log arguments and result.""" + 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_logged(base_value: int, exponent: int) -> int | float: + """Return power of a number.""" + result: int | float = base_value**exponent + return result + + +power_logged(5, 3) + + +# - + +# ## Время исполнения функции +# + + +def timer(func: Callable[Params, Arguments]) -> Callable[Params, Arguments]: + """Wrap function to measure execution time.""" + + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Arguments: + """Wrap function call, measure duration, and return result.""" + 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_timed(delay_time: float) -> str: + """Delay execution for specified time.""" + time.sleep(delay_time) + return "execution completed" + + +delayed_function_timed(2) + + +# - + +# ## Типы методов +# ### Методы экземпляра +# + + +class CatClassBasic: + """Represent basic cat data.""" + + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color: str = color + self.type_: str = "cat" + + def info(self) -> None: + """Print cat information.""" + print(self.color, self.type_, sep=", ") + + +cat_basic = CatClassBasic(color="black") +cat_basic.info() + + +# ## Методы класса +# + + +class CatClassWithSpecies: + """Represent cat data with species information.""" + + species: str = "Cat" + + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color: str = color + + def info(self) -> None: + """Print cat color.""" + print(self.color) + + @classmethod + def get_species(cls) -> None: + """Print species name.""" + print(cls.species) + + +print(CatClassWithSpecies.species) + +CatClassWithSpecies.get_species() + + +# ## Статические методы +# + + +class CatClassWithConverter: + """Represent cat data with conversion utility.""" + + species: str = "Cat" + + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color: str = color + + def info(self) -> None: + """Print cat color.""" + print(self.color) + + @classmethod + def get_species(cls) -> None: + """Print species name.""" + print(cls.species) + + @staticmethod + def convert_to_pounds(weight_kg: float) -> None: + """Convert kilograms to pounds and print result.""" + print(f"{weight_kg} kg is approximately {weight_kg * 2.205} pounds") + + +CatClassWithConverter.convert_to_pounds(4) + +cat_with_converter = CatClassWithConverter("gray") +cat_with_converter.convert_to_pounds(12) + + +# ## Декорирование класса +# ### Декорирование методов +# +# + + +class CatClassDecorated: + """Represent cat data with decorated methods.""" + + color: str + type_: str + + @logging + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color = color + self.type_ = "cat" + + @timer + def info(self) -> None: + """Print cat information with delay.""" + time.sleep(2) + print(self.color, self.type_, sep=", ") + + +cat_decorated = CatClassDecorated("black") + +cat_decorated.info() + + +# ## Декорирование всего класса +# + + +@timer +class CatClassTimed: + """Represent cat data with timed methods.""" + + weight: float | int | None = None + color: str + type_: str + + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color = color + self.type_ = "cat" + + def info(self) -> None: + """Print cat information with delay.""" + time.sleep(2) + print(self.color, self.type_, sep=", ") + + +cat_timed = CatClassTimed("grey") + +cat_timed.info() + +setattr(cat_timed, "weight", 5) + +print((cat_timed.weight, getattr(cat_timed, "weight"))) + + +def add_attribute( + attribute_name: str, attribute_value: str +) -> Callable[[type[T]], type[T]]: + """Decorate class by adding specified attribute.""" + + def wrapper(cls: type[T]) -> type[T]: + """Attach attribute to class and return the class.""" + setattr(cls, attribute_name, attribute_value) + return cls + + return wrapper + + +@add_attribute("species", "cat") +class CatClassAttributed: + """Represent cat data with added attributes.""" + + species: str = "cat" + color: str + type_: str + + def __init__(self, color: str) -> None: + """Initialize instance attributes.""" + self.color = color + self.type_ = "cat" + + +print(CatClassAttributed.species) + + +# ## Несколько декораторов +# + + +@logging +@timer +def delayed_function_logged_timed(delay_time: float) -> str: + """Delay execution with logging and timing.""" + time.sleep(delay_time) + return "execution completed" + + +delayed_function_logged_timed(2) + + +def delayed_function_plain(delay_time: float) -> str: + """Delay execution for specified time.""" + time.sleep(delay_time) + return "execution completed" + + +delayed_function_wrapped = logging(timer(delayed_function_plain)) +delayed_function_wrapped(2) + + +# ## Декораторы с аргументами +# + + +def repeat( + repeat_count: int, +) -> Callable[[Callable[Params, None]], Callable[Params, None]]: + """Create decorator repeating function calls.""" + + def inner_decorator(func: Callable[Params, None]) -> Callable[Params, None]: + """Wrap function to repeat calls the specified number of times.""" + + @functools.wraps(func) + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> None: + """Wrap function call and repeat execution.""" + for _ in range(repeat_count): + func(*args, **kwargs) + + return wrapper + + return inner_decorator + + +@repeat(repeat_count=3) +def say_hello_repeated(name: str) -> None: + """Print greeting with provided name.""" + print(f"Hello, {name}!") + + +say_hello_repeated("Alex") diff --git a/python/oop.ipynb b/python/oop.ipynb new file mode 100644 index 00000000..ce540adc --- /dev/null +++ b/python/oop.ipynb @@ -0,0 +1,1234 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "83ac6469", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Programming Paradigms and Object-Oriented Programming in Python.'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"Programming Paradigms and Object-Oriented Programming in Python.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "4315b765", + "metadata": {}, + "source": [ + "Here is a **clear, structured English conspect (summary + notes)** about OOP.\n", + "\n", + "---\n", + "\n", + "# **Conspect: Introduction to Object-Oriented Programming (OOP)**\n", + "\n", + "## **1. Programming Paradigms Overview**\n", + "\n", + "Programming paradigms are different ways of writing and organizing code. OOP is one of these approaches, but not the only one.\n", + "\n", + "### **Main paradigms:**\n", + "\n", + "1. **Procedural Programming**\n", + "\n", + " * Code is written as a sequence of instructions, executed line by line.\n", + " * Easy to start with, but becomes difficult to maintain as the program grows.\n", + "\n", + "2. **Functional Programming**\n", + "\n", + " * Based on functions as the main building blocks.\n", + " * Focuses on transforming data through function calls.\n", + "\n", + "3. **Object-Oriented Programming (OOP)**\n", + "\n", + " * Organizes code around *objects* and *classes*.\n", + " * Objects act as containers that store data and behavior together.\n", + "\n", + "---\n", + "\n", + "## **2. The Scaling Problem in Non-OOP Paradigms**\n", + "\n", + "Functional and procedural programming share a major disadvantage:\n", + "\n", + "### **❗ The problem of scalability and maintainability**\n", + "\n", + "* In large projects, code becomes tightly connected and interdependent.\n", + "* Changing one part often requires modifying many lines across the program.\n", + "* This makes development slow and error-prone.\n", + "\n", + "---\n", + "\n", + "## **3. Core Idea of OOP**\n", + "\n", + "OOP solves the maintainability problem by introducing two key concepts:\n", + "\n", + "### **✔ Class**\n", + "\n", + "A blueprint or template that defines:\n", + "\n", + "* what data (attributes) an object holds\n", + "* what actions (methods) it can perform\n", + "\n", + "### **✔ Object**\n", + "\n", + "A concrete instance created from a class — a container that holds:\n", + "\n", + "* **data**\n", + "* **methods that operate on that data**\n", + "\n", + "---\n", + "\n", + "## **4. Why OOP Helps with Large Projects**\n", + "\n", + "OOP makes complex programs easier to manage because:\n", + "\n", + "### **Encapsulation**\n", + "\n", + "* Internal implementation of a component can be changed at any time\n", + "* Other parts of the program are unaffected as long as the external interface stays the same\n", + "\n", + "### **Reusability**\n", + "\n", + "* Classes and objects can be reused in other programs and tasks\n", + "* Reduces duplication, speeds up development\n", + "\n", + "### **Modularity**\n", + "\n", + "* The program is divided into independent components\n", + "* Easier to debug, maintain, and extend\n", + "\n", + "---\n", + "\n", + "## **5. Summary**\n", + "\n", + "Object-Oriented Programming is a way of writing code that groups data and behavior into classes and objects. Unlike procedural and functional programming, OOP scales much better: changes in one place do not break the entire program. This makes the code cleaner, more modular, and reusable.\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a8de028d", + "metadata": {}, + "outputs": [], + "source": [ + "# for example:\n", + "from __future__ import annotations\n", + "\n", + "from typing import ClassVar\n", + "\n", + "import requests\n", + "from requests import Response\n", + "\n", + "# requesting with .get() method to get the response from google.com\n", + "google_response: Response = requests.get(\"https://google.com\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ae9ef76d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "requests.models.Response" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# as we see below, google_response is an instance of Response class\n", + "type(google_response)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f3c903d1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']\n" + ] + } + ], + "source": [ + "# we can also see all attributes and methods of the Response class\n", + "print(dir(google_response))" + ] + }, + { + "cell_type": "markdown", + "id": "316bea5a", + "metadata": {}, + "source": [ + "---\n", + "\n", + "# **Conspect: Dualism of Data and Actions in OOP**\n", + "\n", + "## **1. Dualism: Data vs. Actions**\n", + "\n", + "In computer science, every piece of information has two aspects:\n", + "\n", + "* **Data** — values or state that must be stored.\n", + "* **Actions** — operations that can be performed on those values.\n", + "\n", + "OOP unifies these two aspects inside a single structure called an **object**.\n", + "\n", + "---\n", + "\n", + "## **2. Why Data Is Divided Into Types**\n", + "\n", + "Data types exist because:\n", + "\n", + "1. **Different types require different amounts of memory.**\n", + " An integer, a float, and a string all occupy different memory sizes.\n", + "\n", + "2. **Different types behave differently under the same operations.**\n", + " Example:\n", + "\n", + " * `\"2\" + \"2\"` → `\"22\"` (string concatenation)\n", + " * `2 + 2` → `4` (integer addition)\n", + "\n", + "So a type defines:\n", + "\n", + "* how much memory to allocate\n", + "* how operations should work with this data\n", + "\n", + "---\n", + "\n", + "## **3. What Is an Object?**\n", + "\n", + "An object is a memory allocation that contains **both**:\n", + "\n", + "1. **Data (state)**\n", + "2. **Methods (behavior)** that operate on that data\n", + "\n", + "In Python, **everything is represented as an object**.\n", + "\n", + "You can think of an object as an abstract **container** holding:\n", + "\n", + "* the values (attributes)\n", + "* the operations available for those values (methods)\n", + "\n", + "---\n", + "\n", + "## **4. Object State and Attributes**\n", + "\n", + "Objects stored in computer memory hold some **state**.\n", + "State = values stored at specific memory addresses at a given moment.\n", + "\n", + "These stored values are called:\n", + "\n", + "* **fields**\n", + "* **properties**\n", + "* **attributes**\n", + "\n", + "Attributes describe the characteristics of the object.\n", + "\n", + "---\n", + "\n", + "## **5. Behavior of an Object**\n", + "\n", + "Besides data, every object also includes **functionality**—methods that define what the object can do or how it behaves.\n", + "\n", + "When designing in OOP we must:\n", + "\n", + "1. Determine what the **data** will be.\n", + "2. Decide what **operations** need to be performed on that data.\n", + "3. Define **interaction rules** between objects.\n", + "\n", + "### **Core idea of OOP**\n", + "\n", + "> Combine data + actions into a single unit (object).\n", + "\n", + "---\n", + "\n", + "## **6. Classes and Instances**\n", + "\n", + "Custom (user-defined) objects are created using **classes**.\n", + "\n", + "### **Class**\n", + "\n", + "A class is a **description** or **blueprint** that tells Python:\n", + "\n", + "* what attributes the object will have\n", + "* what methods will operate on those attributes\n", + "\n", + "### **Instance (Object of a Class)**\n", + "\n", + "An object created from a class is called:\n", + "\n", + "* an **instance of the class**\n", + "* a **class object**\n", + "\n", + "All objects of one class share the **same structure**:\n", + "\n", + "* same attributes\n", + "* same methods\n", + "\n", + "…but they may hold **different states** (different values of those attributes).\n", + "\n", + "---\n", + "\n", + "# **Short Summary**\n", + "\n", + "* Data types exist because memory usage and behavior differ between data kinds.\n", + "* An **object** is a structure that stores both data (attributes) and actions (methods).\n", + "* Python represents *everything* as an object.\n", + "* OOP is about designing programs by combining data + behavior into objects.\n", + "* Classes define what objects look like; objects are instances of classes and may have different states.\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "208de7ce", + "metadata": {}, + "outputs": [], + "source": [ + "# key word \"class\" is used to define a class in Python\n", + "# here is a simple class definition\n", + "# pep say that class names should use CapWords convention\n", + "# where each word starts with a capital letter and there are no underscores\n", + "class FirstPerson:\n", + " \"\"\"A class representing a first-person perspective in programming.\"\"\"\n", + "\n", + " name: ClassVar[str] = \"Ivan\"\n", + " # Class variable shared by all instances" + ] + }, + { + "cell_type": "markdown", + "id": "588753ee", + "metadata": {}, + "source": [ + "We access the methods and properties of an object using a dot, known as dot notation." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "85224905", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ivan\n" + ] + } + ], + "source": [ + "print(FirstPerson.name) # Accessing the class variable" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e6a95334", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FirstPerson\n" + ] + } + ], + "source": [ + "# every class has a built-in attribute __name__\n", + "# that holds the name of the class as a string\n", + "print(FirstPerson.__name__) # Output: FirstPerson" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c265b3ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']\n" + ] + } + ], + "source": [ + "# with the dir() function, we can see all\n", + "# attributes and methods of the class\n", + "print(dir(FirstPerson))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1dd47fa0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# class of user defined class is 'type'\n", + "# because class is a user-defined type\n", + "print(FirstPerson.__class__)\n", + "# Output: " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b437bda7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# To create an instance of a class, we must call the class.\n", + "# Calling the class returns a new object of that class.\n", + "first_person_instance = FirstPerson()\n", + "print(first_person_instance.__class__)\n", + "# Output: " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5306c5a7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# same thing we can check with type()\n", + "print(type(first_person_instance))" + ] + }, + { + "cell_type": "markdown", + "id": "7f57da8a", + "metadata": {}, + "source": [ + "When I say class, I primarily mean object descriptions. " + ] + }, + { + "cell_type": "markdown", + "id": "196d313b", + "metadata": {}, + "source": [ + "---\n", + "\n", + "# **Conspect: Properties of Class Functions and Namespaces in Python OOP**\n", + "\n", + "## **1. A Class Creates Its Own Namespace**\n", + "\n", + "When a class is defined, Python creates a **namespace** for it — a special dictionary that stores:\n", + "\n", + "* variable names\n", + "* function names\n", + "* their corresponding values\n", + "\n", + "Example:\n", + "\n", + "```python\n", + "class Person:\n", + " name = \"Ivan\"\n", + "```\n", + "\n", + "Here, the class namespace contains:\n", + "\n", + "* key `\"name\"` with value `\"Ivan\"`\n", + "\n", + "You can inspect class attributes using:\n", + "\n", + "```python\n", + "dir(Person)\n", + "```\n", + "\n", + "---\n", + "\n", + "## **2. Where Object State Is Stored: `__dict__`**\n", + "\n", + "Both **classes** and **instances** store their attributes in a dictionary-like structure accessible via `__dict__`.\n", + "\n", + "* For classes: `Person.__dict__`\n", + "* For instances: `p.__dict__`\n", + "\n", + "These dictionaries hold the state of the object at a given moment.\n", + "\n", + "### But there is an important nuance:\n", + "\n", + "`Class.__dict__` returns a **mappingproxy** — a **read-only view** of the class namespace.\n", + "\n", + "Example:\n", + "\n", + "```python\n", + "Person.__dict__[\"name\"] = \"Vasa\"\n", + "```\n", + "\n", + "This will raise an **error**, because `mappingproxy` cannot be modified directly.\n", + "\n", + "---\n", + "\n", + "## **3. Why `mappingproxy` Exists**\n", + "\n", + "`mappingproxy` protects the class namespace from direct accidental modification.\n", + "It behaves like a dictionary **except**:\n", + "\n", + "* you **cannot assign** new values through it\n", + "* you **cannot add** new keys\n", + "* you **cannot delete** keys\n", + "\n", + "It is a read-only wrapper around the real dictionary inside the class.\n", + "\n", + "---\n", + "\n", + "## **4. How to Modify Attributes Correctly**\n", + "\n", + "Although the class namespace cannot be modified through `__dict__`, it **can** be changed using:\n", + "\n", + "### ✔ Dot notation\n", + "\n", + "```python\n", + "Person.age = 30\n", + "```\n", + "\n", + "### ✔ Built-in functions\n", + "\n", + "* `getattr(obj, \"attr\")`\n", + "* `setattr(obj, \"attr\", value)`\n", + "* `delattr(obj, \"attr\")`\n", + "\n", + "These functions allow controlled, dynamic access to attributes.\n", + "\n", + "---\n", + "\n", + "## **5. Python Allows Modifying Classes at Runtime**\n", + "\n", + "Because Python is a **dynamic language**, you can **add new attributes or methods to a class even after it has been defined**.\n", + "\n", + "Example:\n", + "\n", + "```python\n", + "Person.country = \"Russia\"\n", + "```\n", + "\n", + "Now all instances of `Person`, including previously created ones, have access to `country`.\n", + "\n", + "---\n", + "\n", + "## **Summary**\n", + "\n", + "* A class creates its own **namespace**, implemented as a dictionary of attributes.\n", + "* This namespace is exposed as a read-only `mappingproxy` through `Class.__dict__`.\n", + "* Instance attributes are stored in their own writable dictionary `Instance.__dict__`.\n", + "* You cannot modify the class namespace *through* `__dict__`, but you can modify it:\n", + "\n", + " * using dot notation\n", + " * using `getattr`, `setattr`, `delattr`\n", + "* Python’s dynamic nature allows adding new attributes and methods to a class **after** definition.\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7eafceee", + "metadata": {}, + "outputs": [], + "source": [ + "class SecondPerson:\n", + " \"\"\"Represent lesson 2 person with mutable attributes.\"\"\"\n", + "\n", + " name: ClassVar[str] = \"Peter\"\n", + " age: ClassVar[int]\n", + " dob: ClassVar[str]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1135f4a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']\n" + ] + } + ], + "source": [ + "# checking the attributes of SecondPerson class\n", + "print(dir(SecondPerson))" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "ed17aa17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'__module__': '__main__', '__annotations__': {'name': 'ClassVar[str]', 'age': 'ClassVar[int]', 'dob': 'ClassVar[str]'}, '__doc__': 'Represent lesson 2 person with mutable attributes.', 'name': 'Peter', '__dict__': , '__weakref__': , 'age': 30, 'dob': '1993-01-01'}\n" + ] + } + ], + "source": [ + "# checking the namespace of SecondPerson class\n", + "print(SecondPerson.__dict__)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "347d39a9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'__module__': '__main__', '__annotations__': {'name': 'ClassVar[str]', 'age': 'ClassVar[int]', 'dob': 'ClassVar[str]'}, '__doc__': 'Represent lesson 2 person with mutable attributes.', 'name': 'Peter', '__dict__': , '__weakref__': , 'age': 30, 'dob': '1993-01-01'}\n" + ] + } + ], + "source": [ + "# modifying class attributes\n", + "SecondPerson.age = 30\n", + "SecondPerson.dob = \"1993-01-01\"\n", + "# checking the updated namespace of SecondPerson class\n", + "print(SecondPerson.__dict__)" + ] + }, + { + "cell_type": "markdown", + "id": "ec6aa9ce", + "metadata": {}, + "source": [ + "---\n", + "\n", + "# **Conspect: Classes as Callable Objects and Isolated Namespaces**\n", + "\n", + "## **1. Classes Are Callable Objects**\n", + "\n", + "In Python, a **class is a callable object**.\n", + "When a class is called, Python creates and returns a **new instance** of that class.\n", + "\n", + "Example:\n", + "\n", + "```python\n", + "p = Person()\n", + "```\n", + "\n", + "Here:\n", + "\n", + "* `Person` is called like a function\n", + "* `p` is an instance of the class `Person`\n", + "\n", + "---\n", + "\n", + "## **2. Classes and Instances Have Separate Namespaces**\n", + "\n", + "Each **class** and each **instance** has its own **independent namespace**.\n", + "\n", + "* Class namespace → stores **class attributes and methods**\n", + "* Instance namespace → stores **instance-specific attributes (state)**\n", + "\n", + "These namespaces:\n", + "\n", + "* are **isolated from each other**\n", + "* do **not overwrite** one another\n", + "* interact only through defined attribute lookup rules\n", + "\n", + "---\n", + "\n", + "## **3. Why Namespace Isolation Is Important**\n", + "\n", + "Namespace isolation allows:\n", + "\n", + "* creation of many objects with the **same structure**\n", + "* each object to maintain its **own unique state**\n", + "* safe modification of one object without affecting others\n", + "\n", + "Example:\n", + "\n", + "```python\n", + "p1 = Person()\n", + "p2 = Person()\n", + "\n", + "p1.name = \"Ivan\"\n", + "p2.name = \"Alex\"\n", + "```\n", + "\n", + "Both objects:\n", + "\n", + "* share the same class definition\n", + "* have different values for their attributes\n", + "\n", + "---\n", + "\n", + "## **4. Core Advantage of This Design**\n", + "\n", + "The separation of namespaces enables:\n", + "\n", + "* scalability\n", + "* memory efficiency\n", + "* predictable behavior\n", + "\n", + "This is why we can create **thousands or millions of objects** with:\n", + "\n", + "* identical properties and methods\n", + "* different internal data values\n", + "\n", + "---\n", + "\n", + "## **Short Summary**\n", + "\n", + "* Classes in Python are callable.\n", + "* Calling a class creates an instance.\n", + "* Classes and instances have isolated namespaces.\n", + "* This isolation allows many similar objects to exist with different states.\n", + "* It is a fundamental mechanism behind object-oriented programming.\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "3bacf95e", + "metadata": {}, + "source": [ + "поведение функции отличается от поведения свойств " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e2d9561a", + "metadata": {}, + "outputs": [], + "source": [ + "class PersonLesson4:\n", + " \"\"\"Represent lesson 4 person with a simple greeter.\"\"\"\n", + "\n", + " def hello(self: PersonLesson4) -> None:\n", + " \"\"\"Say hello from the class namespace.\"\"\"\n", + " print(\"Hello!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "af936ec4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print(PersonLesson4.hello)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "ad883d52", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ">\n" + ] + } + ], + "source": [ + "greeting_person: PersonLesson4 = PersonLesson4()\n", + "print(greeting_person.hello)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "93c59755", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x28a182b3a70\n" + ] + } + ], + "source": [ + "print(hex(id(greeting_person)))" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "f212547e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello!\n" + ] + } + ], + "source": [ + "PersonLesson4.hello(greeting_person)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "53062a23", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print(type(greeting_person.hello))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "65d5b70e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print(type(PersonLesson4.hello))" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "0479eb85", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2792134444672, 2792134519936)\n" + ] + } + ], + "source": [ + "print((id(PersonLesson4.hello), id(greeting_person.hello)))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "0957c488", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__getstate__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__type_params__']\n" + ] + } + ], + "source": [ + "print(dir(PersonLesson4.hello))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "300fe98b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']\n" + ] + } + ], + "source": [ + "print(dir(greeting_person.hello))" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "404de79d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<__main__.PersonLesson4 object at 0x0000028A182B3A70>\n" + ] + } + ], + "source": [ + "print(greeting_person.hello.__self__) # type: ignore[attr-defined]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "5205ad78", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x28a182b3a70\n" + ] + } + ], + "source": [ + "print(hex(id(greeting_person)))" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "5bba4c38", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print(greeting_person.hello.__func__) # type: ignore[attr-defined]" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "6d1e338c", + "metadata": {}, + "outputs": [], + "source": [ + "class PersonLesson4BoundInspector:\n", + " \"\"\"Inspect bound method internals via a person.\"\"\"\n", + "\n", + " def hello(self: PersonLesson4BoundInspector) -> None:\n", + " \"\"\"Display the instance reference.\"\"\"\n", + " print(self)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "862fb51a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<__main__.PersonLesson4BoundInspector object at 0x0000028A182B28A0>\n" + ] + } + ], + "source": [ + "inspected_person: PersonLesson4BoundInspector = PersonLesson4BoundInspector()\n", + "inspected_person.hello()" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "32e2323f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x28a182b28a0\n" + ] + } + ], + "source": [ + "print(hex(id(inspected_person)))" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "2f5eb356", + "metadata": {}, + "outputs": [], + "source": [ + "class PersonLesson4Self:\n", + " \"\"\"Display instance reference through self.\"\"\"\n", + "\n", + " def hello(self: PersonLesson4Self) -> None:\n", + " \"\"\"Display the instance reference through self.\"\"\"\n", + " print(self)" + ] + }, + { + "cell_type": "markdown", + "id": "d116459c", + "metadata": {}, + "source": [ + "Here is a **minimal, clean demo** that shows **exactly the core ideas**:\n", + "class function → bound method → `self` → `__self__` / `__func__`.\n", + "\n", + "```python\n", + "class Person:\n", + " def hello(self) -> None:\n", + " print(\"Hello\")\n", + "\n", + "\n", + "p = Person()\n", + "\n", + "# 1. Class attribute vs instance attribute\n", + "print(Person.hello) # function (unbound)\n", + "print(p.hello) # bound method\n", + "\n", + "# 2. Calling methods\n", + "Person.hello(p) # manual call\n", + "p.hello() # automatic self passing\n", + "\n", + "# 3. Types\n", + "print(type(Person.hello)) # function\n", + "print(type(p.hello)) # method\n", + "\n", + "# 4. Bound method internals\n", + "print(p.hello.__self__) # instance the method is bound to\n", + "print(p.hello.__func__) # original function object\n", + "\n", + "# 5. Identity proof\n", + "print(hex(id(p)))\n", + "print(hex(id(p.hello.__self__)))\n", + "```\n", + "\n", + "### What this demo proves\n", + "\n", + "* A method is **just a function in the class**\n", + "* Access through an instance creates a **bound method**\n", + "* `self` is passed automatically\n", + "* Bound methods store:\n", + "\n", + " * `__self__` → the instance\n", + " * `__func__` → the function\n", + "* Class and instance namespaces remain separate" + ] + }, + { + "cell_type": "markdown", + "id": "20360471", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## **Dynamic Attributes vs Initialization with `__init__`**\n", + "\n", + "### **1. Dynamic Attribute Assignment**\n", + "\n", + "```python\n", + "class PersonLesson5Placeholder:\n", + " name: str\n", + "```\n", + "\n", + "* The class only contains a **type annotation**, not a real attribute.\n", + "* No memory is allocated for `name` at class creation.\n", + "* The attribute appears **only when assigned to an instance**.\n", + "\n", + "```python\n", + "person_with_dynamic_attr = PersonLesson5Placeholder()\n", + "person_with_dynamic_attr.name = \"Ivan\"\n", + "```\n", + "\n", + "✔ Python allows adding attributes to objects **at runtime**.\n", + "✔ The attribute `name` now exists **only in the instance namespace**.\n", + "\n", + "```python\n", + "print(person_with_dynamic_attr.name)\n", + "```\n", + "\n", + "---\n", + "\n", + "### **2. Instance Namespace (`__dict__`)**\n", + "\n", + "Every instance stores its state in `__dict__`.\n", + "\n", + "If you printed:\n", + "\n", + "```python\n", + "print(person_with_dynamic_attr.__dict__)\n", + "```\n", + "\n", + "You would get:\n", + "\n", + "```python\n", + "{\"name\": \"Ivan\"}\n", + "```\n", + "\n", + "---\n", + "\n", + "## **3. Attribute Initialization via `__init__`**\n", + "\n", + "```python\n", + "class PersonLesson5Named:\n", + " def __init__(self, name: str) -> None:\n", + " self.name = name\n", + "```\n", + "\n", + "* `__init__` defines **how an object is initialized**\n", + "* Guarantees that every instance **has the attribute**\n", + "* Prevents partially initialized objects\n", + "\n", + "```python\n", + "named_person = PersonLesson5Named(\"Max\")\n", + "```\n", + "\n", + "Now the attribute exists immediately after creation.\n", + "\n", + "---\n", + "\n", + "### **4. Inspecting Object State**\n", + "\n", + "```python\n", + "print(named_person.__dict__)\n", + "```\n", + "\n", + "Output:\n", + "\n", + "```python\n", + "{\"name\": \"Max\"}\n", + "```\n", + "\n", + "This confirms:\n", + "\n", + "* Attributes live in the instance namespace\n", + "* `self.name` is just a key-value pair in `__dict__`\n", + "\n", + "---\n", + "\n", + "## **Key Differences (Very Important)**\n", + "\n", + "| Dynamic attribute | `__init__` initialization |\n", + "| ----------------- | ------------------------- |\n", + "| Added at runtime | Added during creation |\n", + "| Optional | Guaranteed |\n", + "| Error-prone | Safe and explicit |\n", + "| Flexible | Structured |\n", + "\n", + "---\n", + "\n", + "## **Core Takeaway**\n", + "\n", + "* Python allows **dynamic attribute creation**, but this is rarely ideal.\n", + "* `__init__` is the **correct and safe** way to define an object’s state.\n", + "* All instance data is stored in `instance.__dict__`.\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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/oop.py b/python/oop.py new file mode 100644 index 00000000..c7627d5b --- /dev/null +++ b/python/oop.py @@ -0,0 +1,699 @@ +"""Programming Paradigms and Object-Oriented Programming in Python.""" + +# Here is a **clear, structured English conspect (summary + notes)** about OOP. +# +# --- +# +# # **Conspect: Introduction to Object-Oriented Programming (OOP)** +# +# ## **1. Programming Paradigms Overview** +# +# Programming paradigms are different ways of writing and organizing code. OOP is one of these approaches, but not the only one. +# +# ### **Main paradigms:** +# +# 1. **Procedural Programming** +# +# * Code is written as a sequence of instructions, executed line by line. +# * Easy to start with, but becomes difficult to maintain as the program grows. +# +# 2. **Functional Programming** +# +# * Based on functions as the main building blocks. +# * Focuses on transforming data through function calls. +# +# 3. **Object-Oriented Programming (OOP)** +# +# * Organizes code around *objects* and *classes*. +# * Objects act as containers that store data and behavior together. +# +# --- +# +# ## **2. The Scaling Problem in Non-OOP Paradigms** +# +# Functional and procedural programming share a major disadvantage: +# +# ### **❗ The problem of scalability and maintainability** +# +# * In large projects, code becomes tightly connected and interdependent. +# * Changing one part often requires modifying many lines across the program. +# * This makes development slow and error-prone. +# +# --- +# +# ## **3. Core Idea of OOP** +# +# OOP solves the maintainability problem by introducing two key concepts: +# +# ### **✔ Class** +# +# A blueprint or template that defines: +# +# * what data (attributes) an object holds +# * what actions (methods) it can perform +# +# ### **✔ Object** +# +# A concrete instance created from a class — a container that holds: +# +# * **data** +# * **methods that operate on that data** +# +# --- +# +# ## **4. Why OOP Helps with Large Projects** +# +# OOP makes complex programs easier to manage because: +# +# ### **Encapsulation** +# +# * Internal implementation of a component can be changed at any time +# * Other parts of the program are unaffected as long as the external interface stays the same +# +# ### **Reusability** +# +# * Classes and objects can be reused in other programs and tasks +# * Reduces duplication, speeds up development +# +# ### **Modularity** +# +# * The program is divided into independent components +# * Easier to debug, maintain, and extend +# +# --- +# +# ## **5. Summary** +# +# Object-Oriented Programming is a way of writing code that groups data and behavior into classes and objects. Unlike procedural and functional programming, OOP scales much better: changes in one place do not break the entire program. This makes the code cleaner, more modular, and reusable. +# +# --- + +# + +# for example: +from __future__ import annotations + +from typing import ClassVar + +import requests +from requests import Response + +# requesting with .get() method to get the response from google.com +google_response: Response = requests.get("https://google.com") +# - + +# as we see below, google_response is an instance of Response class +type(google_response) + +# we can also see all attributes and methods of the Response class +print(dir(google_response)) + + +# --- +# +# # **Conspect: Dualism of Data and Actions in OOP** +# +# ## **1. Dualism: Data vs. Actions** +# +# In computer science, every piece of information has two aspects: +# +# * **Data** — values or state that must be stored. +# * **Actions** — operations that can be performed on those values. +# +# OOP unifies these two aspects inside a single structure called an **object**. +# +# --- +# +# ## **2. Why Data Is Divided Into Types** +# +# Data types exist because: +# +# 1. **Different types require different amounts of memory.** +# An integer, a float, and a string all occupy different memory sizes. +# +# 2. **Different types behave differently under the same operations.** +# Example: +# +# * `"2" + "2"` → `"22"` (string concatenation) +# * `2 + 2` → `4` (integer addition) +# +# So a type defines: +# +# * how much memory to allocate +# * how operations should work with this data +# +# --- +# +# ## **3. What Is an Object?** +# +# An object is a memory allocation that contains **both**: +# +# 1. **Data (state)** +# 2. **Methods (behavior)** that operate on that data +# +# In Python, **everything is represented as an object**. +# +# You can think of an object as an abstract **container** holding: +# +# * the values (attributes) +# * the operations available for those values (methods) +# +# --- +# +# ## **4. Object State and Attributes** +# +# Objects stored in computer memory hold some **state**. +# State = values stored at specific memory addresses at a given moment. +# +# These stored values are called: +# +# * **fields** +# * **properties** +# * **attributes** +# +# Attributes describe the characteristics of the object. +# +# --- +# +# ## **5. Behavior of an Object** +# +# Besides data, every object also includes **functionality**—methods that define what the object can do or how it behaves. +# +# When designing in OOP we must: +# +# 1. Determine what the **data** will be. +# 2. Decide what **operations** need to be performed on that data. +# 3. Define **interaction rules** between objects. +# +# ### **Core idea of OOP** +# +# > Combine data + actions into a single unit (object). +# +# --- +# +# ## **6. Classes and Instances** +# +# Custom (user-defined) objects are created using **classes**. +# +# ### **Class** +# +# A class is a **description** or **blueprint** that tells Python: +# +# * what attributes the object will have +# * what methods will operate on those attributes +# +# ### **Instance (Object of a Class)** +# +# An object created from a class is called: +# +# * an **instance of the class** +# * a **class object** +# +# All objects of one class share the **same structure**: +# +# * same attributes +# * same methods +# +# …but they may hold **different states** (different values of those attributes). +# +# --- +# +# # **Short Summary** +# +# * Data types exist because memory usage and behavior differ between data kinds. +# * An **object** is a structure that stores both data (attributes) and actions (methods). +# * Python represents *everything* as an object. +# * OOP is about designing programs by combining data + behavior into objects. +# * Classes define what objects look like; objects are instances of classes and may have different states. +# +# --- + + +# key word "class" is used to define a class in Python +# here is a simple class definition +# pep say that class names should use CapWords convention +# where each word starts with a capital letter and there are no underscores +class FirstPerson: + """A class representing a first-person perspective in programming.""" + + name: ClassVar[str] = "Ivan" + # Class variable shared by all instances + + +# We access the methods and properties of an object using a dot, known as dot notation. + +print(FirstPerson.name) # Accessing the class variable + +# every class has a built-in attribute __name__ +# that holds the name of the class as a string +print(FirstPerson.__name__) # Output: FirstPerson + +# with the dir() function, we can see all +# attributes and methods of the class +print(dir(FirstPerson)) + +# class of user defined class is 'type' +# because class is a user-defined type +print(FirstPerson.__class__) +# Output: + +# To create an instance of a class, we must call the class. +# Calling the class returns a new object of that class. +first_person_instance = FirstPerson() +print(first_person_instance.__class__) +# Output: + +# same thing we can check with type() +print(type(first_person_instance)) + + +# When I say class, I primarily mean object descriptions. + +# --- +# +# # **Conspect: Properties of Class Functions and Namespaces in Python OOP** +# +# ## **1. A Class Creates Its Own Namespace** +# +# When a class is defined, Python creates a **namespace** for it — a special dictionary that stores: +# +# * variable names +# * function names +# * their corresponding values +# +# Example: +# +# ```python +# class Person: +# name = "Ivan" +# ``` +# +# Here, the class namespace contains: +# +# * key `"name"` with value `"Ivan"` +# +# You can inspect class attributes using: +# +# ```python +# dir(Person) +# ``` +# +# --- +# +# ## **2. Where Object State Is Stored: `__dict__`** +# +# Both **classes** and **instances** store their attributes in a dictionary-like structure accessible via `__dict__`. +# +# * For classes: `Person.__dict__` +# * For instances: `p.__dict__` +# +# These dictionaries hold the state of the object at a given moment. +# +# ### But there is an important nuance: +# +# `Class.__dict__` returns a **mappingproxy** — a **read-only view** of the class namespace. +# +# Example: +# +# ```python +# Person.__dict__["name"] = "Vasa" +# ``` +# +# This will raise an **error**, because `mappingproxy` cannot be modified directly. +# +# --- +# +# ## **3. Why `mappingproxy` Exists** +# +# `mappingproxy` protects the class namespace from direct accidental modification. +# It behaves like a dictionary **except**: +# +# * you **cannot assign** new values through it +# * you **cannot add** new keys +# * you **cannot delete** keys +# +# It is a read-only wrapper around the real dictionary inside the class. +# +# --- +# +# ## **4. How to Modify Attributes Correctly** +# +# Although the class namespace cannot be modified through `__dict__`, it **can** be changed using: +# +# ### ✔ Dot notation +# +# ```python +# Person.age = 30 +# ``` +# +# ### ✔ Built-in functions +# +# * `getattr(obj, "attr")` +# * `setattr(obj, "attr", value)` +# * `delattr(obj, "attr")` +# +# These functions allow controlled, dynamic access to attributes. +# +# --- +# +# ## **5. Python Allows Modifying Classes at Runtime** +# +# Because Python is a **dynamic language**, you can **add new attributes or methods to a class even after it has been defined**. +# +# Example: +# +# ```python +# Person.country = "Russia" +# ``` +# +# Now all instances of `Person`, including previously created ones, have access to `country`. +# +# --- +# +# ## **Summary** +# +# * A class creates its own **namespace**, implemented as a dictionary of attributes. +# * This namespace is exposed as a read-only `mappingproxy` through `Class.__dict__`. +# * Instance attributes are stored in their own writable dictionary `Instance.__dict__`. +# * You cannot modify the class namespace *through* `__dict__`, but you can modify it: +# +# * using dot notation +# * using `getattr`, `setattr`, `delattr` +# * Python’s dynamic nature allows adding new attributes and methods to a class **after** definition. +# +# --- + + +class SecondPerson: + """Represent lesson 2 person with mutable attributes.""" + + name: ClassVar[str] = "Peter" + age: ClassVar[int] + dob: ClassVar[str] + + +# checking the attributes of SecondPerson class +print(dir(SecondPerson)) + +# checking the namespace of SecondPerson class +print(SecondPerson.__dict__) + +# modifying class attributes +SecondPerson.age = 30 +SecondPerson.dob = "1993-01-01" +# checking the updated namespace of SecondPerson class +print(SecondPerson.__dict__) + + +# --- +# +# # **Conspect: Classes as Callable Objects and Isolated Namespaces** +# +# ## **1. Classes Are Callable Objects** +# +# In Python, a **class is a callable object**. +# When a class is called, Python creates and returns a **new instance** of that class. +# +# Example: +# +# ```python +# p = Person() +# ``` +# +# Here: +# +# * `Person` is called like a function +# * `p` is an instance of the class `Person` +# +# --- +# +# ## **2. Classes and Instances Have Separate Namespaces** +# +# Each **class** and each **instance** has its own **independent namespace**. +# +# * Class namespace → stores **class attributes and methods** +# * Instance namespace → stores **instance-specific attributes (state)** +# +# These namespaces: +# +# * are **isolated from each other** +# * do **not overwrite** one another +# * interact only through defined attribute lookup rules +# +# --- +# +# ## **3. Why Namespace Isolation Is Important** +# +# Namespace isolation allows: +# +# * creation of many objects with the **same structure** +# * each object to maintain its **own unique state** +# * safe modification of one object without affecting others +# +# Example: +# +# ```python +# p1 = Person() +# p2 = Person() +# +# p1.name = "Ivan" +# p2.name = "Alex" +# ``` +# +# Both objects: +# +# * share the same class definition +# * have different values for their attributes +# +# --- +# +# ## **4. Core Advantage of This Design** +# +# The separation of namespaces enables: +# +# * scalability +# * memory efficiency +# * predictable behavior +# +# This is why we can create **thousands or millions of objects** with: +# +# * identical properties and methods +# * different internal data values +# +# --- +# +# ## **Short Summary** +# +# * Classes in Python are callable. +# * Calling a class creates an instance. +# * Classes and instances have isolated namespaces. +# * This isolation allows many similar objects to exist with different states. +# * It is a fundamental mechanism behind object-oriented programming. +# +# --- + +# поведение функции отличается от поведения свойств + + +class PersonLesson4: + """Represent lesson 4 person with a simple greeter.""" + + def hello(self: PersonLesson4) -> None: + """Say hello from the class namespace.""" + print("Hello!") + + +print(PersonLesson4.hello) + +greeting_person: PersonLesson4 = PersonLesson4() +print(greeting_person.hello) + +print(hex(id(greeting_person))) + +PersonLesson4.hello(greeting_person) + +print(type(greeting_person.hello)) + +print(type(PersonLesson4.hello)) + +print((id(PersonLesson4.hello), id(greeting_person.hello))) + +print(dir(PersonLesson4.hello)) + +print(dir(greeting_person.hello)) + +print(greeting_person.hello.__self__) # type: ignore[attr-defined] + +print(hex(id(greeting_person))) + +print(greeting_person.hello.__func__) # type: ignore[attr-defined] + + +class PersonLesson4BoundInspector: + """Inspect bound method internals via a person.""" + + def hello(self: PersonLesson4BoundInspector) -> None: + """Display the instance reference.""" + print(self) + + +inspected_person: PersonLesson4BoundInspector = PersonLesson4BoundInspector() +inspected_person.hello() + +print(hex(id(inspected_person))) + + +class PersonLesson4Self: + """Display instance reference through self.""" + + def hello(self: PersonLesson4Self) -> None: + """Display the instance reference through self.""" + print(self) + + +# Here is a **minimal, clean demo** that shows **exactly the core ideas**: +# class function → bound method → `self` → `__self__` / `__func__`. +# +# ```python +# class Person: +# def hello(self) -> None: +# print("Hello") +# +# +# p = Person() +# +# # 1. Class attribute vs instance attribute +# print(Person.hello) # function (unbound) +# print(p.hello) # bound method +# +# # 2. Calling methods +# Person.hello(p) # manual call +# p.hello() # automatic self passing +# +# # 3. Types +# print(type(Person.hello)) # function +# print(type(p.hello)) # method +# +# # 4. Bound method internals +# print(p.hello.__self__) # instance the method is bound to +# print(p.hello.__func__) # original function object +# +# # 5. Identity proof +# print(hex(id(p))) +# print(hex(id(p.hello.__self__))) +# ``` +# +# ### What this demo proves +# +# * A method is **just a function in the class** +# * Access through an instance creates a **bound method** +# * `self` is passed automatically +# * Bound methods store: +# +# * `__self__` → the instance +# * `__func__` → the function +# * Class and instance namespaces remain separate + +# --- +# +# ## **Dynamic Attributes vs Initialization with `__init__`** +# +# ### **1. Dynamic Attribute Assignment** +# +# ```python +# class PersonLesson5Placeholder: +# name: str +# ``` +# +# * The class only contains a **type annotation**, not a real attribute. +# * No memory is allocated for `name` at class creation. +# * The attribute appears **only when assigned to an instance**. +# +# ```python +# person_with_dynamic_attr = PersonLesson5Placeholder() +# person_with_dynamic_attr.name = "Ivan" +# ``` +# +# ✔ Python allows adding attributes to objects **at runtime**. +# ✔ The attribute `name` now exists **only in the instance namespace**. +# +# ```python +# print(person_with_dynamic_attr.name) +# ``` +# +# --- +# +# ### **2. Instance Namespace (`__dict__`)** +# +# Every instance stores its state in `__dict__`. +# +# If you printed: +# +# ```python +# print(person_with_dynamic_attr.__dict__) +# ``` +# +# You would get: +# +# ```python +# {"name": "Ivan"} +# ``` +# +# --- +# +# ## **3. Attribute Initialization via `__init__`** +# +# ```python +# class PersonLesson5Named: +# def __init__(self, name: str) -> None: +# self.name = name +# ``` +# +# * `__init__` defines **how an object is initialized** +# * Guarantees that every instance **has the attribute** +# * Prevents partially initialized objects +# +# ```python +# named_person = PersonLesson5Named("Max") +# ``` +# +# Now the attribute exists immediately after creation. +# +# --- +# +# ### **4. Inspecting Object State** +# +# ```python +# print(named_person.__dict__) +# ``` +# +# Output: +# +# ```python +# {"name": "Max"} +# ``` +# +# This confirms: +# +# * Attributes live in the instance namespace +# * `self.name` is just a key-value pair in `__dict__` +# +# --- +# +# ## **Key Differences (Very Important)** +# +# | Dynamic attribute | `__init__` initialization | +# | ----------------- | ------------------------- | +# | Added at runtime | Added during creation | +# | Optional | Guaranteed | +# | Error-prone | Safe and explicit | +# | Flexible | Structured | +# +# --- +# +# ## **Core Takeaway** +# +# * Python allows **dynamic attribute creation**, but this is rarely ideal. +# * `__init__` is the **correct and safe** way to define an object’s state. +# * All instance data is stored in `instance.__dict__`. +# +# --- diff --git a/python/venv.ipynb b/python/venv.ipynb new file mode 100644 index 00000000..322c2359 --- /dev/null +++ b/python/venv.ipynb @@ -0,0 +1,68 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "e9e98dab", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Venv conspect file.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "368a45ba", + "metadata": {}, + "source": [ + "Что делает команда python -m venv venv?\n", + "#создаёт виртуальное окружение для питона\n", + "Что делает каждая команда в списке ниже?\n", + "#pip list - выведет список всех установленных пакетов в терминал\n", + "#pip freeze > requirements.txt - выгружет все пакеты и информацию о их версии в отдельный файл\n", + "#pip install -r requirements.txt - установит все пакеты их этого файла\n", + "Что делает каждая команда в списке ниже?\n", + "#conda env list - выведет список всех установленных окружений \n", + "#conda create -n env_name python=3.5 - создастся новая окружение с установленным интерпретатором питон версии 3.5\n", + "#conda env update -n env_name -f file.yml - conda прочитает этот файл(file.yml) и установит, обновит или удалит пакеты, чтобы текущее окружение соответствовало содержимому файла.\n", + "#source activate env_name - активирует окружение \n", + "#source deactivate - отключит окружение\n", + "#conda clean -a - помогает освободить место на диске, которое могло быть занято в процессе установки, обновления и удаления пакетов" + ] + }, + { + "cell_type": "markdown", + "id": "0a6ecda8", + "metadata": {}, + "source": [ + "Как установить необходимые пакеты внутрь виртуального окружения для conda/venv?\n", + "#через pip install\n", + "Что делают эти команды?\n", + "#pip freeze > requirements.txt - выгружает все установленные файлы в файл зависимостей \n", + "#conda env export > environment.yml - используется для сохранения текущего активного окружения Conda в файл environment.yml\n", + "Что делают эти команды?\n", + "#pip install -r requirements.txt - устанавливает пакеты из файла зависимостей\n", + "#conda env create -f environment.yml. - создаёт новое окружение конда с пакетами и установкаки как в файле конфигурации\n", + "Что делают эти команды?\n", + "#pip list - список установленных пакетов\n", + "#pip show -\n", + "#conda list - список существующих окружение конда\n", + "Где по умолчанию больше пакетов venv/pip или conda? и почему дата сайнинисты используют conda?\n", + "#в конда больше предустановленных пакетов именно для дата сайенс поэтому она более широко популярна \n", + "вставьте скрин где будет видно, Выбор интерпретатора Python (conda) в VS Code/cursor\n", + "#\n", + "Зачем нужно виртуально окружение?\n", + "#чтобы не засорять железу с ненужными пакетами и файлами а установить поработать и удалить или отключить \n", + "С этого момента надо работать в виртуальном окружении conda, ты научился(-ась) выгружать зависимости и работать с окружением?\n", + "#да\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/venv.py b/python/venv.py new file mode 100644 index 00000000..07200fa3 --- /dev/null +++ b/python/venv.py @@ -0,0 +1,37 @@ +"""Venv conspect file.""" + +# Что делает команда python -m venv venv? +# #создаёт виртуальное окружение для питона +# Что делает каждая команда в списке ниже? +# #pip list - выведет список всех установленных пакетов в терминал +# #pip freeze > requirements.txt - выгружет все пакеты и информацию о их версии в отдельный файл +# #pip install -r requirements.txt - установит все пакеты их этого файла +# Что делает каждая команда в списке ниже? +# #conda env list - выведет список всех установленных окружений +# #conda create -n env_name python=3.5 - создастся новая окружение с установленным интерпретатором питон версии 3.5 +# #conda env update -n env_name -f file.yml - conda прочитает этот файл(file.yml) и установит, обновит или удалит пакеты, чтобы текущее окружение соответствовало содержимому файла. +# #source activate env_name - активирует окружение +# #source deactivate - отключит окружение +# #conda clean -a - помогает освободить место на диске, которое могло быть занято в процессе установки, обновления и удаления пакетов + +# Как установить необходимые пакеты внутрь виртуального окружения для conda/venv? +# #через pip install +# Что делают эти команды? +# #pip freeze > requirements.txt - выгружает все установленные файлы в файл зависимостей +# #conda env export > environment.yml - используется для сохранения текущего активного окружения Conda в файл environment.yml +# Что делают эти команды? +# #pip install -r requirements.txt - устанавливает пакеты из файла зависимостей +# #conda env create -f environment.yml. - создаёт новое окружение конда с пакетами и установкаки как в файле конфигурации +# Что делают эти команды? +# #pip list - список установленных пакетов +# #pip show - +# #conda list - список существующих окружение конда +# Где по умолчанию больше пакетов venv/pip или conda? и почему дата сайнинисты используют conda? +# #в конда больше предустановленных пакетов именно для дата сайенс поэтому она более широко популярна +# вставьте скрин где будет видно, Выбор интерпретатора Python (conda) в VS Code/cursor +# # +# Зачем нужно виртуально окружение? +# #чтобы не засорять железу с ненужными пакетами и файлами а установить поработать и удалить или отключить +# С этого момента надо работать в виртуальном окружении conda, ты научился(-ась) выгружать зависимости и работать с окружением? +# #да +#