"
]
},
{
"cell_type": "markdown",
"id": "630ea759",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"id": "95de41a5",
"metadata": {},
"source": [
"## _Python-Tuples.ipynb_\n",
"#### [Click me to learn more about Python Tuples](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences)"
]
},
{
"cell_type": "markdown",
"id": "0f75a9de",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"id": "3813f231",
"metadata": {},
"source": [
"> **A Tuple is a numerically ordered sequence of elements that can store elements of heterogeneous types, is iterable, immutable and allows duplicate elements.**"
]
},
{
"cell_type": "markdown",
"id": "a2e370e3",
"metadata": {},
"source": [
"- Like Lists, a Tuple in Python is also an ordered collection of values.\n",
"- Like Lists, a Tuple is created by placing comma separated values, but in parenthesis rather square brackets. \n",
"- Like List, a Tuple also allows us to store elements of different data types in one container.\n",
"- Unlike List, it is not possible to add, remove, or modify values in a Tuple, so you can think of tuples as immutable Lists.\n",
"- Apart from this, every operation that we can perform on Lists that do not modify them, can be performed on Tuples as well.\n",
"- To be honest, Tuples are not used as often as Lists in programming, but are used when immutability is necessary.\n",
"- When to prefer Tuples over Lists?\n",
" - While passing an object to a function, if you want to make sure that the object does not get changed, then Tuple become your solution. So Tuples provides a convenient source of data integrity.\n",
" - Similarly, since functions can return only one value, if you want a function to return more than one value, you pack your result in a tuple and return it\n",
" - Manipulating elements of a Tuple is far more efficient than manipulating elements of a List.\n",
" - Tuples being immutable are used in Dictionaries as keys (which are immutable)."
]
},
{
"cell_type": "markdown",
"id": "7c109b0c",
"metadata": {},
"source": [
"## Learning agenda of this notebook\n",
"1. How to create Tuples?\n",
"2. Proof of concepts: Tuples are heterogeneous, ordered, nested, immutable, and allow duplicate elements\n",
"3. Different ways to access elements of a Tuple?\n",
"4. Slicing a Tuple\n",
"5. Tuple concatenation and repetition\n",
"6. Being immutable, you cannot add elements to a Tuple\n",
"7. Being immutable, you cannot remove elemenst from a Tuple\n",
"8. Converting string object to Tuple and vice-versa (using type casting, `split()` and `join()`)\n",
"9. Tuple methods\n",
"10. Sorting a Tuple using built-in `sorted()` function"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "a0ce27db",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on class tuple in module builtins:\n",
"\n",
"class tuple(object)\n",
" | tuple(iterable=(), /)\n",
" | \n",
" | Built-in immutable sequence.\n",
" | \n",
" | If no argument is given, the constructor returns an empty tuple.\n",
" | If iterable is specified the tuple is initialized from iterable's items.\n",
" | \n",
" | If the argument is a tuple, the return value is the same object.\n",
" | \n",
" | Built-in subclasses:\n",
" | asyncgen_hooks\n",
" | UnraisableHookArgs\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",
" | __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__(self, key, /)\n",
" | Return self[key].\n",
" | \n",
" | __getnewargs__(self, /)\n",
" | \n",
" | __gt__(self, value, /)\n",
" | Return self>value.\n",
" | \n",
" | __hash__(self, /)\n",
" | Return hash(self).\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\n"
]
}
],
"source": [
"t1 = (1, 2, 3, 4, 5) #tuple of integers\n",
"t1 = 1, 2, 3, 4, 5\n",
"print(\"t1: \", t1)\n",
"\n",
"t2 = (2.3, 5.6, 1.8) #tuple of floats\n",
"print(\"t2: \", t2)\n",
"\n",
"t3 = ('hello', 'this', 'F', 'good show') #tuple of strings\n",
"print(\"t3: \", t3)\n",
"\n",
"t4 = (True, False, True) # tuple of boolean values\n",
"print(\"t4: \", t4)\n",
"\n",
"\n",
"print(\"Type of t4 is: \", type(t4))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "64ed8ede",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 18,
"id": "a51ee7b3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"t5: ()\n"
]
}
],
"source": [
"# creating empty tuple\n",
"t5 = ()\n",
"print(\"t5: \", t5)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "0d9fbff4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"t6: (25,)\n",
"\n"
]
}
],
"source": [
"# to create a tuple with only one element is a bit tricky\n",
"t6 = (25,) # note the comma, without it, Python will take it as int/float/string and not tuple\n",
"print(\"\\nt6: \", t6)\n",
"print(type(t6))"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "3c2bd2e4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('Arif', 30, 5.5, (10, 'rauf'))\n"
]
}
],
"source": [
"# Nested Tuple: a tuple can also have another tuple as an item\n",
"t1 = (\"Arif\", 30, 5.5, (10,'rauf'))\n",
"print(t1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5200e1b2",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 20,
"id": "810d75d3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"t1: (1, 'Hello', [8, 'OK', 6], (1, 2, 'BYE'), 5.5)\n",
"Type of t1 is: \n"
]
}
],
"source": [
"# Nested tuple: A tuple can also have another tuple, or list as an item\n",
"t1 = (1, \"Hello\", [8, 'OK', 6], (1, 2, 'BYE'), 5.5)\n",
"print(\"t1: \", t1)\n",
"print(\"Type of t1 is: \", type(t1))"
]
},
{
"cell_type": "markdown",
"id": "48f77dc4",
"metadata": {},
"source": [
"## 2. Proof of Concepts:"
]
},
{
"cell_type": "markdown",
"id": "00a2ff5d",
"metadata": {},
"source": [
"### a. Tuples are Heterogeneous\n",
"- Like Lists, Tuples are heterogeneous, as their elements/items can be of any data type"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "7c3a9b9c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"t1: ('Arif', 30, 5.5)\n"
]
}
],
"source": [
"t1 = (\"Arif\", 30, 5.5)\n",
"print(\"t1: \", t1)"
]
},
{
"cell_type": "markdown",
"id": "f7ef359e",
"metadata": {},
"source": [
"### b. Tuples are ordered\n",
"- Like Lists Tuples are ordered.\n",
"- Tuples are ordered means every element is associated by an index.\n",
"- Every time you access tuple elements they will show up in same sequence. \n",
"- Moreover, two tuples having same elements in different order are not same."
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "8c570d52",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(140597048184448, 140597047356352, False, False)"
]
},
"execution_count": 22,
"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": "251c05b7",
"metadata": {},
"source": [
"### c. Tuples are immutable\n",
"- Unlike Lists Tuples are immutable\n",
"- Means once a tuple object is created, you CANNOT make changes to it and modify its elements"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "8d0f40de",
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "'tuple' object does not support item assignment",
"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_27657/769081338.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Tuples are immutable, i.e., tuple elements cannot be changed\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[0mnumbers\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m20\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m30\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mnumbers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m15\u001b[0m \u001b[0;31m# this will generate an error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
]
}
],
"source": [
"# Tuples are immutable, i.e., tuple elements cannot be changed\n",
"numbers = (10, 20, 30)\n",
"numbers[2] = 15 # this will generate an error"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "80c29ede",
"metadata": {},
"outputs": [],
"source": [
"# Tupple however can be reassigned\n",
"numbers = (10, 20, 30)\n",
"numbers = (1, 2, 3) # A tupple can be reassigned\n",
"numbers"
]
},
{
"cell_type": "markdown",
"id": "1e8e4bc4",
"metadata": {},
"source": [
"Remember the tuple object `(10,20,20)` in memory has become an orphan, since the numbers variable is now pointing to another tuple object `(1,2,3)` in memory. The unreferenced tuple object will be garbage collected by Python garbage collector"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "4fc9e430",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1, 'Hello', [8, 'Not OK', 6], (1, 2, 'BYE'), 5.5)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A List within a tuple is still mutable\n",
"t1 = (1, \"Hello\", [8, 'OK', 6], (1, 2, 'BYE'), 5.5)\n",
"t1[2][1] = 'Not OK' # will work fine\n",
"t1"
]
},
{
"cell_type": "markdown",
"id": "8a459d21",
"metadata": {},
"source": [
"### d. Tuples can have duplicate elements"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "0a910e6f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('Arif', 'Rauf', 'Hadeed', 'Arif', 'Mujahid')\n"
]
}
],
"source": [
"# Like Lists, Tuples allow duplicate elements\n",
"names = ('Arif', 'Rauf', 'Hadeed', 'Arif', 'Mujahid')\n",
"print(names)"
]
},
{
"cell_type": "markdown",
"id": "32a0f7b9",
"metadata": {},
"source": [
"### e. Tuples can be nested to arbitrary depth\n",
"- Like Lists, you can have tuples within tuples 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": 26,
"id": "e087c00b",
"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": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A tuple having two sub-tuples within it\n",
"a = (1,2,3,(4,5),(6,7,8,9),10,11)\n",
"# A tuple having a sub-tuple, which is further having a sub-tuple and that again having a subtuple\n",
"b = (1,2,3,(4,5,(6,7,8,(9,10,11))))\n",
"a, b"
]
},
{
"cell_type": "markdown",
"id": "1f8ac237",
"metadata": {},
"source": [
"### f. Packing and Unpacking Tuples"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "6b94e91a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"learning fun Arif\n",
"\n"
]
}
],
"source": [
"# you can unpack tuple elements\n",
"t1 = ('learning', 'is', 'fun', 'with', 'Arif')\n",
"a, b, c, d, e = t1 # the number of variables on the left must match the length of tuple\n",
"print (a, c, e)\n",
"print(type(a))"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "b63654ee",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('learning', 'is', 'fun', 'with', 'Arif')\n",
"\n"
]
}
],
"source": [
"# you can pack individual elements to a tuple\n",
"t1 = a,b,c,d,e\n",
"print(t1)\n",
"print(type(t1))"
]
},
{
"cell_type": "markdown",
"id": "418db83b",
"metadata": {},
"source": [
"## 3. Different ways to access Elements of a Tuple\n",
"- Since Tuple like List is of type Sequence, and any component within a sequence can be accessed by entrying an index within square brackets. So naturally this must work for Tuple as well\n",
"- Similarly, if we want to find out the index of a specific item/character, we can use the `index()` method of Tuple class"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "bbc96405",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5.5\n",
"(10, 'rauf')\n",
"i\n",
"rauf\n"
]
}
],
"source": [
"#You can access elements of tuple using indexing which starts from zero\n",
"t1 = (\"Arif\", 30, 5.5, (10,'rauf'))\n",
"\n",
"print(t1[2]) #accessing element of tuple at index2\n",
"print(t1[3]) #accessing element of tuple at index3, which is again a tuple\n",
"\n",
"#accessing Nested tuple element\n",
"print(t1[0][2]) #accessing third character of a tuple element at index 0\n",
"print(t1[3][1]) #accessing second element of Nested tuple at index 3"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "c0d21f34",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(10, 'rauf')\n",
"5.5\n"
]
}
],
"source": [
"#Negative indexing starts looking at the tuple from the right hand side\n",
"t1 = (\"Arif\", 30, 5.5, (10,'rauf'))\n",
"print(t1[-1]) #accessing last element\n",
"print(t1[-2]) #accessing second last element"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb601e4a",
"metadata": {},
"outputs": [],
"source": [
"help(t1.index)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "d42c7653",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"mytuple: (27, 4.5, 'arif', 64, 'hadeed', 19, 'arif')\n",
"mytuple.index(3): 2\n"
]
}
],
"source": [
"# index(value) method is used when you know the tuple element and wants to get its index\n",
"# index(value) method returns the index of the first matched item with its only argument\n",
"mytuple = (27, 4.5, 'arif', 64, 'hadeed', 19, 'arif')\n",
"print(\"\\nmytuple: \", mytuple)\n",
"print(\"mytuple.index(3): \", mytuple.index('arif'))"
]
},
{
"cell_type": "markdown",
"id": "c9517d91",
"metadata": {},
"source": [
"## 4. Slicing Tuples\n",
"- Like anyother sequence object we can perform slicing with tuples as well.\n",
"- Slicing is the process of obtaining a portion of a tuple by using its indices.\n",
"- Given a tuple, we can use the following template to slice it and obtain a sublist:\n",
"```\n",
"mytuple[start:end:step]\n",
"```\n",
"\n",
"- **start** is the index from where we want the subtuple to start.If start is not provided, slicing starts from the beginning.\n",
"- **end** is the index where we want our subtuple to end (not inclusive in the subtuple). If end is not provided, slicing goes till the last element of the tuple.\n",
"- **step** is the step through which we want to skip elements in the tuple. The default step is 1, so we iterate through every element of the tuple."
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "d533f237",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1 = ('a','b','c','d','e','f','g','h','i')\n",
"t1"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "fc7f5721",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1[::]"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "bacb22ad",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('d', 'e', 'f', 'g', 'h', 'i')"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1[3:]"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "fda45faa",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('a', 'b', 'c', 'd')"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1[:4]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "abafa446",
"metadata": {},
"outputs": [],
"source": [
"t1[2:5]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17127f79",
"metadata": {},
"outputs": [],
"source": [
"t1[:-2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0a4ca863",
"metadata": {},
"outputs": [],
"source": [
"t1[-1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c4cf41ba",
"metadata": {},
"outputs": [],
"source": [
"# Slicing by using strides\n",
"print(t1[::]) # A default step of 1\n",
"print(t1[::1]) # A step of 1\n",
"print(t1[::2]) # A step of 2\n",
"print(t1[::3]) # A step of 3"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "44359432",
"metadata": {},
"outputs": [],
"source": [
"# Reverse slicing\n",
"print(t1[::-1]) # Take 1 step back each time\n",
"print(t1[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(t1[2:10:-1])\n",
"print(t1[::-2]) # Take 2 steps back"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8221022c",
"metadata": {},
"outputs": [],
"source": [
"# You CANNOT use slice operator on the left side of assignment as tuple is immutable\n",
"t1 = (1, 2, 3, 4, 5, 6, 7)\n",
"#t1[2:4] = ['a', 'b', 'c'] # will generate an error as 'tuple' object does not support item assignment"
]
},
{
"cell_type": "markdown",
"id": "8f109f45",
"metadata": {},
"source": [
"## 5. Tuple Concatenation and Repetition\n",
"- The `+` operator is used to concatenate two or more tuples\n",
"- The `*` operator is used to repeat or replicate"
]
},
{
"cell_type": "markdown",
"id": "4063124d",
"metadata": {},
"source": [
"### a. Concatenating Tuples"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "5db695de",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"((1, 2, 3), (1, 2, 3, 4, 5), (0, 1, 2, 3, 4, 5))"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Add some elements to the end of an existing tuple using concatenation operator\n",
"a = (1,2,3)\n",
"b = a + (4,5)\n",
"# Add some elements to the beginning of an existing tuple using concatenation operator\n",
"c = (0,) + b\n",
"a, b, c"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "65c304f4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('fruits', 'bread', 'veggies', 'meat', 'spices', 'burger')\n"
]
}
],
"source": [
"# use + operator to concatenate two tuples\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": 38,
"id": "895eb9a4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(5, 3.4, 'hello', 31, 9.7, 'bye')\n"
]
}
],
"source": [
"# You can concatenate two heterogeneous tuples\n",
"t1 = (5, 3.4, 'hello')\n",
"t2 = (31, 9.7, 'bye')\n",
"t3 = t1 + t2\n",
"print(t3)"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "0845f519",
"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": "617419b0",
"metadata": {},
"source": [
"### b. Replicating Tuples"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "d4208107",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('Arif', 'Hadeed', 'Mujahid', 'Arif', 'Hadeed', 'Mujahid', 'Arif', 'Hadeed', 'Mujahid')\n"
]
}
],
"source": [
"# use tuple * n syntax to create large tuples by repeating the tuple n times\n",
"name = ('Arif', 'Hadeed', 'Mujahid')\n",
"a = name * 3\n",
"print(a)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "a9a6308a",
"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"
]
},
{
"data": {
"text/plain": [
"tuple"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#tuple of 100 A's\n",
"buf = ('A',)\n",
"newbuf = buf * 100\n",
"print(newbuf)\n",
"type(newbuf)"
]
},
{
"cell_type": "markdown",
"id": "0557d8ff",
"metadata": {},
"source": [
"## 6. Being immutable, you cannot add elements to a tuple (in list this is possible using `append`, `extend`, and `insert`)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "4ca664fe",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
" myfamily tuple: ('Farooq', 'Rauf', 'Hadeed')\n"
]
},
{
"ename": "AttributeError",
"evalue": "'tuple' object has no attribute 'insert'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/var/folders/1t/g3ylw8h50cjdqmk5d6jh1qmm0000gn/T/ipykernel_27657/1169247384.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mmyfamily\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m\"Farooq\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Rauf'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Hadeed'\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[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"\\n myfamily tuple: \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmyfamily\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mmyfamily\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Arif'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# will generate an error as tuple object has no attribute 'insert'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: 'tuple' object has no attribute 'insert'"
]
}
],
"source": [
"myfamily = (\"Farooq\", 'Rauf', 'Hadeed')\n",
"print(\"\\n myfamily tuple: \", myfamily)\n",
"myfamily.insert(2,'Arif') # will generate an error as tuple object has no attribute 'insert'\n"
]
},
{
"cell_type": "markdown",
"id": "ae40dd9e",
"metadata": {},
"source": [
"## 7. Being immutable, you cannot remove elements from a tuple (in list this is possible using `pop` and `remove` methods)"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "33f7704a",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'tuple1' 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_27657/527872821.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;31m# However, you can delete an entire tuple object using del keyword\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mtuple1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtuple1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'tuple1' is not defined"
]
}
],
"source": [
"tuple1 = ('learning', 'is', 'fun', 'with', 'arif', 'butt')\n",
"\n",
"#You cannot delete items from a tuple using del keyword\n",
"#del tuple1[3] # will generate an error as tuple object doesn't support item deletion\n",
"\n",
"# However, you can assign a new tuple object to the reference tuple1\n",
"tuple1 = (1, 2, 3, 'arif')\n",
"# However, you can delete an entire tuple object using del keyword\n",
"#del tuple1\n",
"#print(tuple1)\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0f4dd1c2",
"metadata": {},
"source": [
"## 8. Converting String object to List/Tuple and vice-versa"
]
},
{
"cell_type": "markdown",
"id": "f9dcb124",
"metadata": {},
"source": [
"### a. Type Casting"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "71af910c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Original string: Learning is fun and its type is: \n",
"t1: ('L', 'e', 'a', 'r', 'n', 'i', 'n', 'g', ' ', 'i', 's', ' ', 'f', 'u', 'n') and its type is: \n"
]
}
],
"source": [
"# convert a string into tuple using tuple()\n",
"str1 = 'Learning is fun' #this is a string\n",
"\n",
"print(\"Original string: \", str1, \"and its type is: \", type(str1))\n",
"t1 = tuple(str1)\n",
"print(\"t1: \", t1, \"and its type is: \", type(t1))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bcf7ce2f",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "5e9e7346",
"metadata": {},
"source": [
"### b. Use `str.split()` to Split a Tuple into Strings\n",
"- Used to tokenize a string based on some delimiter, which can be stored in a tuple\n",
"- It returns a list, so we need to type cast the returned object to a tuple"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "993e0fef",
"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": 47,
"id": "c5d68224",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('Learning', 'is', 'fun')\n",
"\n"
]
}
],
"source": [
"str1 = 'Learning is fun' #this is a string\n",
"t1 = tuple(str1.split(' ')) # The split() method returns a list, which you can typecast to a tuple\n",
"print(t1)\n",
"print(type(t1))"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "0ae62a11",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('Data S', 'ien', 'e is GR8 Degree')\n",
"\n"
]
}
],
"source": [
"str2 = \"Data Science is GR8 Degree\" #this is a string\n",
"t2 = tuple(str2.split('c'))\n",
"print(t2)\n",
"print(type(t2))"
]
},
{
"cell_type": "markdown",
"id": "1096daf9",
"metadata": {},
"source": [
"### c. Use `str.join()` to Join Strings into a Tuple\n",
"- The `str.join()` is the reverse of split() method, and is used to joing multiple strings by inserting the string in between on which this method is called\n",
"- Remember, you can pass any iterable as argument to `str.join()` method"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "0c20a59f",
"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": [
"str = \"\"\n",
"help(str.join)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "f04b4019",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('This', 'is', 'getting', 'more', 'and', 'more', 'interesting')"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1 = ('This', 'is', 'getting', 'more', 'and', 'more', 'interesting')\n",
"t1"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "04ecbbc7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('This is getting more and more interesting', str)"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"str2 = ' '.join(t1)\n",
"str2, type(str2)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "2bb77698",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This # is # getting # more # and # more # interesting\n",
"\n"
]
}
],
"source": [
"delimiter = \" # \"\n",
"str3 = delimiter.join(t1)\n",
"print(str3)\n",
"print(type(str3))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a06d0265",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "fbf88b2e",
"metadata": {},
"source": [
"## 9. Misc Tuple Methods in Python\n",
"- Tuples have built-in methods, but not as many as Lists do. Lets look at two of them:\n",
" - The `t1.index(val)` method takes the value and returns the first index where that value resides in the tuple\n",
" - The `t1.count(val)` method takes exactly one argument and returns the number of times a that value occurs in a tuple"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "9a32d56d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3\n"
]
}
],
"source": [
"t1 = (3, 8, 1, 6, 0, 8, 4)\n",
"rv = t1.index(6)\n",
"print(rv)"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "8dfa6b70",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3\n"
]
}
],
"source": [
"t1 = (3, 8, 1, 6, 8, 0, 8, 4)\n",
"rv = t1.count(8)\n",
"print(rv)"
]
},
{
"cell_type": "markdown",
"id": "4f48dd83",
"metadata": {},
"source": [
"**Like Lists, you can apply `max()`, `min()`, and `sum()` functions on tuples with numeric elements**"
]
},
{
"cell_type": "code",
"execution_count": 15,
"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": [
"t1 = (3, 8, 1, 6, 0, 8, 4)\n",
"print(\"length of list: \", len(t1))\n",
"print(\"max element in list: \", max(t1))\n",
"print(\"min element in list: \",min(t1))\n",
"print(\"Sum of element in list: \",sum(t1))"
]
},
{
"cell_type": "markdown",
"id": "bf47a9e8",
"metadata": {},
"source": [
"**Like Lists, you can apply `in` and `not in` membership operators on Tuples**"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "689db389",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n",
"True\n",
"True\n"
]
}
],
"source": [
"t1 = (3, 8, 1, 6, 0, 8, 4)\n",
"rv1 = 9 in t1\n",
"print(rv1)\n",
"\n",
"rv2 = 9 not in t1\n",
"print(rv2)\n",
"\n",
"\n",
"t2 = (\"XYZ\", \"ABC\", \"MNO\", \"ARIF\")\n",
"rv3 = \"ARIF\" in t2\n",
"print(rv3)\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "aaaa0c01",
"metadata": {},
"source": [
"**Comparing Objects and Values**"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "e6a50444",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"140597046554096 140597046554096\n",
"True\n",
"True\n"
]
}
],
"source": [
"#In case of strings, both variables str1 and str2 refers to the same memory location containing string object 'hello'\n",
"str1 = 'hello'\n",
"str2 = 'hello'\n",
"print(id(str1), id(str2))\n",
"\n",
"print (str1 is str2) # is operator is checking the memory address (ID) of two strings\n",
"print (str1 == str2) # == operator is checking the contents of two strings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a1c96bd0",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 15,
"id": "8639f31f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"140597048251712 140597048247424\n",
"False\n",
"True\n"
]
}
],
"source": [
"#In case of tuples, both t1 and t2 refers to two different objects in the memory having same values\n",
"t1 = (1, 2, 3)\n",
"t2 = (1, 2, 3)\n",
"print(id(t1), id(t2))\n",
"\n",
"print (t1 is t2) # is operator is checking the memory address (ID) of two tuples\n",
"print (t1 == t2) # == operator is checking the contents of two tuples element by element"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f37b0ce",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "4d074020",
"metadata": {},
"source": [
"## 10. Sorting a Tuple\n",
"- Python’s built-in `sorted()` function can be used to sort iterable objects, such as lists, tuples, and dictionaries. - We have seen its usage in our Tuple session.\n",
"- The `sorted()` function sorts the items of the specified iterable object and creates a new object with the newly sorted values.\n",
"- It's syntax is as shown below:\n",
"```\n",
" sorted(object, key=None, reverse=False)\n",
"```\n",
"- Where:\n",
" - `object`: the iterable object that you want to sort (required)\n",
" - `key`: the function that allows you to perform custom sort operations (optional)\n",
" - `reverse`: specifies whether the object should be sorted in descending order (optional)- default value is False"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "4625d4b2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Original Tuple = (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": [
"# Sorting a Dictionary by it values with numeric values\n",
"\n",
"t1 = (3, 8, 1, 6, 0, 8, 4)\n",
"\n",
"print(\"Original Tuple = \", t1)\n",
"\n",
"\n",
"list1 = sorted(t1)\n",
"list2 = sorted(t1, reverse=True)\n",
"\n",
"print(\"Ascending Sort: \", list1)\n",
"print(\"Descending Sort: \", list2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d8c14be7",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 58,
"id": "4203d43f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Original Tuple: ('XYZ', 'ABC', 'MNO', 'ARIF')\n",
"Ascending Sort: ['ABC', 'ARIF', 'MNO', 'XYZ']\n",
"Descending Sort: ['XYZ', 'MNO', 'ARIF', 'ABC']\n"
]
}
],
"source": [
"# Sorting a tuple with string values\n",
"\n",
"t1 = (\"XYZ\", \"ABC\", \"MNO\", \"ARIF\")\n",
"print(\"Original Tuple: \", t1)\n",
"\n",
"list1 = sorted(t1)\n",
"list2 = sorted(t1, reverse=True)\n",
"\n",
"print(\"Ascending Sort: \", list1)\n",
"print(\"Descending Sort: \", list2)"
]
},
{
"cell_type": "markdown",
"id": "cdcb5387",
"metadata": {},
"source": [
"### b. Custom Sorting using `sorted()` Method"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2c90cf5e",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "e03ac410",
"metadata": {},
"source": [
"**Example 1: Suppose given a tuple with elements `('ccc', 'aaaa', 'd', 'bb')` and we want to sort it by length of strings inside the tuple so that the output is like : `('d', 'bb', 'ccc', 'aaaa)`**\n",
"\n",
"```\n",
" sorted(iterable, key=None, reverse=False)\n",
"```\n",
"- We write a one argument function, and pass that function to the `key` parameter of `sorted()` function\n",
"- The `sorted()` function will run this one argument function on all the elements of the tuple 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 `tuple` will return a shadow list containing length of every string within the original tuple containing `[3,4,1,2]`\n",
"- The `sorted()` function will then sort elements of the tuple based on the values of the shadow list and returns the required sorted list :)"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "d4015aa1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['aaaa', 'bb', 'ccc', 'd']"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1 = ('ccc', 'aaaa', 'd', 'bb')\n",
"sorted(t1)"
]
},
{
"cell_type": "code",
"execution_count": 64,
"id": "ff103dab",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['d', 'bb', 'ccc', 'aaaa']"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#Example 1:\n",
"t1 = ('ccc', 'aaaa', 'd', 'bb')\n",
"sorted(t1, key=len)"
]
},
{
"cell_type": "markdown",
"id": "e0a78fe8",
"metadata": {},
"source": [
"**Example 2: Suppose given a tuple with elements `('abcz', 'xyza', 'bas', 'arif')` and we want to sort it by last character of strings within the tuple so that the output is like : `('xyza', 'arif', 'bas', 'abcz')`**\n",
"\n",
"```\n",
" sorted(iterable, key=None, reverse=False)\n",
"```\n",
"- We write a one argument function, and pass that function to the `key` parameter of `sorted()` function\n",
"- The `sorted()` function will run this one argument function on all the elements of the tuple and return a single value, and build up a shadow list of those new values. \n",
"- This time the one argument function is a user defined function that receives a string and returns its last character. When called on every element of `tuple` will return a shadow list containing only the last character of every string within the original tuple containing `['z', 'a', 's', 'f']`\n",
"- The `sorted()` function will then sort elements of the tuple based on the values of the shadow list and returns the required sorted list :)"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "2587b323",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['xyza', 'arif', 'bas', 'abcz']\n",
"('abcz', 'xyza', 'bas', 'arif')\n"
]
}
],
"source": [
"def last(s):\n",
" return s[-1]\n",
"\n",
"t1 = ('abcz', 'xyza', 'bas', 'arif')\n",
"rv = sorted(t1, key=last)\n",
"print(rv)\n",
"print(t1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b77e3768",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "1bd4be02",
"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. How tuples are different from list?\n",
"2. Can you add or remove elements in a tuple?\n",
"3. How do you create a tuple with just one element?\n",
"4. How do you convert a tuple to a list and vice versa?\n",
"5. How to create a nested tuple?\n",
"6. How to find a min, max value from a tuple?\n",
"7. How to compare two tuples, without iteration? (Hint: cmp)\n",
"8. How to find the index of a specific element of a tuple?\n",
"9. How to fiund the count of occurrence of element in Python Tuple?\n",
"10.How to delete Tuple in Python ?\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b0cf3eb0",
"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
}