From f7f6de1eca9588c1717ce21fa78d18d5f0eb52fb Mon Sep 17 00:00:00 2001 From: Dmitry Medvedev Date: Fri, 9 Oct 2026 00:37:26 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=94=D0=97=20=D0=BF=D0=BE=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=8F=D0=B5=D0=BC=D1=8B=D0=BC=20=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D1=8F=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?=D0=BC=20=D1=82=D0=B8=D0=BF=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../12.mutable_and_immutable_types.ipynb | 311 ++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 dmedvedev/python/12.mutable_and_immutable_types.ipynb diff --git a/dmedvedev/python/12.mutable_and_immutable_types.ipynb b/dmedvedev/python/12.mutable_and_immutable_types.ipynb new file mode 100644 index 0000000..2cbf860 --- /dev/null +++ b/dmedvedev/python/12.mutable_and_immutable_types.ipynb @@ -0,0 +1,311 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ad33a980", + "metadata": {}, + "source": [ + "Задача 1. Две переменные — один список\n", + "Есть список колонок:\n", + "columns= [\"id\",\"event_time\",\"amount\"]\n", + "Нужно:\n", + " создать переменную columns_for_export и присвоить ей columns;\n", + " добавить в columns_for_export колонку \"load_dt\";\n", + " вывести:\n", + " columns\n", + " columns_for_export" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f5d2c49a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['id', 'event_time', 'amount', 'load_dt']\n", + "['id', 'event_time', 'amount', 'load_dt']\n" + ] + } + ], + "source": [ + "columns = [\"id\",\"event_time\",\"amount\"]\n", + "columns_for_expert = columns\n", + "columns_for_expert.append(\"load_dt\")\n", + "print(columns)\n", + "print(columns_for_expert)" + ] + }, + { + "cell_type": "markdown", + "id": "e3cc1bdb", + "metadata": {}, + "source": [ + "почему изменились обе переменные: обе переменные изменились потому что мы используем изменяемую переменную списка - list, данная переменная изменяемая и columns_for_expert ссылается на columns, сами переменные это не переменные, а указатели на них в памяти, поэтому если изменить одну, то и вторая поменяется\n", + "\n", + "какой тип здесь используется: используется список list\n", + "\n", + "он изменяемый или неизменяемый: изменяемый" + ] + }, + { + "cell_type": "markdown", + "id": "1422c7e6", + "metadata": {}, + "source": [ + "Задача 2. Строка и список — разное поведение\n", + "Есть переменные:\n", + " table_name=\"orders\"\n", + " metrics= [\"rows\",\"errors\",\"duration\"]\n", + "Нужно:\n", + " создать table_name_copy = table_name;\n", + " создать metrics_copy = metrics;\n", + " к table_name добавить строку \"_raw\";\n", + " в metrics_copy добавить элемент \"latency\";\n", + "вывести все 4 переменные:\n", + " table_name\n", + " table_name_copy\n", + " metrics\n", + " metrics_copy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7acdbe0d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "orders_raws\n", + "orders\n", + "['rows', 'errors', 'duration', 'latency']\n", + "['rows', 'errors', 'duration', 'latency']\n" + ] + } + ], + "source": [ + "table_name = \"orders\"\n", + "metrics = [\"rows\",\"errors\",\"duration\"]\n", + "table_name_copy = table_name\n", + "metrics_copy = metrics\n", + "table_name = (\"orders\" + \"_raws\")\n", + "metrics_copy.append(\"latency\")\n", + "print(table_name)\n", + "print(table_name_copy)\n", + "print(metrics)\n", + "print(metrics_copy)" + ] + }, + { + "cell_type": "markdown", + "id": "ade754e4", + "metadata": {}, + "source": [ + "почему строка изменилась не так, как список: потому что строка в данном случае это переменная и это неизменяемый тип данных, каждая переменная хранится в одной ячейке памяти и получается, что у нас две переменные и каждая хранится по отдельности, в отличие от списка, который в данном случае хранится как указатель на ячейку в памяти и изменение одного списка порождает изменение и в другом, так как это одна и та же ячейка в памяти\n", + "\n", + "какой объект оказался неизменяемым: строка\n", + "\n", + "какой объект оказался изменяемым: список" + ] + }, + { + "cell_type": "markdown", + "id": "07e7c0e3", + "metadata": {}, + "source": [ + "Задача 3. Словарь конфигурации пайплайна\n", + "Есть конфиг:\n", + "pipeline_config= {\n", + "\"source\":\"postgres\",\n", + "\"target\":\"s3\",\n", + "\"batch_size\":1000\n", + "}\n", + "Нужно:\n", + " создать current_config = pipeline_config;\n", + " изменить в current_config значение batch_size на 5000;\n", + " добавить ключ \"mode\" со значением \"append\";\n", + " вывести:\n", + " pipeline_config\n", + " current_config" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9b4fb54b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'source': 'postgres', 'target': 's3', 'batch_size': '5000', 'mode': 'append'}\n", + "{'source': 'postgres', 'target': 's3', 'batch_size': '5000', 'mode': 'append'}\n" + ] + } + ], + "source": [ + "pipeline_config = {\n", + " \"source\":\"postgres\",\n", + " \"target\":\"s3\",\n", + " \"batch_size\":1000\n", + "}\n", + "current_config = pipeline_config\n", + "current_config[\"batch_size\"] = \"5000\"\n", + "current_config[\"mode\"] = \"append\"\n", + "print(pipeline_config)\n", + "print(current_config)" + ] + }, + { + "cell_type": "markdown", + "id": "d41c940e", + "metadata": {}, + "source": [ + "почему исходный словарь тоже изменился: потому что словарь это изменяемый тип данных и когда мы его записываем в переменную, то он лишь хранится в виде указателя на ячейку памяти, соответственно, когда мы присваиваем другой переменной этот же словарь, то он ссылкается на ту же ячейку в памяти и любое изменение того или иного словаря влечет изменение и другого словаря\n", + "\n", + "является ли словарь изменяемым типом: да, является\n", + "\n", + "чем это может быть опасно в ETL-задачах: тем что если мы например захотим как-то проанализировать данные и например добавим какую-то колонку, то соответственно эта колонка появится в обоих словарях, что может привести к ошибкам или искажениям данных, поэтому необходимо при такой работе создавать копию словаря, чтобы оставить исходный словарь без изменений" + ] + }, + { + "cell_type": "markdown", + "id": "7af4f14d", + "metadata": {}, + "source": [ + "Задача 4. Функция меняет исходные данные\n", + "Есть список статусов:\n", + "statuses= [\"new\",\"validated\",\"loaded\"]\n", + "\n", + "Нужно:\n", + " вывести список до изменений;\n", + " заменить первый элемент на \"processed\";\n", + " добавить в конец \"archived\";\n", + " вывести список после изменений.\n", + "Требования:\n", + " использовать обращение по индексу;\n", + " использовать append();\n", + " вывести список до и после изменений." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5344d3d5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['new', 'validated', 'loaded']\n", + "['processed', 'validated', 'loaded', 'archived']\n" + ] + } + ], + "source": [ + "statuses = [\"new\",\"validated\",\"loaded\"]\n", + "print(statuses)\n", + "statuses[0] = \"processed\"\n", + "statuses.append(\"archived\")\n", + "print(statuses)" + ] + }, + { + "cell_type": "markdown", + "id": "a276419e", + "metadata": {}, + "source": [ + "почему список изменился: список это изменяемый тип данных и его можно менять. когда мы изменили значение и добавили новое , то список изменяется внутри ячейки памяти\n", + "\n", + "какой элемент был заменён: самый первый\n", + "\n", + "какой элемент был добавлен: самый последний - \"archived\"" + ] + }, + { + "cell_type": "markdown", + "id": "5ea9f452", + "metadata": {}, + "source": [ + "Задача 5. Подготовка списка колонок без порчи исходника\n", + "Есть список:\n", + " raw_columns= [\"id\",\"user_id\",\"price\"]\n", + "Нужно подготовить список для витрины:\n", + " в новый список добавить \"load_dt\";\n", + " в новый список добавить \"source_name\".\n", + "Но при этом исходный raw_columns менять нельзя.\n", + "Что нужно сделать:\n", + " создать новый список mart_columns;\n", + " добавить в него новые поля;\n", + " вывести:\n", + " raw_columns\n", + " mart_columns" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "3e4dbd80", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['id', 'user_id', 'price']\n", + "['id', 'user_id', 'price', 'load_dt', 'source_name']\n" + ] + } + ], + "source": [ + "raw_columns = [\"id\",\"user_id\",\"price\"]\n", + "mart_columns = raw_columns.copy()\n", + "mart_columns.append(\"load_dt\")\n", + "mart_columns.append(\"source_name\")\n", + "print(raw_columns)\n", + "print(mart_columns)" + ] + }, + { + "cell_type": "markdown", + "id": "bd0f9b9c", + "metadata": {}, + "source": [ + "почему нельзя просто написать mart_columns = raw_columns: потому что в таком случае оба списка будут ссылаться на одну ячейку памяти и изменение одно из списков в таком случае влечет изменение второго\n", + "\n", + "что произойдёт, если потом изменить mart_columns: если мы напишем mart_columns = raw_columns, то оба списка изменятся, это нам не нужно\n", + "\n", + "почему в DE важно не портить исходные структуры: потому что это может вызвать ошибку или исказить анализ данных" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}