{ "cells": [ { "cell_type": "markdown", "id": "a6651c01", "metadata": {}, "source": [ "--- \n", " \n", "\n", "

Department of Data Science

\n", "

Course: Tools and Techniques for Data Science

\n", "\n", "---\n", "

Instructor: Muhammad Arif Butt, Ph.D.

" ] }, { "cell_type": "markdown", "id": "a363bc39", "metadata": {}, "source": [ "

Lecture 2.8

" ] }, { "cell_type": "markdown", "id": "2003ae68", "metadata": {}, "source": [ "\"Open" ] }, { "cell_type": "markdown", "id": "95de41a5", "metadata": {}, "source": [ "## _Python-Dictionaries.ipynb_\n", "#### [Click me to learn more about Python Dictionaries](https://www.geeksforgeeks.org/python-dictionary/)" ] }, { "cell_type": "markdown", "id": "3594553d", "metadata": {}, "source": [ " " ] }, { "cell_type": "markdown", "id": "68ab91ba", "metadata": {}, "source": [ "- A Dictionary object is created by placing comma separated `key:value` pairs in curly braces.\n", "- The keys of a dictionary has to be unique and can be of heterogeneous immutable types only (int, string or tuple).\n", "- The values can be duplicated and can be of heterogeneous types (mutable + immutable).\n", "- From Python version 3.7 onwards, dictionaries are ordered, however, are not indexed like Lists rather indexed on key values.\n", "- The dictionaries are used when you have to store million of `key:value` pairs and want to search a value given the key efficiently." ] }, { "cell_type": "markdown", "id": "7c109b0c", "metadata": {}, "source": [ "## Learning agenda of this notebook\n", "* **Motivation to use Dictionary**\n", "1. How to create dictionaries?\n", "2. Proof of concepts\n", "3. Accessing elements of a dictionary\n", "4. Adding/Modifying elements of a dictionary\n", "5. Removing elements from a dictionary\n", "6. Dictionary, tuple and list conversions\n", "7. Sorting Dictionary values\n", "8. Aliasing vs Shallow Copy vs Deep Copy" ] }, { "cell_type": "code", "execution_count": 1, "id": "20690d1d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class dict in module builtins:\n", "\n", "class dict(object)\n", " | dict() -> new empty dictionary\n", " | dict(mapping) -> new dictionary initialized from a mapping object's\n", " | (key, value) pairs\n", " | dict(iterable) -> new dictionary initialized as if via:\n", " | d = {}\n", " | for k, v in iterable:\n", " | d[k] = v\n", " | dict(**kwargs) -> new dictionary initialized with the name=value pairs\n", " | in the keyword argument list. For example: dict(one=1, two=2)\n", " | \n", " | Built-in subclasses:\n", " | StgDict\n", " | \n", " | Methods defined here:\n", " | \n", " | __contains__(self, key, /)\n", " | True if the dictionary has the specified key, else False.\n", " | \n", " | __delitem__(self, key, /)\n", " | Delete self[key].\n", " | \n", " | __eq__(self, value, /)\n", " | Return self==value.\n", " | \n", " | __ge__(self, value, /)\n", " | Return self>=value.\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\n", " | \n", " | __gt__(self, value, /)\n", " | Return self>value.\n", " | \n", " | __init__(self, /, *args, **kwargs)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __iter__(self, /)\n", " | Implement iter(self).\n", " | \n", " | __le__(self, value, /)\n", " | Return self<=value.\n", " | \n", " | __len__(self, /)\n", " | Return len(self).\n", " | \n", " | __lt__(self, value, /)\n", " | Return self size of D in memory, in bytes\n", " | \n", " | clear(...)\n", " | D.clear() -> None. Remove all items from D.\n", " | \n", " | copy(...)\n", " | D.copy() -> a shallow copy of D\n", " | \n", " | get(self, key, default=None, /)\n", " | Return the value for key if key is in the dictionary, else default.\n", " | \n", " | items(...)\n", " | D.items() -> a set-like object providing a view on D's items\n", " | \n", " | keys(...)\n", " | D.keys() -> a set-like object providing a view on D's keys\n", " | \n", " | pop(...)\n", " | D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n", " | If key is not found, d is returned if given, otherwise KeyError is raised\n", " | \n", " | popitem(self, /)\n", " | Remove and return a (key, value) pair as a 2-tuple.\n", " | \n", " | Pairs are returned in LIFO (last-in, first-out) order.\n", " | Raises KeyError if the dict is empty.\n", " | \n", " | setdefault(self, key, default=None, /)\n", " | Insert key with a value of default if key is not in the dictionary.\n", " | \n", " | Return the value for key if key is in the dictionary, else default.\n", " | \n", " | update(...)\n", " | D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n", " | If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]\n", " | If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v\n", " | In either case, this is followed by: for k in F: D[k] = F[k]\n", " | \n", " | values(...)\n", " | D.values() -> an object providing a view on D's values\n", " | \n", " | ----------------------------------------------------------------------\n", " | Class methods defined here:\n", " | \n", " | fromkeys(iterable, value=None, /) from builtins.type\n", " | Create a new dictionary with keys from iterable and values set to value.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Static methods defined here:\n", " | \n", " | __new__(*args, **kwargs) from builtins.type\n", " | Create and return a new object. See help(type) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __hash__ = None\n", "\n" ] } ], "source": [ "help(dict)" ] }, { "cell_type": "markdown", "id": "dbc7a471", "metadata": {}, "source": [ "## Motivation to use Dictionary" ] }, { "cell_type": "code", "execution_count": 2, "id": "6ca016ed", "metadata": {}, "outputs": [], "source": [ "students = ['rauf', 'arif', 'maaz', 'hadeed', 'mujahid']\n", "marks = [81, 52, 70, 74, 78]" ] }, { "cell_type": "code", "execution_count": 3, "id": "a0e0607c", "metadata": {}, "outputs": [], "source": [ "def get_marks(name):\n", " i = students.index(name)\n", " return marks[i]" ] }, { "cell_type": "code", "execution_count": 4, "id": "fa5142da", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "74" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_marks('hadeed')" ] }, { "cell_type": "code", "execution_count": 5, "id": "1c39967c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "70" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_marks('maaz')" ] }, { "cell_type": "markdown", "id": "78d11dc1", "metadata": {}, "source": [ "## 1. How to create Dictionaries?\n", "- A Dictionary object is created by placing comma separated `key:value` pairs in curly braces.\n", "- The keys of a dictionary has to be unique and can be of heterogeneous immutable types only (int, string or tuple).\n", "- The values can be duplicated and can be of heterogeneous types (mutable + immutable)." ] }, { "cell_type": "code", "execution_count": 6, "id": "88801cf7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'arif': 51, 'rauf': 52, 'hadeed': 22}\n", "\n", "140419669449344\n" ] } ], "source": [ "# A dictionary with string keys, and integer values, showing age of person\n", "dict1 = {\n", " 'arif':51, \n", " 'rauf':52, \n", " 'hadeed':22\n", "}\n", "print(dict1)\n", "print(type(dict1))\n", "print(id(dict1))" ] }, { "cell_type": "code", "execution_count": 7, "id": "4eaf7468", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{2580: 'var1', 2582: 'var2', 2586: 'var3'}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A dictionary with integer keys, and string values, showing a symbol table generated by compiler\n", "dict2 = {\n", " 2580:'var1', \n", " 2582:'var2', \n", " 2586:'var3'\n", "}\n", "dict2" ] }, { "cell_type": "code", "execution_count": 8, "id": "28246b4b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna', 1: 10, 'abc': 25, 33: 'xyz'}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# dictionary with mixed keys (immutable types only)\n", "dict3 = {\n", " 'name': 'kakamanna', \n", " 1: 10,\n", " 'abc':25,\n", " 33: 'xyz'\n", "}\n", "dict3" ] }, { "cell_type": "code", "execution_count": 9, "id": "2b837716", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: 'hello', 2: 'bye'}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# creating dictionary using dict() method\n", "dict4 = dict({1: 'hello', 2: 'bye'})\n", "dict4" ] }, { "cell_type": "code", "execution_count": 10, "id": "42a9682a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Creating an empty dictionary\n", "dict5 = dict()\n", "dict5" ] }, { "cell_type": "code", "execution_count": 11, "id": "e5aa7f0f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# other way to create empty dictionary\n", "dict6 = {}\n", "dict6" ] }, { "cell_type": "code", "execution_count": 12, "id": "82597fbb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'arif', 'age': 51, 'city': 'Lahore'}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A list of two object tuples can also be used to create dictionaries\n", "dict7 = dict([('name', 'arif'), ('age',51), ('city', 'Lahore')])\n", "dict7" ] }, { "cell_type": "markdown", "id": "d6ec8ad7", "metadata": {}, "source": [ "## 2. Proof of concepts" ] }, { "cell_type": "markdown", "id": "feba67cb", "metadata": {}, "source": [ "### a. Dictionary allows Duplicate Values" ] }, { "cell_type": "code", "execution_count": 13, "id": "36c560ea", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name1': 'kakamanna', 'name2': 'kakamanna'}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Duplicate values are allowed\n", "d1 = {'name1' : 'kakamanna',\n", " 'name2' : 'kakamanna'\n", " }\n", "d1" ] }, { "cell_type": "markdown", "id": "241ef2e0", "metadata": {}, "source": [ "### b. Dictionary DOESNOT allows Duplicate Keys" ] }, { "cell_type": "code", "execution_count": 14, "id": "873aa251", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'arif'}" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Duplicate keys are not allowed\n", "# This will not raise an error, but will overwrite the value corresponding to the key\n", "d1 = {'name' : 'kakamanna',\n", " 'name' : 'arif'\n", " }\n", "d1" ] }, { "cell_type": "markdown", "id": "37e2a7a2", "metadata": {}, "source": [ "### c. Keys inside Dictionaries Must be of Immutable data types\n", "- The keys of a dictionary has to be of immutable data type (number, string, tuple)" ] }, { "cell_type": "code", "execution_count": 15, "id": "f6c829c1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'kakamanna': 'name', (60, 78, 83): 'marks'}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Tuple being immutable can be used as a key\n", "d1 = {'kakamanna':'name', \n", " (60, 78, 83): 'marks' \n", " }\n", "d1" ] }, { "cell_type": "code", "execution_count": 16, "id": "fbcf6824", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unhashable type: 'list'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/1t/g3ylw8h50cjdqmk5d6jh1qmm0000gn/T/ipykernel_28173/357288203.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# List being mutable cannot be used as a key\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m d1 = {'kakamanna':'name', \n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m60\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m78\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m83\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m'marks'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m }\n\u001b[1;32m 5\u001b[0m \u001b[0md1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'" ] } ], "source": [ "# List being mutable cannot be used as a key\n", "d1 = {'kakamanna':'name', \n", " [60, 78, 83]:'marks' \n", " }\n", "d1" ] }, { "cell_type": "markdown", "id": "b6b79f18", "metadata": {}, "source": [ "### d. Values inside Dictionaies can be of mutable/immutable data type" ] }, { "cell_type": "code", "execution_count": 17, "id": "707b1982", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'nam': 'kakamanna', 'marks': [60, 78, 83]}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List being mutable can be used as a value\n", "d1 = {'nam':'kakamanna', \n", " 'marks':[60,78,83] \n", " }\n", "d1" ] }, { "cell_type": "code", "execution_count": 18, "id": "848acae1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'nam': 'kakamanna', 'marks': (60, 78, 83)}" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Tuple being immutable can also be used as a value\n", "d1 = {'nam':'kakamanna', \n", " 'marks': (60,78,83) \n", " }\n", "d1" ] }, { "cell_type": "markdown", "id": "b4736b44", "metadata": {}, "source": [ "### e. Dictionaries are heterogeneous\n", "- The keys of a dictionary can be of integer, string, or tuple type\n", "- The values of a dictionary can be of any data type" ] }, { "cell_type": "code", "execution_count": 19, "id": "554ca278", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna', 1: 10, 'abc': 25, 33: 'xyz'}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict3 = {\n", " 'name': 'kakamanna', \n", " 1: 10,\n", " 'abc':25,\n", " 33: 'xyz'\n", "}\n", "dict3" ] }, { "cell_type": "markdown", "id": "dd3c355e", "metadata": {}, "source": [ "### f. Dictionaries can be nested to arbitrary depth" ] }, { "cell_type": "code", "execution_count": 20, "id": "6b41d82a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'arif',\n", " 'occupation': 'teaching',\n", " 'address': {'house#': 131, 'area': 'model town', 'city': 'lahore'},\n", " 'phone': '03214456454'}" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Creating a Nested Dictionary\n", "dict7 = {'name':'arif', \n", " 'occupation':'teaching',\n", " 'address':{'house#' : 131, 'area' : 'model town', 'city' : 'lahore'},\n", " 'phone': '03214456454'\n", " }\n", " \n", "dict7" ] }, { "cell_type": "markdown", "id": "bdfb8c5d", "metadata": {}, "source": [ "### g. Dictionaries from Python 3.7 onward are ordered\n", "- From Python 3.7 onwards, dictionaries are guranteed to be in insertion ordered. i.e., every time you access dictionary elements they will show up in same sequence. \n", "- However, like string, list, and tuple, the elements of a dictionary are not associated by an index\n", "- Moreover, two dictionaries having same key-value pairs are two different objects" ] }, { "cell_type": "code", "execution_count": 21, "id": "f588c165", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(140419669239424, 140419668292416, 140419668418176)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = {\n", " 'arif':51, \n", " 'rauf':52, \n", " 'hadeed':20\n", "}\n", "d1\n", "d2 = {\n", " 'arif':51, \n", " 'rauf':52, \n", " 'hadeed':20\n", "}\n", "d2\n", "d3 = {\n", " 'rauf':52, \n", " 'hadeed':20,\n", " 'arif':51\n", "}\n", "id(d1), id(d2), id(d3)" ] }, { "cell_type": "markdown", "id": "11c05fb2", "metadata": {}, "source": [ "## 3. Accessing Elements of a Dictionary" ] }, { "cell_type": "markdown", "id": "f79228bc", "metadata": {}, "source": [ "### a. Retrieving a `value`of a Dictionary given a `key`\n", "- Given a key, you can retrieve corresponding value from a dictionary using two ways:\n", " - Use key inside `[]` operator\n", " - Pass the key as argument to `dict.get(key)` method" ] }, { "cell_type": "code", "execution_count": 22, "id": "af560a31", "metadata": {}, "outputs": [], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}" ] }, { "cell_type": "code", "execution_count": 23, "id": "06df71ad", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Johar Town'" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1['address']" ] }, { "cell_type": "code", "execution_count": 24, "id": "43c4a5ff", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[60, 75, 80]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.get('marks')" ] }, { "cell_type": "markdown", "id": "248a9a51", "metadata": {}, "source": [ "**To retrieve a value from a nested dictionary**" ] }, { "cell_type": "code", "execution_count": 25, "id": "c7bcc139", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'arif',\n", " 'occupation': 'teaching',\n", " 'address': {'house#': 131, 'area': 'model town', 'city': 'lahore'}}" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = {'name':'arif', \n", " 'occupation':'teaching',\n", " 'address':{'house#' : 131, \n", " 'area' : 'model town', \n", " 'city' : 'lahore'\n", " }\n", " }\n", "d2" ] }, { "cell_type": "code", "execution_count": 26, "id": "a08ce2d1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'house#': 131, 'area': 'model town', 'city': 'lahore'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2['address']" ] }, { "cell_type": "code", "execution_count": 27, "id": "3ffa6521", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'lahore'" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2['address']['city']" ] }, { "cell_type": "code", "execution_count": 28, "id": "61ead2f6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'house#': 131, 'area': 'model town', 'city': 'lahore'}" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2.get('address')" ] }, { "cell_type": "code", "execution_count": 29, "id": "7aea3ab9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'lahore'" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2.get('address').get('city')" ] }, { "cell_type": "markdown", "id": "46c467b5", "metadata": {}, "source": [ "### c. Retrieving all `key:value` pairs from a Dictionary using `dict.items()` method\n", "- The `dict.items()` method returns all the key-value pairs of a dictionary as a two object tuple" ] }, { "cell_type": "code", "execution_count": 30, "id": "f3b13815", "metadata": {}, "outputs": [], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}" ] }, { "cell_type": "code", "execution_count": 31, "id": "63929986", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_items([('name', 'kakamanna'), ('age', 22), ('address', 'Johar Town'), ('marks', [60, 75, 80])])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 = d1.items()\n", "l1" ] }, { "cell_type": "markdown", "id": "b1b75815", "metadata": {}, "source": [ "### d. Retrieving all `keys` of a Dictionary using `dict.keys()` method\n", "- The `dict.keys()` method returns all the keys of a dictionary object" ] }, { "cell_type": "code", "execution_count": 32, "id": "757ddbcd", "metadata": {}, "outputs": [], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}" ] }, { "cell_type": "code", "execution_count": 33, "id": "9a202981", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_keys(['name', 'age', 'address', 'marks'])" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.keys()" ] }, { "cell_type": "markdown", "id": "9bd002d9", "metadata": {}, "source": [ "### e. Retrieving all `values` from a Dictionary using `dict.values()` method\n", "- The `dict.values()` method returns all the values of a dict object\n", "- If a value occurs multiple times in the dictionary, it will appear that many times" ] }, { "cell_type": "code", "execution_count": 34, "id": "521ab72a", "metadata": {}, "outputs": [], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}" ] }, { "cell_type": "code", "execution_count": 35, "id": "7a1fc953", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_values(['kakamanna', 22, 'Johar Town', [60, 75, 80]])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.values()" ] }, { "cell_type": "markdown", "id": "c8bf8328", "metadata": {}, "source": [ "## 4. Adding/Modifying Elements of a Dictionary" ] }, { "cell_type": "markdown", "id": "b3baf5f7", "metadata": {}, "source": [ "### a. Adding/Modifying Elements using `[]` Operator\n", "- You can modify value associated with a key using `[]` operator and assignment statement\n", "```\n", "dict[key] = value\n", "```\n", "- If the key donot already exist, a new key:value is inserted in the dictionary" ] }, { "cell_type": "code", "execution_count": 36, "id": "ee36941b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a simple dictionary\n", "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 37, "id": "9ab55d28", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Model Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Modify value corresponding to an existing key\n", "d1['address'] = 'Model Town'\n", "d1" ] }, { "cell_type": "code", "execution_count": 38, "id": "eb507d6e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Model Town',\n", " 'marks': [60, 75, 80],\n", " 'key1': 'value1'}" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Adding a new key:value pair\n", "d1['key1'] = 'value1'\n", "d1" ] }, { "cell_type": "markdown", "id": "e40d6d74", "metadata": {}, "source": [ "### b. Modifying Elements using `d1.update()` method \n", "- The `d1.update()` method is used to update the value corresponding to an existing key inside the dictionary\n", "```\n", "dict.update(key:value)\n", "```\n", "- If the key donot already exist, a new key:value is inserted in the dictionary" ] }, { "cell_type": "code", "execution_count": 39, "id": "be36f778", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a simple dictionary\n", "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 40, "id": "4f7f5acf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'Arif Butt',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Modify value corresponding to an existing key\n", "d1.update({'name':'Arif Butt'})\n", "d1" ] }, { "cell_type": "code", "execution_count": 41, "id": "f4427151", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'Arif Butt',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80],\n", " 'key2': 'value2'}" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Adding a new key:value pair\n", "d1.update({'key2':'value2'})\n", "d1" ] }, { "cell_type": "markdown", "id": "202c78c0", "metadata": {}, "source": [ "**You can use the `dict.update()` method to merge two dictionaries**" ] }, { "cell_type": "code", "execution_count": 42, "id": "fbd84bff", "metadata": {}, "outputs": [], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", "}\n", "\n", "d2 = {\n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}" ] }, { "cell_type": "code", "execution_count": 43, "id": "21a4621f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.update(d2)\n", "d1" ] }, { "cell_type": "markdown", "id": "77a3ec17", "metadata": {}, "source": [ "## 5. Removing Elements from a Dictionary" ] }, { "cell_type": "markdown", "id": "bee8de58", "metadata": {}, "source": [ "### a. Removing Element using `[]` operator\n", "- To delete a dictionary element use the `del d1[key]` \n", "- To delete an entire dictionary from memory use `del d1` " ] }, { "cell_type": "code", "execution_count": 44, "id": "17874e8f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 45, "id": "d581d04d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna', 'address': 'Johar Town', 'marks': [60, 75, 80]}" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del d1['age']\n", "d1" ] }, { "cell_type": "code", "execution_count": 46, "id": "96f35fe3", "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'd1' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/1t/g3ylw8h50cjdqmk5d6jh1qmm0000gn/T/ipykernel_28173/1687696692.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m#this will delete the whole directory\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0md1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0md1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# will generate an error now\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'd1' is not defined" ] } ], "source": [ "#this will delete the whole directory\n", "del d1\n", "print(d1) # will generate an error now" ] }, { "cell_type": "markdown", "id": "689320ac", "metadata": {}, "source": [ "### b. Removing Element using `d1.popitem()` Method\n", "- The `d1.popitem()` removes and returns a (key,value) pair as a 2-tuple\n", "- Pairs are returned in LIFO order, i.e., last inserted element is returned\n", "- Raises KeyError if the dict is empty" ] }, { "cell_type": "code", "execution_count": 47, "id": "5be61226", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 48, "id": "0c4776fe", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('marks', [60, 75, 80])" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.popitem()" ] }, { "cell_type": "code", "execution_count": 49, "id": "aba9d471", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('address', 'Johar Town')" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.popitem()" ] }, { "cell_type": "code", "execution_count": 50, "id": "c089f60f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna', 'age': 22}" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1" ] }, { "cell_type": "markdown", "id": "a67d9031", "metadata": {}, "source": [ "### c. Removing Element using `d1.pop(key)` Method\n", "- The `d1.pop(key)` returns the value only of the key passed as its required argument\n", "- Moreover, the corresponding key-value pair is also removed from the dictionary\n", "- If key is not found a KeyError is raised" ] }, { "cell_type": "code", "execution_count": 51, "id": "2463a560", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 52, "id": "803ccb1b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'kakamanna'" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1.pop('name')" ] }, { "cell_type": "code", "execution_count": 53, "id": "1acdedb0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'age': 22, 'address': 'Johar Town', 'marks': [60, 75, 80]}" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1" ] }, { "cell_type": "code", "execution_count": 54, "id": "9c8bf117", "metadata": {}, "outputs": [], "source": [ "#d1.pop('nokey') #This will raise an error" ] }, { "cell_type": "markdown", "id": "f54b5f0b", "metadata": {}, "source": [ "### d. Removing Element using `d1.clear()` Method\n", "- The `d1.clear()` removes all items from the dictionary and returns None" ] }, { "cell_type": "code", "execution_count": 55, "id": "52892e03", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'kakamanna',\n", " 'age': 22,\n", " 'address': 'Johar Town',\n", " 'marks': [60, 75, 80]}" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1 = {\n", " 'name':'kakamanna', \n", " 'age':22, \n", " 'address':'Johar Town', \n", " 'marks':[60, 75, 80]\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 56, "id": "a3781586", "metadata": {}, "outputs": [], "source": [ "d1.clear()" ] }, { "cell_type": "code", "execution_count": 57, "id": "c2651f02", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{}" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d1" ] }, { "cell_type": "markdown", "id": "0f4dd1c2", "metadata": {}, "source": [ "## 6. Dictionary, Tuple and List conversions" ] }, { "cell_type": "code", "execution_count": 58, "id": "24e78729", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Name': 'Kakamanna',\n", " 'Sex': 'Male',\n", " 'Age': 23,\n", " 'Height': 6.1,\n", " 'Occupation': 'Student'}" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a simple dictionary for these operations\n", "d1 = {\n", " 'Name': 'Kakamanna', \n", " 'Sex': 'Male', \n", " 'Age': 23, \n", " 'Height': 6.1, \n", " 'Occupation': 'Student'\n", "}\n", "d1" ] }, { "cell_type": "code", "execution_count": 59, "id": "5f5ac187", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dict_items([('Name', 'Kakamanna'), ('Sex', 'Male'), ('Age', 23), ('Height', 6.1), ('Occupation', 'Student')])\n", "\n", " \n" ] } ], "source": [ "# The items() method, returns an object of dict_items containing two value tuples\n", "rv = d1.items()\n", "print(rv)\n", "print(\"\\n\", type(rv))" ] }, { "cell_type": "code", "execution_count": 60, "id": "26e3bf6b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(('Name', 'Kakamanna'), ('Sex', 'Male'), ('Age', 23), ('Height', 6.1), ('Occupation', 'Student'))\n", "\n", " \n" ] } ], "source": [ "# You can convert dictionary key-value pairs into a tuple containing two valued tuples\n", "t1 = tuple(d1.items())\n", "print(t1)\n", "print(\"\\n\", type(t1))" ] }, { "cell_type": "code", "execution_count": 61, "id": "6908b650", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Name', 'Sex', 'Age', 'Height', 'Occupation')\n", "\n", " \n" ] } ], "source": [ "#converting dictionary keys only into a tuple\n", "t1 = tuple(d1.keys())\n", "print(t1)\n", "print(\"\\n\", type(t1))" ] }, { "cell_type": "code", "execution_count": 62, "id": "a040924f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " ['Kakamanna', 'Male', 23, 6.1, 'Student']\n", "\n" ] } ], "source": [ "#converting dictionary values only into a list\n", "mylist = list(d1.values())\n", "print(\"\\n\", mylist)\n", "print(type(mylist))" ] }, { "cell_type": "markdown", "id": "af8f68ac", "metadata": {}, "source": [ "## 7. Sorting a Dictionary by Values\n", "- We can use the built-in function `sorted(iterable)` to get a sorted copy of a dictionary (by value). \n", "- The `sorted(iterable)` returns a sorted version of the iterable, without making any change to the iterable. \n", "- It's syntax is quite similar to `list.sort()` method, however, the iterator to be sorted needs to be passed as a required parameteras shown below:\n", "```\n", " sorted(iterable, key=None, reverse=False)\n", "```\n", "- By default the `reverse` argument is `False`, you override the default behavior by passing a `True` value to this argument to perform a descending sort\n", "- A custom key function can also be supplied to customize the sort order." ] }, { "cell_type": "markdown", "id": "81562a11", "metadata": {}, "source": [ "**Consider the following dictionary having `names` as keys and `marks` as values**" ] }, { "cell_type": "code", "execution_count": 63, "id": "0a29a9b7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'rauf': 81, 'arif': 90, 'maaz': 76, 'hadeed': 73, 'mujahid': 93}" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':76, \n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", "dict1" ] }, { "cell_type": "code", "execution_count": 64, "id": "37a29315", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['rauf', 'mujahid', 'maaz', 'hadeed', 'arif']" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(dict1, reverse=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "509de2b8", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "ec112673", "metadata": {}, "source": [ "**When you pass a dictionary object to the `sorted()` function, it will return the list of sorted dictionary keys**" ] }, { "cell_type": "code", "execution_count": 65, "id": "342246d7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['arif', 'hadeed', 'maaz', 'mujahid', 'rauf']" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = sorted(dict1)\n", "d2" ] }, { "cell_type": "markdown", "id": "1bad6321", "metadata": {}, "source": [ "**You can pass the keys only to the `sorted()` function, to do the above task**" ] }, { "cell_type": "code", "execution_count": 66, "id": "66df17d9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['arif', 'hadeed', 'maaz', 'mujahid', 'rauf']" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = sorted(dict1.keys())\n", "d2" ] }, { "cell_type": "markdown", "id": "30acac88", "metadata": {}, "source": [ "**Similarly you can pass the values only to the `sorted()` function, and it will return the list of sorted values**" ] }, { "cell_type": "code", "execution_count": 67, "id": "ae007f27", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[73, 76, 81, 90, 93]" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = sorted(dict1.values())\n", "d2" ] }, { "cell_type": "markdown", "id": "295bbb71", "metadata": {}, "source": [ "**Let us do customized sorting with Python Dictionaries**" ] }, { "cell_type": "markdown", "id": "53bf33d8", "metadata": {}, "source": [ "**Example 1: Suppose we have a dictionary containing student names along with their marks and we want to sort the dictionary by highest marks of the students first**" ] }, { "cell_type": "code", "execution_count": 1, "id": "89b0a8ab", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'rauf': 81, 'arif': 90, 'maaz': 76, 'hadeed': 73, 'mujahid': 93}" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':76, \n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", "dict1" ] }, { "cell_type": "code", "execution_count": null, "id": "77b05206", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 2, "id": "a0e128a4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('mujahid', 93), ('arif', 90), ('rauf', 81), ('maaz', 76), ('hadeed', 73)]\n" ] } ], "source": [ "# Function receives a key:value tuple (key, value) and returns the value\n", "def func1(item):\n", " return item[1]\n", "\n", "\n", "mylist = sorted(dict1.items(), key = func1, reverse=True)\n", "\n", "print(mylist)\n" ] }, { "cell_type": "markdown", "id": "ff2fc3e3", "metadata": {}, "source": [ "Note the `sorted()` function returned a list object in which each element is a two valued tuple having (key,value) pairs. You can always typecast such lists to a dictionary object" ] }, { "cell_type": "code", "execution_count": 70, "id": "5eb1c717", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'mujahid': 93, 'arif': 90, 'rauf': 81, 'maaz': 76, 'hadeed': 73}" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted_dict = dict(mylist)\n", "sorted_dict" ] }, { "cell_type": "code", "execution_count": 71, "id": "1bc663ac", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(sorted_dict)" ] }, { "cell_type": "code", "execution_count": null, "id": "ec95e260", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "6a575f97", "metadata": {}, "source": [ "**Example 2: Suppose we have a JSON array containing name, age and grades of students. We want to sort it by the age of the students.**\n", "- JSON stands for JavaScript Object Notation\n", "- JSON is a text format for storing and transporting data\n", "- A JSON string has comma separated `key:value` pairs" ] }, { "cell_type": "code", "execution_count": 72, "id": "25db9c4a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'name': 'Hashim', 'age': 18, 'grade': 'B'},\n", " {'name': 'Salman', 'age': 11, 'grade': 'A'},\n", " {'name': 'Mazhar', 'age': 12, 'grade': 'C'},\n", " {'name': 'Farhan', 'age': 22, 'grade': 'D'},\n", " {'name': 'Bilal', 'age': 19, 'grade': 'A'},\n", " {'name': 'Zalaid', 'age': 17, 'grade': 'B'}]" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The following JSON array defines a student object with 3 properties: `name`, `age`, and `grade`\n", "# It is actually a list containing dictionary objects each object containing three key:value pairs\n", "students = [\n", " {\"name\": \"Hashim\", \"age\": 18, \"grade\": \"B\"},\n", " {\"name\": \"Salman\", \"age\": 11, \"grade\": \"A\"},\n", " {\"name\": \"Mazhar\", \"age\": 12, \"grade\": \"C\"},\n", " {\"name\": \"Farhan\", \"age\": 22, \"grade\": \"D\"},\n", " {\"name\": \"Bilal\", \"age\": 19, \"grade\": \"A\"},\n", " {\"name\": \"Zalaid\", \"age\": 17, \"grade\": \"B\"}\n", " ]\n", "students" ] }, { "cell_type": "code", "execution_count": 73, "id": "b5f46b71", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'name': 'Salman', 'age': 11, 'grade': 'A'},\n", " {'name': 'Mazhar', 'age': 12, 'grade': 'C'},\n", " {'name': 'Zalaid', 'age': 17, 'grade': 'B'},\n", " {'name': 'Hashim', 'age': 18, 'grade': 'B'},\n", " {'name': 'Bilal', 'age': 19, 'grade': 'A'},\n", " {'name': 'Farhan', 'age': 22, 'grade': 'D'}]" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Function receives a dictionary object and returns the value corresponding to key age in that dictionary\n", "def func2(item):\n", " return item.get('age') #return item['age']\n", "\n", "sorted_students = sorted(students, key = func2)\n", "\n", "sorted_students" ] }, { "cell_type": "markdown", "id": "6e45acd9", "metadata": {}, "source": [ "Note the `sorted()` function returned a list object in which each element is a dictionary object having three key:value pairs" ] }, { "cell_type": "code", "execution_count": null, "id": "73bea17b", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "c0f4a519", "metadata": {}, "source": [ "## 8. Simple Assignment (aliasing) vs Shallow Copy vs Deep Copy" ] }, { "cell_type": "markdown", "id": "4aac33b0", "metadata": {}, "source": [ "### a. Aliasing: Making an Alias of a List object using simple Assignment `=` Operator\n", "- In Python, we use `=` operator to create a copy/alias of an object. \n", "- Remember it doesnot create a new object, rather creates a new variable that shares the reference of the original object." ] }, { "cell_type": "code", "execution_count": 74, "id": "17189b7d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of dict1: 140419669413952\n", "ID of dict2: 140419669413952\n" ] } ], "source": [ "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':76, \n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", "\n", "dict2 = dict1\n", "\n", "# Both references point to same memory object, so have the same ID\n", "print('ID of dict1:', id(dict1))\n", "print('ID of dict2:', id(dict2))" ] }, { "cell_type": "code", "execution_count": 75, "id": "7962e717", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "dict1: {'rauf': 81, 'arif': 90, 'maaz': 100, 'hadeed': 73, 'mujahid': 93}\n", "dict2: {'rauf': 81, 'arif': 90, 'maaz': 100, 'hadeed': 73, 'mujahid': 93}\n" ] } ], "source": [ "# If you modify an element of one object, the change will be visible in both\n", "dict2[\"maaz\"] = 100\n", "\n", "print('\\ndict1:', dict1)\n", "print('dict2:', dict2)\n" ] }, { "cell_type": "markdown", "id": "ae7c3184", "metadata": {}, "source": [ "### b. Shallow Copy\n", "- We have used the `copy.copy()` method of copy module to create a shallow copy of List objects in our previous session\n", "- To create a shallow copy of a list or dictionary, we can also use `copy()` method of List and Dictionary objects." ] }, { "cell_type": "code", "execution_count": 76, "id": "d09fb369", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of dict1: 140419640424064\n", "ID of dict2: 140419640545856\n" ] } ], "source": [ "import copy\n", "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':76, \n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", "\n", "#dict2 = copy.copy(dict1)\n", "dict2 = dict1.copy()\n", "\n", "\n", "# Both variables point to different memory objects, so have the different ID\n", "print('ID of dict1:', id(dict1))\n", "print('ID of dict2:', id(dict2))" ] }, { "cell_type": "code", "execution_count": 77, "id": "4095a88e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "dict1: {'rauf': 81, 'arif': 90, 'maaz': 76, 'hadeed': 73, 'mujahid': 93}\n", "dict2: {'rauf': 81, 'arif': 90, 'maaz': 100, 'hadeed': 73, 'mujahid': 93}\n" ] } ], "source": [ "# If you modify an element of one object, the change will NOT be visible in other\n", "dict2[\"maaz\"] = 100\n", "\n", "print('\\ndict1:', dict1)\n", "print('dict2:', dict2)\n" ] }, { "cell_type": "markdown", "id": "5d06c019", "metadata": {}, "source": [ "**This seems woking fine, then why this is called shallow copy**" ] }, { "cell_type": "markdown", "id": "bed7ee06", "metadata": {}, "source": [ "**Limitation of Shallow Copy**\n", "- The word Shallow copy comes in picture when there is some object in dictionary like list or user define objects instead of primitive datatypes.\n", "- The limitation of shallow copy is that it does not create a copy of nested objects, instead it just copies the reference of nested objects. This means, a copy process does not recurse or create copies of nested objects itself.\n", "- Let us understand this by an example" ] }, { "cell_type": "code", "execution_count": 78, "id": "be8025d4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of dict1: 140419668402752\n", "ID of dict2: 140419668423104\n" ] } ], "source": [ "import copy\n", "\n", "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':[55, 66, 77], #note we have a list of marks as a dictionary value\n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", " \n", "#dict2 = copy.copy(dict1)\n", "dict2 = dict1.copy()\n", "\n", "\n", "# Both variables point to different memory objects, so have the different ID\n", "print('ID of dict1:', id(dict1))\n", "print('ID of dict2:', id(dict2))" ] }, { "cell_type": "code", "execution_count": 79, "id": "44adc1ca", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "dict1: {'rauf': 81, 'arif': 90, 'maaz': [55, 0, 77], 'hadeed': 73, 'mujahid': 93}\n", "\n", "dict2: {'rauf': 81, 'arif': 90, 'maaz': [55, 0, 77], 'hadeed': 73, 'mujahid': 93}\n" ] } ], "source": [ "# If you modify a nested element of one object, the change will be visible in both\n", "# This is the limitation of shallow copy\n", "\n", "dict2[\"maaz\"][1] = 0\n", "\n", "print('\\ndict1:', dict1)\n", "print('\\ndict2:', dict2)\n" ] }, { "cell_type": "markdown", "id": "f24c4ad9", "metadata": {}, "source": [ "- **Marks of student 'maaz' has been changed in both :(**\n", "- **So in case of a dictionary having primitive datatypes, the shallow copy works fine. However, when we have nested objects inside the dictionary the shallow copy does not work**\n", "- **Lets solve this using deep copy**" ] }, { "cell_type": "markdown", "id": "fbf7c5a1", "metadata": {}, "source": [ "### c. Deep Copy: Making a Copy of an Object using `copy.deepcopy()` Method\n", "- Deep copy creates a new object and recursively creates independent copy of original object and all its nested objects." ] }, { "cell_type": "code", "execution_count": 80, "id": "5ffcd728", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of dict1: 140419640545856\n", "ID of dict2: 140419640435712\n" ] } ], "source": [ "import copy\n", "\n", "dict1 = {'rauf': 81, \n", " 'arif':90, \n", " 'maaz':[55, 66, 77], \n", " 'hadeed':73,\n", " 'mujahid':93, \n", " }\n", " \n", "dict2 = copy.deepcopy(dict1)\n", "\n", "# Both variables point to different memory objects, so have the different ID\n", "print('ID of dict1:', id(dict1))\n", "print('ID of dict2:', id(dict2))" ] }, { "cell_type": "code", "execution_count": 81, "id": "a6d9dee9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "dict1: {'rauf': 81, 'arif': 90, 'maaz': [55, 66, 77], 'hadeed': 73, 'mujahid': 93}\n", "\n", "dict2: {'rauf': 81, 'arif': 90, 'maaz': [55, 0, 77], 'hadeed': 73, 'mujahid': 93}\n" ] } ], "source": [ "# If you modify a nested element of one object, the change will be visible in other\n", "dict2[\"maaz\"][1] = 0\n", "\n", "print('\\ndict1:', dict1)\n", "print('\\ndict2:', dict2)\n" ] }, { "cell_type": "markdown", "id": "26a08d4c", "metadata": {}, "source": [ "# Visualize Python Code: https://pythontutor.com/" ] }, { "cell_type": "markdown", "id": "055bad4f", "metadata": {}, "source": [ "## Check your Concepts\n", "\n", "Try answering the following questions to test your understanding of the topics covered in this notebook:\n", "\n", "\n", "1. What is a dictionary in Python?\n", "2. How do you create a dictionary?\n", "3. What are keys and values?\n", "4. How do you access the value associated with a specific key in a dictionary?\n", "5. What happens if you try to access the value for a key that doesn't exist in a dictionary?\n", "6. What is the `.get` method of a dictionary used for?\n", "7. How do you change the value associated with a key in a dictionary?\n", "8. How do you add or remove a key-value pair in a dictionary?\n", "9. How do you access the keys, values, and key-value pairs within a dictionary?\n", "10.Describe/Differentiate the concept of aliasing, shallow copy and deep copy using assignment statement, `dict.copy()`, `copy.copy()` and `copy.deepcopy()` methods\n", "11.Practice sorting dictionaries having different types of `key:value` combinations" ] }, { "cell_type": "code", "execution_count": null, "id": "efc94f4a", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }