{ "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.5

" ] }, { "cell_type": "markdown", "id": "8c10be24", "metadata": {}, "source": [ "\"Open" ] }, { "cell_type": "markdown", "id": "95de41a5", "metadata": {}, "source": [ "## _Python-Lists.ipynb_\n", "#### [Click me to learn more about Python Lists](https://docs.python.org/3/tutorial/datastructures.html)" ] }, { "cell_type": "markdown", "id": "dc557a3b", "metadata": {}, "source": [ " " ] }, { "cell_type": "markdown", "id": "73411664", "metadata": {}, "source": [ " \n", "Lists in Python however, tend to be more flexible than arrays in other languages for a two good reasons: \n", "\n", "- They have no fixed size (meaning we don't have to specify how big a list will be).\n", "- They have no fixed type constraint." ] }, { "cell_type": "markdown", "id": "ee14dd7d", "metadata": {}, "source": [ "> **A List is a numerically ordered sequence of elements that can store elements of heterogeneous types, is iterable, mutable and allows duplicate elements.**" ] }, { "cell_type": "markdown", "id": "7c109b0c", "metadata": {}, "source": [ " \n", "\n", "\n", "\n", "## Learning agenda of this notebook\n", "* **Data Structures** are a particular way of organizing data in computer. A clever way of laying out your data to make sure the data does what you want it to do. Most of the variables types that we have studied so far (numbers and strings) have one value in them, when we put a new value in them the old value is overwritten.\n", "* **Collections** allows us to put many values in a single variable. Lists, Sets, Tuples, and Dictionaries are some types of Python collections\n", "* **Sequences** are collections of objects, however, each object in a sequence is assigned an index and the items of a sequence can be manipulated using its respective index. List and Tuples fall into this category.\n", "* Today we are going to talk about **Python Lists**, which is a collection of arbitrary objects, somewhat akin to an array in many other programming languages, but more flexible. Unlike strings, Lists are mutable, meaning the elements inside a list can be changed.\n", "\n", "1. How to create lists?\n", "2. Proof of concepts: Lists are heterogeneous, ordered, mutable, nested, and allow duplicate elements\n", "3. Different ways to access list elements\n", "4. Slicing Lists\n", "5. List concatenation and repetition\n", "6. Modifying/Adding elements to a List using `append()`, `extend()`, and `insert()` methods\n", "7. Removing elements from a list using `pop()` and `remove()` methods\n", "8. Converting string object to list and vice-versa (using type casting, `split()` and `join()`)\n", "9. Aliasing vs Shallow Copy vs Deep Copy\n", "10. Sorting a list and Custom sorting\n", "11. Misc Concepts" ] }, { "cell_type": "code", "execution_count": 1, "id": "588cc46d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class list in module builtins:\n", "\n", "class list(object)\n", " | list(iterable=(), /)\n", " | \n", " | Built-in mutable sequence.\n", " | \n", " | If no argument is given, the constructor creates a new empty list.\n", " | The argument must be an iterable if specified.\n", " | \n", " | Methods defined here:\n", " | \n", " | __add__(self, value, /)\n", " | Return self+value.\n", " | \n", " | __contains__(self, key, /)\n", " | Return key in self.\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", " | __iadd__(self, value, /)\n", " | Implement self+=value.\n", " | \n", " | __imul__(self, value, /)\n", " | Implement 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- **A Python List is a numerically ordered sequence of elements that can store multiple items of heterogeneous types and allows duplicate elements.**\n", ">- **A Python List can be created by placing comma separated values in square brackets.**" ] }, { "cell_type": "code", "execution_count": 2, "id": "88801cf7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5]\n", "[3.7, 6.5, 3.8, 7.95]\n", "['hello', 'this', 'F', 'good show']\n", "[True, False, True]\n", "[]\n", "\n" ] } ], "source": [ "# It allows us to store elements of different data types (number, boolean, string, list) in one container.\n", "\n", "list1 = [1,2,3,4,5] #list of integers\n", "print(list1)\n", "\n", "list2 = [3.7, 6.5, 3.8, 7.95 ] #list of floats\n", "print(list2)\n", "\n", "list3 = [\"hello\", \"this\", \"F\", \"good show\"] #list of strings\n", "print(list3)\n", "\n", "list4 = [True, False, True] #list of boolean\n", "print(list4)\n", "\n", "list5 = [] #this will create an empty list\n", "print(list5)\n", "\n", "print(type(list5))" ] }, { "cell_type": "code", "execution_count": 3, "id": "458957c8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Arif', 30, 5.5, [10, 'rauf']]\n" ] } ], "source": [ "# Nested list: list can also have another list as an item\n", "list1 = [\"Arif\", 30, 5.5, [10,'rauf']]\n", "print(list1)" ] }, { "cell_type": "code", "execution_count": 4, "id": "539f6d47", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n" ] } ], "source": [ "# we can create empty list\n", "empty_list = []\n", "print (empty_list)" ] }, { "cell_type": "code", "execution_count": 5, "id": "a11b5b3f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5]\n", "['Arif', 30, 5.5, [10, 'rauf']]\n", "[]\n" ] } ], "source": [ "#printing multiple lists\n", "list1 = [1,2,3,4,5]\n", "list2 = [\"Arif\", 30, 5.5, [10,'rauf']]\n", "empty_list = []\n", "\n", "print(list1, list2, empty_list, sep='\\n')" ] }, { "cell_type": "markdown", "id": "48f77dc4", "metadata": {}, "source": [ "## 2. Proof of concepts" ] }, { "cell_type": "markdown", "id": "d2c423a2", "metadata": {}, "source": [ "### a. Lists are heterogeneous\n", "- Lists are heterogeneous, as their elements/items can be of any data type" ] }, { "cell_type": "code", "execution_count": 6, "id": "e42284d8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "list1: ['Arif', 30, 5.5]\n" ] } ], "source": [ "list1 = [\"Arif\", 30, 5.5]\n", "print(\"list1: \", list1)" ] }, { "cell_type": "markdown", "id": "a9281ff0", "metadata": {}, "source": [ "### b. Lists are ordered\n", "- Lists are ordered means every element is associated by an index\n", "- Every time you access list elements they will show up in same sequence. \n", "- Moreover, two lists having same elements in different order are not same." ] }, { "cell_type": "code", "execution_count": 7, "id": "4d10cb93", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(140681132808768, 140681132808320, False, True)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = [1, 2, 3]\n", "y = [1, 2, 3]\n", "id(x), id(y), x is y, x==y" ] }, { "cell_type": "code", "execution_count": 8, "id": "291d292e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(140681142453440, 140681142415936, False, False)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = [1, 2, 3]\n", "b = [2, 3, 1]\n", "id(a), id(b), a is b, a == b" ] }, { "cell_type": "markdown", "id": "a4d31dd7", "metadata": {}, "source": [ "### c. Lists are mutable\n", "- We have seen in previous session that Strings are **immutable**, i.e., we cannot change the contents of a string, however, we can assign an entirely new string to a variable\n", "- List on the contrary are **mutable**, i.e., once a List object is created, you can change an element of the list using the index `[]` and assignment `=' operator" ] }, { "cell_type": "code", "execution_count": 9, "id": "3942c4a3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "numbers: [10, 20, 555, 40, 50]\n" ] } ], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers[2] = 555\n", "print(\"numbers: \", numbers)" ] }, { "cell_type": "markdown", "id": "f1271382", "metadata": {}, "source": [ "### d. Lists can have duplicate emements" ] }, { "cell_type": "code", "execution_count": 10, "id": "904f68ac", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Arif', 'Rauf', 'Hadeed', 'Arif', 'Mujahid']\n" ] } ], "source": [ "# lists allow duplicate elements\n", "names = ['Arif', 'Rauf', 'Hadeed', 'Arif', 'Mujahid']\n", "print(names)" ] }, { "cell_type": "markdown", "id": "1cbb9c99", "metadata": {}, "source": [ "### e. Lists can be nested to arbitrary depth\n", "- You can have list within list and that can be done to an arbitrary depth. You are only restricted to the available memory on your system" ] }, { "cell_type": "code", "execution_count": 11, "id": "de0ae65e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([1, 2, 3, [4, 5], [6, 7, 8, 9], 10, 11],\n", " [1, 2, 3, [4, 5, [6, 7, 8, [9, 10, 11]]]])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A list having two sub-lists within it\n", "a = [1,2,3,[4,5],[6,7,8,9],10,11]\n", "\n", "# A list having a sublist, which is further having a sublist and that again having a sublist\n", "b = [1,2,3,[4,5,[6,7,8,[9,10,11]]]]\n", "a, b" ] }, { "cell_type": "markdown", "id": "ca269402", "metadata": {}, "source": [ "### f. Packing and Unpacking Lists" ] }, { "cell_type": "code", "execution_count": 12, "id": "4fc9e430", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "learning with Arif\n", "\n" ] } ], "source": [ "# you can unpack list elements\n", "mylist = ['learning', 'is', 'fun', 'with', 'Arif']\n", "a, b, c, d, e = mylist # the number of variables on the left must match the number of elements in the list\n", "print (a, d, e)\n", "print(type(a))" ] }, { "cell_type": "code", "execution_count": 13, "id": "e994ce1b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['learning', 'is', 'fun', 'with', 'Arif']\n", "\n" ] } ], "source": [ "# you can pack individual elements to a list\n", "tuple1 = a,b,c,d,e\n", "mylist2 = list(tuple1)\n", "print(mylist2)\n", "print(type(mylist2))" ] }, { "cell_type": "code", "execution_count": 14, "id": "af507554", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tuple" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1 = a,b,c,d,e\n", "tuple1\n", "type(tuple1)" ] }, { "cell_type": "markdown", "id": "418db83b", "metadata": {}, "source": [ "## 3. Different ways to access elements of a list\n", "- Since Lists like Strings are of type sequence, and any element within a sequence can be accessed by entrying an index within square brackets. So naturally this must work for Lists as well\n", "- Similarly, if we want to find out the index of a specific item/element, we can use the `index()` method of List class" ] }, { "cell_type": "code", "execution_count": 15, "id": "d42c7653", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[10, 'rauf']\n", "i\n", "rauf\n" ] } ], "source": [ "#You can access elements of list using indexing which starts from zero\n", "list1 = [\"Arif\", 30, 5.5, [10,'rauf']]\n", "print(list1[3])\n", "\n", "#accessing Nested list element\n", "print(list1[0][2]) #accessing third element of string at index 0\n", "print(list1[3][1]) #accessing second element of Nested list" ] }, { "cell_type": "code", "execution_count": 16, "id": "b1f6cd69", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[10, 'rauf']\n", "5.5\n" ] } ], "source": [ "#Negative indexing starts looking at the list from the right hand side\n", "list1 = [\"Arif\", 30, 5.5, [10,'rauf']]\n", "print(list1[-1]) #accessing last element\n", "print(list1[-2]) #accessing second last element" ] }, { "cell_type": "code", "execution_count": 17, "id": "cf060c56", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function index:\n", "\n", "index(value, start=0, stop=9223372036854775807, /) method of builtins.list instance\n", " Return first index of value.\n", " \n", " Raises ValueError if the value is not present.\n", "\n" ] } ], "source": [ "help(list1.index)" ] }, { "cell_type": "code", "execution_count": 18, "id": "74898626", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "mylist: [27, 4.5, 'arif', 64, 'hadeed', 19, 'arif']\n" ] }, { "data": { "text/plain": [ "2" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# index(value) method is used when you know the list element and wants to get its index\n", "# index(value) method returns the index of the first matched item with its only argument\n", "mylist = [27, 4.5, 'arif', 64, 'hadeed', 19, 'arif']\n", "print(\"\\nmylist: \", mylist)\n", "mylist.index('arif')" ] }, { "cell_type": "markdown", "id": "c9517d91", "metadata": {}, "source": [ "## 4. Slicing Lists\n", "- Like anyother sequence object we can perform slicing with lists as well.\n", "- Slicing is the process of obtaining a portion of a list by using its indices.\n", "- Given a list, we can use the following template to slice it and obtain a sublist:\n", "```\n", "mylist[start:end:step]\n", "```\n", "\n", "- **start** is the index from where we want the sublist to start. If start is not provided, slicing starts from the beginning.\n", "- **end** is the index where we want our sublist to end (not inclusive in the sublist). If end is not provided, slicing goes till the last element of the list.\n", "- **step** is the step through which we want to skip elements in the list. The default step is 1, so we iterate through every element of the list." ] }, { "cell_type": "code", "execution_count": 19, "id": "35e2ee1a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1 = ['a','b','c','d','e','f','g','h','i']\n", "list1" ] }, { "cell_type": "code", "execution_count": 20, "id": "bf9edbdb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[::]" ] }, { "cell_type": "code", "execution_count": 21, "id": "7da08034", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['d', 'e', 'f', 'g', 'h', 'i']" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[3:]" ] }, { "cell_type": "code", "execution_count": 22, "id": "b0341f68", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['a', 'b', 'c', 'd']" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[:4]" ] }, { "cell_type": "code", "execution_count": 23, "id": "90138f70", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['c', 'd', 'e']" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[2:5]" ] }, { "cell_type": "code", "execution_count": 24, "id": "a88e461e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['a', 'b', 'c', 'd', 'e', 'f', 'g']" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[:-2]" ] }, { "cell_type": "code", "execution_count": 25, "id": "9fbfba37", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'i'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1[-1]" ] }, { "cell_type": "code", "execution_count": 26, "id": "ed3fa5a4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']\n", "['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']\n", "['a', 'c', 'e', 'g', 'i']\n", "['a', 'd', 'g']\n" ] } ], "source": [ "# Slicing by using strides\n", "list1 = ['a','b','c','d','e','f','g','h','i']\n", "print(list1[::]) # A default step of 1\n", "print(list1[::1]) # A step of 1\n", "print(list1[::2]) # A step of 2\n", "print(list1[::3]) # A step of 3" ] }, { "cell_type": "code", "execution_count": 27, "id": "2c0ff8ef", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']\n", "['f', 'e', 'd', 'c']\n", "[]\n", "['i', 'g', 'e', 'c', 'a']\n" ] } ], "source": [ "# Reverse slicing\n", "list1 = ['a','b','c','d','e','f','g','h','i']\n", "print(list1[::-1]) # Take 1 step back each time\n", "print(list1[5:1:-1]) # Take 1 step back each time\n", "#if start is less than end in case of a negative step, it will return empty string\n", "print(list1[2:10:-1])\n", "print(list1[::-2]) # Take 2 steps back" ] }, { "cell_type": "markdown", "id": "87ccae14", "metadata": {}, "source": [ "Here are some experiments you should try out:\n", "\n", "* Try setting one or both indices of the range are larger than the size of the list, e.g., `a_list[2:10]`\n", "* Try setting the start index of the range to be larger than the end index, e.g., `a_list[12:10]`\n", "* Try leaving out the start or end index of a range, e.g., `a_list[2:]` or `a_list[:5]`\n", "* Try using negative indices for the range, e.g., `a_list[-2:-5]` or `a_list[-5:-2]` (can you explain the results?)\n", "\n", "> The flexible and interactive nature of Jupyter notebooks makes them an excellent tool for learning and experimentation. If you are new to Python, you can resolve most questions as soon as they arise simply by typing the code into a cell and executing it. **Let your curiosity run wild, discover what Python is capable of and what it isn't!**" ] }, { "cell_type": "code", "execution_count": 13, "id": "470034d1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['a', 'd', 'g']\n", "['d', 'e', 'f']\n", "[]\n", "['i', 'h']\n" ] } ], "source": [ "list1 = ['a','b','c','d','e','f','g','h','i']\n", "\n", "print(list1[::3])\n", "print(list1[3:6])\n", "print(list1[2:8:-1])\n", "print(list1[-1:-3:-1])" ] }, { "cell_type": "markdown", "id": "8f109f45", "metadata": {}, "source": [ "## 5. List Concatenation and Repetition" ] }, { "cell_type": "markdown", "id": "6807e6b2", "metadata": {}, "source": [ "### a. Concatenating Lists\n", "- Like Strings, the `+` operator can be used to concatenate two or more lists" ] }, { "cell_type": "code", "execution_count": 28, "id": "5bf4db5d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([1, 2, 3], [1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5])" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Add some elements to the end of an existing list using concatenation operator\n", "a = [1,2,3]\n", "b = a + [4,5]\n", "# Add some elements to the beginning of an existing list using concatenation operator\n", "c = [0] + b\n", "a, b, c" ] }, { "cell_type": "code", "execution_count": 29, "id": "6106dde2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['fruits', 'bread', 'veggies', 'meat', 'spices', 'burger']\n" ] } ], "source": [ "# use + operator to concatenate two lists\n", "food_items1 = ['fruits', 'bread', 'veggies'] \n", "food_items2 = ['meat', 'spices', 'burger']\n", "food = food_items1 + food_items2\n", "print(food)" ] }, { "cell_type": "code", "execution_count": 30, "id": "92843c21", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 3.4, 'hello', 31, 9.7, 'bye']\n" ] } ], "source": [ "# You can concatenate two heterogeneous lists\n", "list1 = [5, 3.4, 'hello']\n", "list2 = [31, 9.7, 'bye']\n", "list3 = list1 + list2\n", "print(list3)" ] }, { "cell_type": "code", "execution_count": 31, "id": "7085ad9c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5, 6, [7, 8]]\n" ] } ], "source": [ "num1 = [1,2,3]\n", "num2 = num1 + [4, 5, 6, [7, 8]]\n", "print (num2)" ] }, { "cell_type": "markdown", "id": "75f6b199", "metadata": {}, "source": [ "### b. Replicating Lists\n", "- Like Strings, the `*` operator can be used to repeat or replicate a list multiple times" ] }, { "cell_type": "code", "execution_count": 32, "id": "d4208107", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Arif', 'Hadeed', 'Mujahid', 'Arif', 'Hadeed', 'Mujahid', 'Arif', 'Hadeed', 'Mujahid']\n" ] } ], "source": [ "# use list * n syntax to create large lists by repeating the list n times\n", "name = ['Arif', 'Hadeed', 'Mujahid']\n", "a = name * 3\n", "print(a)" ] }, { "cell_type": "code", "execution_count": 33, "id": "f1dd57af", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A']\n" ] } ], "source": [ "#list of 100 A's\n", "buf = ['A']\n", "newbuf = buf * 100\n", "print(newbuf)" ] }, { "cell_type": "markdown", "id": "0557d8ff", "metadata": {}, "source": [ "## 6. Modifying/Adding elements to a list\n", "\n", "- We have worked on different methods of String class in our previous session. Similarly there are several built-in methods of the List class. \n", "> **Remember, unlike String methods, most methods of List class modify the original List rather than returning a new one.**\n", "- Lists are dynamic, as we write our Python program, we can actually make changes to our already created list, whithout having to go for compiling it again. \n", "- If we have to add certain elements to an already created list, the original list gorws dynamically without the need of compiling/running the program again (as in case of heap memory in C/C++)\n", "\n", "- We can use a list methods to perform various tasks on a list object and modify it. \n", "- Some list methods that can be used to alter a list are (append, insert, extend, remove, pop, clear, index, count, sort, reverse, split and join)\n", "- Check out some common list operations here: https://www.w3schools.com/python/python_ref_list.asp ." ] }, { "cell_type": "markdown", "id": "b533ec2b", "metadata": {}, "source": [ "### a. Modifying/Adding elements to a list using [ ] operator" ] }, { "cell_type": "code", "execution_count": 34, "id": "9a5ac824", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['data science', 'big data', 2, 5, 7]" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mylist = ['data science', 'machine learning', 2, 5, 7]\n", "# Let us change the second element of this list\n", "mylist[1] = 'big data'\n", "mylist" ] }, { "cell_type": "code", "execution_count": 35, "id": "b5f68e63", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['english', 'urdu', 2, 5, 7]" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can use the slice index to modify multiple list elements in one go\n", "mylist = ['data science', 'machine learning', 2, 5, 7]\n", "mylist[0:2] = ['english', 'urdu'] # Note we are replacing two elements with two elements\n", "mylist" ] }, { "cell_type": "code", "execution_count": 36, "id": "3355ee53", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['BIG DATA', 2, 5, 7]" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can replace more number of elements with lesser number of elements in a list\n", "mylist = ['data science', 'machine learning', 2, 5, 7]\n", "mylist[0:2] = ['BIG DATA'] # Note we are replacing two elements with one element\n", "mylist" ] }, { "cell_type": "code", "execution_count": 37, "id": "b7086b8e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[['math', 'stat'], 'machine learning', 2, 5, 7]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can replace one element with more number of elements in a list\n", "mylist = ['data science', 'machine learning', 2, 5, 7]\n", "mylist[0] = ['math', 'stat'] # Note we are replacing one element with two elements\n", "mylist" ] }, { "cell_type": "markdown", "id": "d5463e15", "metadata": {}, "source": [ "- Note the elements have been added, but as a sub-list. The first element 'data science' is replaced by a sub-list having two elements 'math' and 'stat'\n", "- If you want the elements to be individually placed in the list do as follows:" ] }, { "cell_type": "code", "execution_count": 38, "id": "3059975f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['math', 'stat', 'machine learning', 2, 5, 7]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mylist = ['data science', 'machine learning', 2, 5, 7]\n", "mylist[0:1] = ['math', 'stat'] # Note we using a slice instead of single index, although it means just zero\n", "mylist" ] }, { "cell_type": "markdown", "id": "2d39a79a", "metadata": {}, "source": [ "### b. Adding elements to a list using `list.append(value)` method\n", "- `list.append(value)` method is used when you want to add a single element at the end of the list\n", "- It is passed one argument which is the element to be inserted and returns none/void" ] }, { "cell_type": "code", "execution_count": 39, "id": "93aed67f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function append:\n", "\n", "append(object, /) method of builtins.list instance\n", " Append object to the end of the list.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.append)" ] }, { "cell_type": "code", "execution_count": 40, "id": "d35792db", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 4, 6, 8, 4.631, 'hello']" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1 = [2, 4, 6, 8]\n", "list1.append(4.631)\n", "list1.append('hello')\n", "list1" ] }, { "cell_type": "code", "execution_count": 41, "id": "ca6ca4be", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 4, 6, 8, [4.631, 'hello']]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# You cannot add multiple elements using append\n", "# If you try it will actually add those elements as a sub-list\n", "list1 = [2, 4, 6, 8]\n", "list1.append([4.631, 'hello'])\n", "list1" ] }, { "cell_type": "markdown", "id": "9d44e1ab", "metadata": {}, "source": [ "### c. Adding elements to a list using `list.extend(sublist)` method\n", "- `list.extend(sublist)` method is used when you want to add multiple elements at the end of the list\n", "- It is passed a list to be added at the end and returns none/void" ] }, { "cell_type": "code", "execution_count": 42, "id": "0e3b12b5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function extend:\n", "\n", "extend(iterable, /) method of builtins.list instance\n", " Extend list by appending elements from the iterable.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.extend)" ] }, { "cell_type": "code", "execution_count": 43, "id": "980f7c99", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 4, 6, 8, 4.631, 'hello']" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1 = [2, 4, 6, 8]\n", "list1.extend([4.631, 'hello'])\n", "list1" ] }, { "cell_type": "code", "execution_count": 44, "id": "1bdeaa24", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['apple', 'banana', 'cherry', 'potato', 'tomato', 'radish']" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# another example of extend()\n", "fruits = ['apple', 'banana', 'cherry']\n", "vegs = ['potato', 'tomato', 'radish']\n", "fruits.extend(vegs)\n", "fruits" ] }, { "cell_type": "markdown", "id": "971f9541", "metadata": {}, "source": [ "### d. Adding elements to a list using `list.insert(index, value)` method\n", "- `list.insert(index, value)` method is used when you want to add an element at a specific location in the list\n", "- It is passed index and value and returns none/void" ] }, { "cell_type": "code", "execution_count": 45, "id": "ec4b5b5e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function insert:\n", "\n", "insert(index, object, /) method of builtins.list instance\n", " Insert object before index.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.insert)" ] }, { "cell_type": "code", "execution_count": 46, "id": "4ca664fe", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original family list: ['Farooq', 'Rauf', 'Hadeed']\n", "After insert: ['Farooq', 'Rauf', 'Arif', 'Hadeed']\n" ] } ], "source": [ "myfamily = [\"Farooq\", 'Rauf', 'Hadeed']\n", "print(\"\\nOriginal family list: \", myfamily)\n", "myfamily.insert(2,'Arif')\n", "print(\"After insert: \", myfamily)" ] }, { "cell_type": "code", "execution_count": 47, "id": "7f06cee2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Farooq', 'Rauf', ['Maaz', 'Mohid'], 'Arif']" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# you can insert a sub-list\n", "myfamily = [\"Farooq\", 'Rauf', 'Arif']\n", "myfamily.insert(2,['Maaz','Mohid'])\n", "myfamily" ] }, { "cell_type": "markdown", "id": "ae40dd9e", "metadata": {}, "source": [ "## 7. Removing elements from a list using `list.pop()` and `list.remove()` methods\n", "- Lists are dynamic, as we write our Python program, we can actually make changes to our already created list, whithout having to go for compiling it again. \n", "- If we have to remove certain elements from an already created list, the original list shrinks dynamically without the need of compiling/running the program again (as in case of heap memory in C/C++)" ] }, { "cell_type": "markdown", "id": "237bc34d", "metadata": {}, "source": [ "### a. Removing element from a List using `list.pop(index)` method\n", "- The `list.pop()` method without any argument removes the last item (right most element) in the list and returns it\n", "- If given an argument/index, will remove that item from list whose index is given and returns it" ] }, { "cell_type": "code", "execution_count": 48, "id": "69e93d25", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function pop:\n", "\n", "pop(index=-1, /) method of builtins.list instance\n", " Remove and return item at index (default last).\n", " \n", " Raises IndexError if list is empty or index is out of range.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.pop)" ] }, { "cell_type": "code", "execution_count": 49, "id": "46064836", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original list: ['learning', 'is', 'fun', 'with', 'arif', 'butt']\n", "\n", "After pop(): ['learning', 'is', 'fun', 'with', 'arif']\n", "Element popped is: butt\n" ] } ], "source": [ "list1 = ['learning', 'is', 'fun', 'with', 'arif', 'butt']\n", "print(\"Original list: \", list1)\n", "x = list1.pop()\n", "print(\"\\nAfter pop(): \", list1)\n", "print(\"Element popped is: \", x)" ] }, { "cell_type": "code", "execution_count": 50, "id": "d8eb6450", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "After pop(2): ['learning', 'is', 'with', 'arif']\n", "Element popped is: fun\n" ] } ], "source": [ "y = list1.pop(2)\n", "print(\"\\nAfter pop(2): \", list1)\n", "print(\"Element popped is: \", y)" ] }, { "cell_type": "code", "execution_count": 51, "id": "117c82e8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "After pop(-2): ['learning', 'is', 'arif']\n", "Element popped is: with\n" ] } ], "source": [ "z = list1.pop(-2)\n", "print(\"\\nAfter pop(-2): \", list1)\n", "print(\"Element popped is: \", z)" ] }, { "cell_type": "markdown", "id": "6942dee3", "metadata": {}, "source": [ "### b. Removing element from a list using `list.remove(val)` method\n", "- The `list.remove(value)` method is used when you want to remove a specific element without returning it\n", "- It is passed exactly one argument, which is the value to be removed and returns none/void\n", "- In case of multiple occurrances, it removes the first occurrence of the element" ] }, { "cell_type": "code", "execution_count": 52, "id": "db0262b0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function remove:\n", "\n", "remove(value, /) method of builtins.list instance\n", " Remove first occurrence of value.\n", " \n", " Raises ValueError if the value is not present.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.remove)" ] }, { "cell_type": "code", "execution_count": 53, "id": "33f7704a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original list: ['learning', 'is', 'fun', 'with', 'arif', 'butt', 'fun']\n", "After remove('fun'): ['learning', 'is', 'with', 'arif', 'butt', 'fun']\n", "Return value of remove() is: None\n" ] } ], "source": [ "list2 = ['learning', 'is', 'fun', 'with', 'arif', 'butt', 'fun']\n", "print(\"\\nOriginal list: \", list2)\n", "\n", "x = list2.remove('fun')\n", "\n", "print(\"After remove('fun'): \", list2)\n", "print(\"Return value of remove() is: \", x)" ] }, { "cell_type": "markdown", "id": "ea9ea511", "metadata": {}, "source": [ "### c. Using `list.clear()` method to remove all the list elements" ] }, { "cell_type": "code", "execution_count": 54, "id": "e7860e12", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function clear:\n", "\n", "clear() method of builtins.list instance\n", " Remove all items from list.\n", "\n" ] } ], "source": [ "list1 = []\n", "help(list1.clear)" ] }, { "cell_type": "code", "execution_count": 55, "id": "db592559", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "After clear() the list becomes empty: []\n" ] } ], "source": [ "list2 = ['learning', 'is', 'fun', 'with', 'arif', 'butt']\n", "list2.clear()\n", "print(\"\\nAfter clear() the list becomes empty: \", list2)" ] }, { "cell_type": "markdown", "id": "2465dd24", "metadata": {}, "source": [ "### d. Using `del` Keyword to delete one or more list items or delete the list entirely from memory" ] }, { "cell_type": "code", "execution_count": 56, "id": "b29e2b9b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The \"del\" statement\n", "*******************\n", "\n", " del_stmt ::= \"del\" target_list\n", "\n", "Deletion is recursively defined very similar to the way assignment is\n", "defined. Rather than spelling it out in full details, here are some\n", "hints.\n", "\n", "Deletion of a target list recursively deletes each target, from left\n", "to right.\n", "\n", "Deletion of a name removes the binding of that name from the local or\n", "global namespace, depending on whether the name occurs in a \"global\"\n", "statement in the same code block. If the name is unbound, a\n", "\"NameError\" exception will be raised.\n", "\n", "Deletion of attribute references, subscriptions and slicings is passed\n", "to the primary object involved; deletion of a slicing is in general\n", "equivalent to assignment of an empty slice of the right type (but even\n", "this is determined by the sliced object).\n", "\n", "Changed in version 3.2: Previously it was illegal to delete a name\n", "from the local namespace if it occurs as a free variable in a nested\n", "block.\n", "\n", "Related help topics: BASICMETHODS\n", "\n" ] } ], "source": [ "help('del')" ] }, { "cell_type": "code", "execution_count": 57, "id": "113706e2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 7, 8, 9]" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# use del keyword to delete one or more list items by using index or to delete the list entirely from memory\n", "list3 = [1,2,3,4,5,6,7,8,9]\n", "del list3[3:6]\n", "list3" ] }, { "cell_type": "code", "execution_count": 58, "id": "a68c5550", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original list [1, 2, 3, [53, 41, 99, 12], 8, 9]\n", "After del list1[3] the list becomes [1, 2, 3, 8, 9]\n" ] } ], "source": [ "# use del keyword to delete one or more list items by using index or to delete the list entirely from memory\n", "list3 = [1,2,3,[53, 41, 99, 12], 8,9]\n", "print(\"\\nOriginal list\", list3)\n", "del list3[3]\n", "print(\"After del list1[3] the list becomes\", list3)" ] }, { "cell_type": "code", "execution_count": 59, "id": "e85aa8f0", "metadata": {}, "outputs": [], "source": [ "#to delete entire list\n", "mylist = ['learning', 'is', 'fun', 'with', 'arif', 'butt']\n", "del mylist\n", "#mylist" ] }, { "cell_type": "markdown", "id": "0f4dd1c2", "metadata": {}, "source": [ "## 8. Converting String object to List and vice-versa" ] }, { "cell_type": "markdown", "id": "9a54e2b3", "metadata": {}, "source": [ "### a. Type Casting" ] }, { "cell_type": "code", "execution_count": 60, "id": "98d157d3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original string: Learning is fun and its type is: \n", "l1: ['L', 'e', 'a', 'r', 'n', 'i', 'n', 'g', ' ', 'i', 's', ' ', 'f', 'u', 'n'] and its type is: \n" ] } ], "source": [ "# convert a string into list using list()\n", "str1 = 'Learning is fun' #this is a string\n", "print(type(str1))\n", "print(\"Original string: \", str1, \"and its type is: \", type(str1))\n", "l1 = list(str1)\n", "print(\"l1: \", l1, \"and its type is: \", type(l1))" ] }, { "cell_type": "markdown", "id": "f732b046", "metadata": {}, "source": [ "### b. Use `str.split()` to Split a List into Strings\n", "- Used to tokenize a string based on some delimiter, which can be stored in a list\n", "- It returns a list having tokens of the string based on spaces if no argument is passed" ] }, { "cell_type": "code", "execution_count": 61, "id": "8a95b4c3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function split:\n", "\n", "split(sep=None, maxsplit=-1) method of builtins.str instance\n", " Return a list of the words in the string, using sep as the delimiter string.\n", " \n", " sep\n", " The delimiter according which to split the string.\n", " None (the default value) means split according to any whitespace,\n", " and discard empty strings from the result.\n", " maxsplit\n", " Maximum number of splits to do.\n", " -1 (the default value) means no limit.\n", "\n" ] } ], "source": [ "str1 = \"\"\n", "help(str1.split)" ] }, { "cell_type": "code", "execution_count": 62, "id": "a220f31c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Learning', 'is', 'fun']" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "str1 = 'Learning is fun' #this is a string\n", "list1 = str1.split(' ')\n", "list1" ] }, { "cell_type": "code", "execution_count": 63, "id": "2bd45927", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Data S', 'ien', 'e is GR8 Degree']" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "str2 = \"Data Science is GR8 Degree\" #this is a string\n", "list2 = str2.split('c')\n", "list2" ] }, { "cell_type": "markdown", "id": "ab267a53", "metadata": {}, "source": [ "### c. Use `str.join()` to Join Strings into a List\n", "- It is the reverse of `str.split()` method, and is used to joing multiple strings by inserting the string in between on which this method is called" ] }, { "cell_type": "code", "execution_count": 64, "id": "642d6919", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function join:\n", "\n", "join(iterable, /) method of builtins.str instance\n", " Concatenate any number of strings.\n", " \n", " The string whose method is called is inserted in between each given string.\n", " The result is returned as a new string.\n", " \n", " Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'\n", "\n" ] } ], "source": [ "str1 = \"\"\n", "help(str1.join)" ] }, { "cell_type": "code", "execution_count": 65, "id": "bca2e103", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['This', 'is', 'getting', 'more', 'and', 'more', 'interesting']" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1 = ['This', 'is', 'getting', 'more', 'and', 'more', 'interesting']\n", "list1" ] }, { "cell_type": "code", "execution_count": 66, "id": "b20ac1f0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is getting more and more interesting\n", "\n" ] } ], "source": [ "str2 = ' '.join(list1)\n", "print(str2)\n", "print(type(str2))" ] }, { "cell_type": "code", "execution_count": 67, "id": "46b9611e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This # is # getting # more # and # more # interesting\n", "\n" ] } ], "source": [ "delimiter = \" # \"\n", "str3 = delimiter.join(list1)\n", "print(str3)\n", "print(type(str3))" ] }, { "cell_type": "markdown", "id": "1f006170", "metadata": {}, "source": [ "### d. Some Built-in Functions that can be used on Lists" ] }, { "cell_type": "code", "execution_count": 68, "id": "5c164642", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function len in module builtins:\n", "\n", "len(obj, /)\n", " Return the number of items in a container.\n", "\n" ] } ], "source": [ "help(len)" ] }, { "cell_type": "code", "execution_count": 69, "id": "93de6e51", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function max in module builtins:\n", "\n", "max(...)\n", " max(iterable, *[, default=obj, key=func]) -> value\n", " max(arg1, arg2, *args, *[, key=func]) -> value\n", " \n", " With a single iterable argument, return its biggest item. The\n", " default keyword-only argument specifies an object to return if\n", " the provided iterable is empty.\n", " With two or more arguments, return the largest argument.\n", "\n" ] } ], "source": [ "help(max)" ] }, { "cell_type": "code", "execution_count": 70, "id": "ec002dbc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function sum in module builtins:\n", "\n", "sum(iterable, /, start=0)\n", " Return the sum of a 'start' value (default: 0) plus an iterable of numbers\n", " \n", " When the iterable is empty, return the start value.\n", " This function is intended specifically for use with numeric values and may\n", " reject non-numeric types.\n", "\n" ] } ], "source": [ "help(sum)" ] }, { "cell_type": "code", "execution_count": 71, "id": "2f025aa2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "length of list: 7\n", "max element in list: 8\n", "min element in list: 0\n", "Sum of element in list: 30\n" ] } ], "source": [ "list_num = [3, 8, 1, 6, 0, 8, 4]\n", "\n", "print(\"length of list: \", len(list_num))\n", "print(\"max element in list: \", max(list_num))\n", "print(\"min element in list: \",min(list_num))\n", "print(\"Sum of element in list: \",sum(list_num))" ] }, { "cell_type": "markdown", "id": "c0711ea2", "metadata": {}, "source": [ "## 9. Simple Assignment (aliasing) vs Shallow Copy vs Deep Copy" ] }, { "cell_type": "markdown", "id": "6e1dca26", "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": 72, "id": "240b5fd8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of Old List: 140681144259456\n", "ID of New List: 140681144259456\n" ] } ], "source": [ "list1 = [1, 2, 3, 4]\n", "list2 = list1\n", "\n", "# Both variables point to same memory object, so have the same ID\n", "print('ID of Old List:', id(list1))\n", "print('ID of New List:', id(list2))" ] }, { "cell_type": "code", "execution_count": 73, "id": "dbeffafc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Old List: [1, 2, 9, 4]\n", "New List: [1, 2, 9, 4]\n" ] } ], "source": [ "# If you modify an element of one object, the change will be visible in both\n", "list2[2] = 9\n", "\n", "print('\\nOld List:', list1)\n", "print('New List:', list2)\n" ] }, { "cell_type": "markdown", "id": "cad05c14", "metadata": {}, "source": [ "### b. Shallow Copy\n", "- Shallow copy creates a new list object.\n", "- There are two ways of making a shallow copy\n", " - On the right hand side of `=` operator use slice operator\n", " - Use `copy.copy()` method" ] }, { "cell_type": "code", "execution_count": 1, "id": "c4cd07ea", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of Old List: 140428124989824\n", "ID of New List: 140428124140096\n" ] } ], "source": [ "# Shallow copy using slice operator while doing assignment\n", "list1 = [1, 2, 3, 4]\n", "list2 = list1[:]\n", "\n", "# Both variables point to different memory objects, so have the different ID\n", "print('ID of Old List:', id(list1))\n", "print('ID of New List:', id(list2))" ] }, { "cell_type": "code", "execution_count": 75, "id": "9f7d6f24", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Old List: [1, 2, 3, 4]\n", "New List: [1, 2, 9, 4]\n" ] } ], "source": [ "# If you modify an element of one object, the change will be not visible in both\n", "list2[2] = 9\n", "\n", "print('\\nOld List:', list1)\n", "print('New List:', list2)\n" ] }, { "cell_type": "code", "execution_count": 76, "id": "515cdade", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of Old List: 140681144262720\n", "ID of New List: 140681144264704\n" ] } ], "source": [ "# Shallow copy using the `copy.copy()` method\n", "import copy\n", "list1 = [1, 2, 3, 4]\n", "list2 = copy.copy(list1)\n", "\n", "# Both variables point to different memory objects, so have different ID\n", "print('ID of Old List:', id(list1))\n", "print('ID of New List:', id(list2))" ] }, { "cell_type": "code", "execution_count": 77, "id": "102d75a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Old List: [1, 2, 3, 4]\n", "New List: [1, 2, 3, 'a']\n" ] } ], "source": [ "# If you modify an element of one object, the change will not be visible in other\n", "list2[3] = 'a'\n", "\n", "print('\\nOld List:', list1)\n", "print('New List:', list2)\n" ] }, { "cell_type": "markdown", "id": "f4f3aeee", "metadata": {}, "source": [ "**This seems woking fine, then why this is called shallow copy**" ] }, { "cell_type": "code", "execution_count": null, "id": "7da0621a", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "6f8f42aa", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "3d514e79", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "c3ab2b99", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "8d1fef92", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "f6e57447", "metadata": {}, "source": [ "**Limitation of Shallow Copy**\n", "- Above examples seems fine. But shallow copy doesn't 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": "ba21558b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of Old List: 140681144288256\n", "ID of New List: 140681144288000\n" ] } ], "source": [ "import copy\n", "old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "new_list = copy.copy(old_list)\n", "\n", "# Both variables point to different memory object, having same references of original object elements\n", "print('ID of Old List:', id(old_list))\n", "print('ID of New List:', id(new_list))" ] }, { "cell_type": "code", "execution_count": 79, "id": "3a5cb6b1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Old List: [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]\n", "New List: [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]\n" ] } ], "source": [ "# If you modify an element of one object, the change will be visible in both\n", "new_list[2][2] = 'a'\n", "\n", "# See contents of both lists\n", "print('\\nOld List:', old_list)\n", "print('New List:', new_list)" ] }, { "cell_type": "markdown", "id": "47bab162", "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": "366b1fbd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID of Old List: 140681144290368\n", "ID of New List: 140681144289024\n" ] } ], "source": [ "import copy\n", "old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "new_list = copy.deepcopy(old_list)\n", "\n", "# Both variables point to different memory object, having their own object elements\n", "print('ID of Old List:', id(old_list))\n", "print('ID of New List:', id(new_list))\n" ] }, { "cell_type": "code", "execution_count": 81, "id": "638eb420", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Old List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "New List: [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]\n" ] } ], "source": [ "# If you modify an element of one object, the change will be made only to that object element\n", "new_list[2][2] = 'a'\n", "\n", "# See contents of both lists\n", "print('\\nOld List:', old_list)\n", "print('New List:', new_list)" ] }, { "cell_type": "markdown", "id": "4d074020", "metadata": {}, "source": [ "## 10. Sorting a List\n", "- You can use following three methods to sort list elements\n", " - The `list.sort()` method can sort the list elements (ascending + descending) on which it is called and returns None (modifies the list on which it is called).\n", " - The `list.reverse()` method simply reverse the list elements on which it is called and returns None (modifies the list on which it is called).\n", " - The `sorted(iterable)` is a built-in function, which returns a sorted version of the list, which is passed to it as parameter (list remains as it is). Limitation is it is a bit slow as it makes a copy of the list. Advantage is that it can sort any iterable." ] }, { "cell_type": "markdown", "id": "fbf88b2e", "metadata": {}, "source": [ "### a. The `list.sort()` method" ] }, { "cell_type": "code", "execution_count": 82, "id": "0ed8fe9d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original numbers list: [3, 8, 1, 6, 0, 8, 4]\n", "Ascending Sort: [0, 1, 3, 4, 6, 8, 8]\n", "Descending Sort: [8, 8, 6, 4, 3, 1, 0]\n" ] } ], "source": [ "# Modifies list on which it is called and returns none/void\n", "list_num = [3, 8, 1, 6, 0, 8, 4]\n", "print(\"Original numbers list: \", list_num)\n", "\n", "list_num.sort()\n", "print(\"Ascending Sort: \", list_num)\n", "\n", "list_num.sort(reverse=True)\n", "print(\"Descending Sort: \", list_num)\n" ] }, { "cell_type": "code", "execution_count": 83, "id": "dd1b54d4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original names list: ['XYZ', 'ABC', 'MNO', 'ARIF']\n", "Ascending Sort: ['ABC', 'ARIF', 'MNO', 'XYZ']\n", "Descending Sort: ['XYZ', 'MNO', 'ARIF', 'ABC']\n" ] } ], "source": [ "list_names = [\"XYZ\", \"ABC\", \"MNO\", \"ARIF\"]\n", "print(\"\\nOriginal names list: \", list_names)\n", "\n", "list_names.sort() \n", "print(\"Ascending Sort: \", list_names)\n", "\n", "list_names.sort(reverse=True) \n", "print(\"Descending Sort: \", list_names)" ] }, { "cell_type": "markdown", "id": "cdcb5387", "metadata": {}, "source": [ "### b. Custom Sorting using `list.sort()` Method" ] }, { "cell_type": "markdown", "id": "e03ac410", "metadata": {}, "source": [ "**Example 1: Suppose given a list with elements `['ccc', 'aaaaa', 'd', 'bb']` and I want to sort it by length of strings within the list so that the output list is like : `['d', 'bb', 'ccc', 'aaaaa]`**\n", "\n", "```\n", " list.sort(*, key=None, reverse=False)\n", "```\n", "- We write a one argument function, and pass that function to the `key` parameter of `list.sort()` method\n", "- The `list.sort()` method will run this one argument function on all the elements of the list and return a single value, and build up a shadow list of those new values. \n", "- Suppose the one argument function in this case is the Python built-in function `len()`, which when called on every element of `list1` will return a shadow list containing length of every string within the original list containing `[3,4,2,1]`\n", "- The `list1.sort()` method will then sort `list1` elements based on the values of the shadow list and generate the required sorted list :)" ] }, { "cell_type": "code", "execution_count": 84, "id": "d4015aa1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['aaaaa', 'bb', 'ccc', 'd']" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list1 = ['ccc', 'aaaaa', 'd', 'bb']\n", "list1.sort()\n", "list1" ] }, { "cell_type": "code", "execution_count": 85, "id": "ff103dab", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['d', 'bb', 'ccc', 'aaaaa']" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Example 1:\n", "list1 = ['ccc', 'aaaaa', 'd', 'bb']\n", "list1.sort(key=len)\n", "list1" ] }, { "cell_type": "markdown", "id": "e0a78fe8", "metadata": {}, "source": [ "**Example 2: Suppose given a list with elements `['abcz', 'xyza', 'bas', 'arif']` and I want to sort it by last character of strings within the list so that the output list is like : `['xyza', 'arif', 'bas', 'abcz']`**\n", "\n", "```\n", " list.sort(*, key=None, reverse=False)\n", "```\n", "- We write a one argument function, and pass that function to the `key` parameter of `list.sort()` method\n", "- The `list.sort()` method will run this one argument function on all the elements of the list and return a single value, and build up a shadow list of those new values. \n", "- This time the one argument function is a custom built function that receives a string and returns its last character. When called on every element of `list1` will return a shadow list containing only the last character of every string within the original list containing `['z', 'a', 's', 'f']`\n", "- The `list1.sort()` method will then sort `list1` elements based on the values of the shadow list and generate the required sorted list :)" ] }, { "cell_type": "code", "execution_count": 86, "id": "2587b323", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['xyza', 'arif', 'bas', 'abcz']" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def last(s):\n", " return s[-1]\n", "\n", "list1 = ['abcz', 'xyza', 'bas', 'arif']\n", "list1.sort(key=last)\n", "list1" ] }, { "cell_type": "markdown", "id": "ff517f2e", "metadata": {}, "source": [ "## 11. Misc Concepts" ] }, { "cell_type": "markdown", "id": "bcf5ab0d", "metadata": {}, "source": [ "### a. Use of `in` Operator on Lists" ] }, { "cell_type": "code", "execution_count": 87, "id": "62370b03", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Membership test operations\n", "**************************\n", "\n", "The operators \"in\" and \"not in\" test for membership. \"x in s\"\n", "evaluates to \"True\" if *x* is a member of *s*, and \"False\" otherwise.\n", "\"x not in s\" returns the negation of \"x in s\". All built-in sequences\n", "and set types support this as well as dictionary, for which \"in\" tests\n", "whether the dictionary has a given key. For container types such as\n", "list, tuple, set, frozenset, dict, or collections.deque, the\n", "expression \"x in y\" is equivalent to \"any(x is e or x == e for e in\n", "y)\".\n", "\n", "For the string and bytes types, \"x in y\" is \"True\" if and only if *x*\n", "is a substring of *y*. An equivalent test is \"y.find(x) != -1\".\n", "Empty strings are always considered to be a substring of any other\n", "string, so \"\"\" in \"abc\"\" will return \"True\".\n", "\n", "For user-defined classes which define the \"__contains__()\" method, \"x\n", "in y\" returns \"True\" if \"y.__contains__(x)\" returns a true value, and\n", "\"False\" otherwise.\n", "\n", "For user-defined classes which do not define \"__contains__()\" but do\n", "define \"__iter__()\", \"x in y\" is \"True\" if some value \"z\", for which\n", "the expression \"x is z or x == z\" is true, is produced while iterating\n", "over \"y\". If an exception is raised during the iteration, it is as if\n", "\"in\" raised that exception.\n", "\n", "Lastly, the old-style iteration protocol is tried: if a class defines\n", "\"__getitem__()\", \"x in y\" is \"True\" if and only if there is a non-\n", "negative integer index *i* such that \"x is y[i] or x == y[i]\", and no\n", "lower integer index raises the \"IndexError\" exception. (If any other\n", "exception is raised, it is as if \"in\" raised that exception).\n", "\n", "The operator \"not in\" is defined to have the inverse truth value of\n", "\"in\".\n", "\n", "Related help topics: SEQUENCEMETHODS\n", "\n" ] } ], "source": [ "help('in')" ] }, { "cell_type": "code", "execution_count": 88, "id": "fd3cd01d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n", "True\n" ] } ], "source": [ "list_num = [3, 8, 1, 6, 0, 8, 4]\n", "rv1 = 9 in list_num\n", "print(rv1)\n", "\n", "rv2 = 9 not in list_num\n", "print(rv2)\n", "\n", "\n", "list_names = [\"XYZ\", \"ABC\", \"MNO\", \"ARIF\"]\n", "rv3 = \"ARIF\" in list_names\n", "print(rv3)\n", "\n", "\n" ] }, { "cell_type": "markdown", "id": "57a57000", "metadata": {}, "source": [ "### b. Comparing objects and values" ] }, { "cell_type": "code", "execution_count": 89, "id": "1ebb5671", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function id in module builtins:\n", "\n", "id(obj, /)\n", " Return the identity of an object.\n", " \n", " This is guaranteed to be unique among simultaneously existing objects.\n", " (CPython uses the object's memory address.)\n", "\n" ] } ], "source": [ "help(id)" ] }, { "cell_type": "code", "execution_count": 90, "id": "5ba0e04b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(140681142371248, 140681142371248)" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# in case of strings, both a and b refers to the same memory location containing string 'hello'\n", "a = 'hello'\n", "b = 'hello'\n", "id(a), id(b)" ] }, { "cell_type": "code", "execution_count": 91, "id": "3442794f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(140681144288320, 140681104115968)" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# in case of list, both a and b refers to two different objects in the memory having same values\n", "x = ['hello']\n", "y = ['hello']\n", "id(x), id(y)" ] }, { "cell_type": "code", "execution_count": 92, "id": "63838cd6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Comparisons\n", "***********\n", "\n", "Unlike C, all comparison operations in Python have the same priority,\n", "which is lower than that of any arithmetic, shifting or bitwise\n", "operation. Also unlike C, expressions like \"a < b < c\" have the\n", "interpretation that is conventional in mathematics:\n", "\n", " comparison ::= or_expr (comp_operator or_expr)*\n", " comp_operator ::= \"<\" | \">\" | \"==\" | \">=\" | \"<=\" | \"!=\"\n", " | \"is\" [\"not\"] | [\"not\"] \"in\"\n", "\n", "Comparisons yield boolean values: \"True\" or \"False\".\n", "\n", "Comparisons can be chained arbitrarily, e.g., \"x < y <= z\" is\n", "equivalent to \"x < y and y <= z\", except that \"y\" is evaluated only\n", "once (but in both cases \"z\" is not evaluated at all when \"x < y\" is\n", "found to be false).\n", "\n", "Formally, if *a*, *b*, *c*, …, *y*, *z* are expressions and *op1*,\n", "*op2*, …, *opN* are comparison operators, then \"a op1 b op2 c ... y\n", "opN z\" is equivalent to \"a op1 b and b op2 c and ... y opN z\", except\n", "that each expression is evaluated at most once.\n", "\n", "Note that \"a op1 b op2 c\" doesn’t imply any kind of comparison between\n", "*a* and *c*, so that, e.g., \"x < y > z\" is perfectly legal (though\n", "perhaps not pretty).\n", "\n", "\n", "Value comparisons\n", "=================\n", "\n", "The operators \"<\", \">\", \"==\", \">=\", \"<=\", and \"!=\" compare the values\n", "of two objects. The objects do not need to have the same type.\n", "\n", "Chapter Objects, values and types states that objects have a value (in\n", "addition to type and identity). The value of an object is a rather\n", "abstract notion in Python: For example, there is no canonical access\n", "method for an object’s value. Also, there is no requirement that the\n", "value of an object should be constructed in a particular way, e.g.\n", "comprised of all its data attributes. Comparison operators implement a\n", "particular notion of what the value of an object is. One can think of\n", "them as defining the value of an object indirectly, by means of their\n", "comparison implementation.\n", "\n", "Because all types are (direct or indirect) subtypes of \"object\", they\n", "inherit the default comparison behavior from \"object\". Types can\n", "customize their comparison behavior by implementing *rich comparison\n", "methods* like \"__lt__()\", described in Basic customization.\n", "\n", "The default behavior for equality comparison (\"==\" and \"!=\") is based\n", "on the identity of the objects. Hence, equality comparison of\n", "instances with the same identity results in equality, and equality\n", "comparison of instances with different identities results in\n", "inequality. A motivation for this default behavior is the desire that\n", "all objects should be reflexive (i.e. \"x is y\" implies \"x == y\").\n", "\n", "A default order comparison (\"<\", \">\", \"<=\", and \">=\") is not provided;\n", "an attempt raises \"TypeError\". A motivation for this default behavior\n", "is the lack of a similar invariant as for equality.\n", "\n", "The behavior of the default equality comparison, that instances with\n", "different identities are always unequal, may be in contrast to what\n", "types will need that have a sensible definition of object value and\n", "value-based equality. Such types will need to customize their\n", "comparison behavior, and in fact, a number of built-in types have done\n", "that.\n", "\n", "The following list describes the comparison behavior of the most\n", "important built-in types.\n", "\n", "* Numbers of built-in numeric types (Numeric Types — int, float,\n", " complex) and of the standard library types \"fractions.Fraction\" and\n", " \"decimal.Decimal\" can be compared within and across their types,\n", " with the restriction that complex numbers do not support order\n", " comparison. Within the limits of the types involved, they compare\n", " mathematically (algorithmically) correct without loss of precision.\n", "\n", " The not-a-number values \"float('NaN')\" and \"decimal.Decimal('NaN')\"\n", " are special. Any ordered comparison of a number to a not-a-number\n", " value is false. A counter-intuitive implication is that not-a-number\n", " values are not equal to themselves. For example, if \"x =\n", " float('NaN')\", \"3 < x\", \"x < 3\" and \"x == x\" are all false, while \"x\n", " != x\" is true. This behavior is compliant with IEEE 754.\n", "\n", "* \"None\" and \"NotImplemented\" are singletons. **PEP 8** advises that\n", " comparisons for singletons should always be done with \"is\" or \"is\n", " not\", never the equality operators.\n", "\n", "* Binary sequences (instances of \"bytes\" or \"bytearray\") can be\n", " compared within and across their types. They compare\n", " lexicographically using the numeric values of their elements.\n", "\n", "* Strings (instances of \"str\") compare lexicographically using the\n", " numerical Unicode code points (the result of the built-in function\n", " \"ord()\") of their characters. [3]\n", "\n", " Strings and binary sequences cannot be directly compared.\n", "\n", "* Sequences (instances of \"tuple\", \"list\", or \"range\") can be compared\n", " only within each of their types, with the restriction that ranges do\n", " not support order comparison. Equality comparison across these\n", " types results in inequality, and ordering comparison across these\n", " types raises \"TypeError\".\n", "\n", " Sequences compare lexicographically using comparison of\n", " corresponding elements. The built-in containers typically assume\n", " identical objects are equal to themselves. That lets them bypass\n", " equality tests for identical objects to improve performance and to\n", " maintain their internal invariants.\n", "\n", " Lexicographical comparison between built-in collections works as\n", " follows:\n", "\n", " * For two collections to compare equal, they must be of the same\n", " type, have the same length, and each pair of corresponding\n", " elements must compare equal (for example, \"[1,2] == (1,2)\" is\n", " false because the type is not the same).\n", "\n", " * Collections that support order comparison are ordered the same as\n", " their first unequal elements (for example, \"[1,2,x] <= [1,2,y]\"\n", " has the same value as \"x <= y\"). If a corresponding element does\n", " not exist, the shorter collection is ordered first (for example,\n", " \"[1,2] < [1,2,3]\" is true).\n", "\n", "* Mappings (instances of \"dict\") compare equal if and only if they\n", " have equal *(key, value)* pairs. Equality comparison of the keys and\n", " values enforces reflexivity.\n", "\n", " Order comparisons (\"<\", \">\", \"<=\", and \">=\") raise \"TypeError\".\n", "\n", "* Sets (instances of \"set\" or \"frozenset\") can be compared within and\n", " across their types.\n", "\n", " They define order comparison operators to mean subset and superset\n", " tests. Those relations do not define total orderings (for example,\n", " the two sets \"{1,2}\" and \"{2,3}\" are not equal, nor subsets of one\n", " another, nor supersets of one another). Accordingly, sets are not\n", " appropriate arguments for functions which depend on total ordering\n", " (for example, \"min()\", \"max()\", and \"sorted()\" produce undefined\n", " results given a list of sets as inputs).\n", "\n", " Comparison of sets enforces reflexivity of its elements.\n", "\n", "* Most other built-in types have no comparison methods implemented, so\n", " they inherit the default comparison behavior.\n", "\n", "User-defined classes that customize their comparison behavior should\n", "follow some consistency rules, if possible:\n", "\n", "* Equality comparison should be reflexive. In other words, identical\n", " objects should compare equal:\n", "\n", " \"x is y\" implies \"x == y\"\n", "\n", "* Comparison should be symmetric. In other words, the following\n", " expressions should have the same result:\n", "\n", " \"x == y\" and \"y == x\"\n", "\n", " \"x != y\" and \"y != x\"\n", "\n", " \"x < y\" and \"y > x\"\n", "\n", " \"x <= y\" and \"y >= x\"\n", "\n", "* Comparison should be transitive. The following (non-exhaustive)\n", " examples illustrate that:\n", "\n", " \"x > y and y > z\" implies \"x > z\"\n", "\n", " \"x < y and y <= z\" implies \"x < z\"\n", "\n", "* Inverse comparison should result in the boolean negation. In other\n", " words, the following expressions should have the same result:\n", "\n", " \"x == y\" and \"not x != y\"\n", "\n", " \"x < y\" and \"not x >= y\" (for total ordering)\n", "\n", " \"x > y\" and \"not x <= y\" (for total ordering)\n", "\n", " The last two expressions apply to totally ordered collections (e.g.\n", " to sequences, but not to sets or mappings). See also the\n", " \"total_ordering()\" decorator.\n", "\n", "* The \"hash()\" result should be consistent with equality. Objects that\n", " are equal should either have the same hash value, or be marked as\n", " unhashable.\n", "\n", "Python does not enforce these consistency rules. In fact, the\n", "not-a-number values are an example for not following these rules.\n", "\n", "\n", "Membership test operations\n", "==========================\n", "\n", "The operators \"in\" and \"not in\" test for membership. \"x in s\"\n", "evaluates to \"True\" if *x* is a member of *s*, and \"False\" otherwise.\n", "\"x not in s\" returns the negation of \"x in s\". All built-in sequences\n", "and set types support this as well as dictionary, for which \"in\" tests\n", "whether the dictionary has a given key. For container types such as\n", "list, tuple, set, frozenset, dict, or collections.deque, the\n", "expression \"x in y\" is equivalent to \"any(x is e or x == e for e in\n", "y)\".\n", "\n", "For the string and bytes types, \"x in y\" is \"True\" if and only if *x*\n", "is a substring of *y*. An equivalent test is \"y.find(x) != -1\".\n", "Empty strings are always considered to be a substring of any other\n", "string, so \"\"\" in \"abc\"\" will return \"True\".\n", "\n", "For user-defined classes which define the \"__contains__()\" method, \"x\n", "in y\" returns \"True\" if \"y.__contains__(x)\" returns a true value, and\n", "\"False\" otherwise.\n", "\n", "For user-defined classes which do not define \"__contains__()\" but do\n", "define \"__iter__()\", \"x in y\" is \"True\" if some value \"z\", for which\n", "the expression \"x is z or x == z\" is true, is produced while iterating\n", "over \"y\". If an exception is raised during the iteration, it is as if\n", "\"in\" raised that exception.\n", "\n", "Lastly, the old-style iteration protocol is tried: if a class defines\n", "\"__getitem__()\", \"x in y\" is \"True\" if and only if there is a non-\n", "negative integer index *i* such that \"x is y[i] or x == y[i]\", and no\n", "lower integer index raises the \"IndexError\" exception. (If any other\n", "exception is raised, it is as if \"in\" raised that exception).\n", "\n", "The operator \"not in\" is defined to have the inverse truth value of\n", "\"in\".\n", "\n", "\n", "Identity comparisons\n", "====================\n", "\n", "The operators \"is\" and \"is not\" test for an object’s identity: \"x is\n", "y\" is true if and only if *x* and *y* are the same object. An\n", "Object’s identity is determined using the \"id()\" function. \"x is not\n", "y\" yields the inverse truth value. [4]\n", "\n", "Related help topics: EXPRESSIONS, BASICMETHODS\n", "\n" ] } ], "source": [ "help('is')" ] }, { "cell_type": "code", "execution_count": 93, "id": "c2fa8fbb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n" ] } ], "source": [ "x = ['hello']\n", "y = ['hello']\n", "print (x is y) # is operator is checking the memory address (ID) of two lists\n", "print (x == y) # == operator is checking the contents of two lists" ] }, { "cell_type": "code", "execution_count": 94, "id": "f851b909", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "True\n" ] } ], "source": [ "x = 'hello'\n", "y = 'hello'\n", "print (x is y) # is operator is checking the memory address (ID) of two strings\n", "print (x == y) # == operator is checking the contents of two strings" ] }, { "cell_type": "markdown", "id": "5ac4b74b", "metadata": {}, "source": [ "## c. Pickling vs Unpickling in Python\n", "- Converting a Python object hierarchy to a Byte stream is called pickling, also referred to as serialization\n", "- Converting a Byte stream to a Python object hierarchy is called unpickling, also referred to as deserialization\n", "- For example if you have created a neural network model, you can save that model on to your hard disk by pickling it and later you can unpickle it to load it into an application\n", "- More on this later..." ] }, { "cell_type": "code", "execution_count": null, "id": "25b94e0d", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "5321ec65", "metadata": {}, "source": [ "## Overview of Python Arrays\n", "- A simple Python array is a sequence of objects of similar data dype. Python array module requires all array elements to be of the same type. Moreover, to create an array, you'll need to specify a value type. \n", "\n", "```\n", "array(typecode [, initializer])\n", "```\n", "\n", "- Return a new array whose items are restricted by typecode, and initialized from the optional initializer value, which must be a list, string or iterable over elements of the appropriate type.\n", "\n", "- Arrays represent basic values and behave very much like lists, except the type of objects stored in them is constrained. The type is specified at object creation time by using a type code, which is a single character.\n", "- The following type codes are defined:\n", "\n", "\n", " Type code C Type Minimum size in bytes\n", " 'b' signed integer 1\n", " 'B' unsigned integer 1\n", " 'u' Unicode character 2 (see note)\n", " 'h' signed integer 2\n", " 'H' unsigned integer 2\n", " 'i' signed integer 2\n", " 'I' unsigned integer 2\n", " 'l' signed integer 4\n", " 'L' unsigned integer 4\n", " 'q' signed integer 8 (see note)\n", " 'Q' unsigned integer 8 (see note)\n", " 'f' floating point 4\n", " 'd' floating point 8" ] }, { "cell_type": "code", "execution_count": 44, "id": "12b80e8a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array('i', [3, 6, 9, 2])\n", "\n", "array('f', [3.4000000953674316, 6.699999809265137, 9.5, 2.0])\n", "\n" ] } ], "source": [ "# To use Python arrays, you have to import Python's built-in array module\n", "import array\n", "\n", "# declaring array of integers\n", "arr1 = array.array(\"i\", [3, 6, 9, 2]) \n", "print(arr1) \n", "print(type(arr1)) \n", "\n", "# declaring array of floats\n", "arr2 = array.array(\"f\", [3.4, 6.7, 9.5, 2]) \n", "print(arr2) \n", "print(type(arr2)) \n" ] }, { "cell_type": "code", "execution_count": null, "id": "c3953e92", "metadata": {}, "outputs": [], "source": [ "arr2.insert" ] }, { "cell_type": "markdown", "id": "48067d20", "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", "1. What is a list in Python?\n", "2. How do you create a list?\n", "3. Can a Python list contain values of different data types?\n", "4. Can a list contain another list as an element within it?\n", "5. Can you create a list without any values?\n", "6. How do you check the length of a list in Python?\n", "7. How do you retrieve a value from a list?\n", "8. What is the smallest and largest index you can use to access elements from a list containing five elements?\n", "9. What happens if you try to access an index equal to or larger than the size of a list?\n", "10. What happens if you try to access a negative index within a list?\n", "11. How do you access a range of elements from a list?\n", "12. How many elements does the list returned by the expression `a_list[2:5]` contain?\n", "13. What do the ranges `a_list[:2]` and `a_list[2:]` represent?\n", "14. How do you change the item stored at a specific index within a list?\n", "15. How do you insert a new item at the beginning, middle, or end of a list?\n", "16. How do you remove an item from al list?\n", "17. How do you remove the item at a given index from a list?\n", "18. How do you check if a list contains a value?\n", "19. How do you combine two or most lists to create a larger list?\n", "20. How do you create a copy of a list?\n", "21. Does the expression `a_new_list = a_list` create a copy of the list `a_list`?\n", "22. How can you find the list of all the methods supported by lists?\n", "23. Understand the difference between creating an alias of a list, and shallow copy and deep copy\n", "24. Write down a proof of concept code to understand the concept of pickling and unpickling in Python" ] }, { "cell_type": "markdown", "id": "677637c7", "metadata": {}, "source": [ "**Go to https://pythontutor.com/ and copy paste following code to visualize aliasing, shallow and deep copy**" ] }, { "cell_type": "raw", "id": "eb3a8dfc", "metadata": {}, "source": [ "# Aliasing\n", "list1 = [1, 2, 3, 4]\n", "list2 = list1\n", "list2[2] = 9\n", "\n", "# Shallow Copy\n", "list3 = [1, 2, 3, 4]\n", "list4 = list3.copy()\n", "list4[2] = 9\n", "\n", "# Issue with Shallow Copy\n", "list5 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "list6 = list5.copy()\n", "list6[2][2] = 'A'\n", "\n", "# Deep Copy\n", "import copy\n", "list7 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "list8 = copy.deepcopy(list7)\n", "list8[2][2] = 'A'" ] }, { "cell_type": "code", "execution_count": null, "id": "f41e7b84", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "96546c0f", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 48, "id": "1a43aa8e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['baz', 'zeeshan', 'arif']" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def func(s):\n", " return s[-1]\n", "\n", "l1 = ['arif', 'zeeshan', 'baz']\n", "sorted(l1, key=func, reverse=True)" ] }, { "cell_type": "code", "execution_count": 47, "id": "494597a3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'f'" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "func('arif')" ] }, { "cell_type": "code", "execution_count": null, "id": "a0352cc3", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "a5378dea", "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 }