Skip to content

Commit 4c83029

Browse files
authored
Updated with more examples and exercises
1 parent 0558972 commit 4c83029

12 files changed

+7957
-0
lines changed

001_Python_Functions.ipynb

+1,580
Large diffs are not rendered by default.

002_Python_Function_Global_Local_Nonlocal.ipynb

+707
Large diffs are not rendered by default.

003_Python_Function_global_Keywords.ipynb

+472
Large diffs are not rendered by default.

004_Python_Function_Arguments.ipynb

+1,046
Large diffs are not rendered by default.

005_Python_Function_Recursion.ipynb

+258
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"<small><small><i>\n",
8+
"All the IPython Notebooks in **Python Functions** lecture series by Dr. Milaan Parmar are available @ **[GitHub](https://github.com/milaan9/04_Python_Functions)**\n",
9+
"</i></small></small>"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"# Python Recursion\n",
17+
"\n",
18+
"In this class, you will learn to create a recursive function (a function that calls itself again and again)."
19+
]
20+
},
21+
{
22+
"cell_type": "markdown",
23+
"metadata": {},
24+
"source": [
25+
"# What is recursion?\n",
26+
"\n",
27+
"Recursion is the process of defining something in terms of itself.\n",
28+
"\n",
29+
"A physical world example would be to **place two parallel mirrors facing each other**. Any object in between them would be reflected recursively."
30+
]
31+
},
32+
{
33+
"cell_type": "markdown",
34+
"metadata": {},
35+
"source": [
36+
"## Python Recursive Function\n",
37+
"\n",
38+
"In Python, we know that a **[function](https://github.com/milaan9/04_Python_Functions/blob/main/001_Python_Functions.ipynb)** can call other functions. It is even possible for the function to call itself. These types of construct are termed as recursive functions.\n",
39+
"\n",
40+
"The following image shows the working of a recursive function called **`recurse`**.\n",
41+
"\n",
42+
"<div>\n",
43+
"<img src=\"img/re1.png\" width=\"250\"/>\n",
44+
"</div>\n",
45+
"\n",
46+
"Following is an example of a recursive function to find the factorial of an integer.\n",
47+
"\n",
48+
"Factorial of a number is the product of all the integers from 1 to that number. For example, the factorial of 6 (denoted as 6!) is \n",
49+
"\n",
50+
"```python\n",
51+
"1*2*3*4*5*6 = 720.\n",
52+
"```"
53+
]
54+
},
55+
{
56+
"cell_type": "code",
57+
"execution_count": 1,
58+
"metadata": {
59+
"ExecuteTime": {
60+
"end_time": "2021-06-13T16:03:47.995819Z",
61+
"start_time": "2021-06-13T16:03:47.984100Z"
62+
}
63+
},
64+
"outputs": [
65+
{
66+
"name": "stdout",
67+
"output_type": "stream",
68+
"text": [
69+
"The factorial of 3 is 6\n"
70+
]
71+
}
72+
],
73+
"source": [
74+
"# Example 1:\n",
75+
"\n",
76+
"def factorial(n):\n",
77+
" \"\"\"This is a recursive function to find the factorial of an integer\"\"\"\n",
78+
"\n",
79+
" if n == 1:\n",
80+
" return 1\n",
81+
" else:\n",
82+
" return (n * factorial(n-1)) # 3 * 2 * 1 = 6\n",
83+
"\n",
84+
"\n",
85+
"num = 3\n",
86+
"print(\"The factorial of\", num, \"is\", factorial(num))"
87+
]
88+
},
89+
{
90+
"cell_type": "markdown",
91+
"metadata": {},
92+
"source": [
93+
"In the above example, **`factorial()`** is a recursive function as it calls itself."
94+
]
95+
},
96+
{
97+
"cell_type": "markdown",
98+
"metadata": {},
99+
"source": [
100+
"When we call this function with a positive integer, it will recursively call itself by decreasing the number.\n",
101+
"\n",
102+
"Each function multiplies the number with the factorial of the number below it until it is equal to one. This recursive call can be explained in the following steps.\n",
103+
"\n",
104+
"```python\n",
105+
"factorial(3) # 1st call with 3\n",
106+
"3 * factorial(2) # 2nd call with 2\n",
107+
"3 * 2 * factorial(1) # 3rd call with 1\n",
108+
"3 * 2 * 1 # return from 3rd call as number=1\n",
109+
"3 * 2 # return from 2nd call\n",
110+
"6 # return from 1st call\n",
111+
"```\n",
112+
"\n",
113+
"Let's look at an image that shows a step-by-step process of what is going on:\n",
114+
"\n",
115+
"<div>\n",
116+
"<img src=\"img/re2.png\" width=\"350\"/>\n",
117+
"</div>"
118+
]
119+
},
120+
{
121+
"cell_type": "markdown",
122+
"metadata": {},
123+
"source": [
124+
"Our recursion ends when the number reduces to 1. This is called the base condition.\n",
125+
"\n",
126+
"Every recursive function must have a base condition that stops the recursion or else the function calls itself infinitely.\n",
127+
"\n",
128+
"The Python interpreter limits the depths of recursion to help avoid infinite recursions, resulting in stack overflows.\n",
129+
"\n",
130+
"By default, the maximum depth of recursion is **`1000`**. If the limit is crossed, it results in **`RecursionError`**. Let's look at one such condition."
131+
]
132+
},
133+
{
134+
"cell_type": "code",
135+
"execution_count": 2,
136+
"metadata": {
137+
"ExecuteTime": {
138+
"end_time": "2021-06-13T16:04:11.723151Z",
139+
"start_time": "2021-06-13T16:04:05.119692Z"
140+
}
141+
},
142+
"outputs": [
143+
{
144+
"ename": "RecursionError",
145+
"evalue": "maximum recursion depth exceeded",
146+
"output_type": "error",
147+
"traceback": [
148+
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
149+
"\u001b[1;31mRecursionError\u001b[0m Traceback (most recent call last)",
150+
"\u001b[1;32m<ipython-input-2-3ec8c6652eef>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
151+
"\u001b[1;32m<ipython-input-2-3ec8c6652eef>\u001b[0m in \u001b[0;36mrecursor\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
152+
"... last 1 frames repeated, from the frame below ...\n",
153+
"\u001b[1;32m<ipython-input-2-3ec8c6652eef>\u001b[0m in \u001b[0;36mrecursor\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mrecursor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
154+
"\u001b[1;31mRecursionError\u001b[0m: maximum recursion depth exceeded"
155+
]
156+
}
157+
],
158+
"source": [
159+
"def recursor():\n",
160+
" recursor()\n",
161+
"recursor()"
162+
]
163+
},
164+
{
165+
"cell_type": "markdown",
166+
"metadata": {},
167+
"source": [
168+
"## Advantages of Recursion\n",
169+
"\n",
170+
"1. Recursive functions make the code look clean and elegant.\n",
171+
"2. A complex task can be broken down into simpler sub-problems using recursion.\n",
172+
"3. Sequence generation is easier with recursion than using some nested iteration."
173+
]
174+
},
175+
{
176+
"cell_type": "markdown",
177+
"metadata": {},
178+
"source": [
179+
"## Disadvantages of Recursion\n",
180+
"\n",
181+
"1. Sometimes the logic behind recursion is hard to follow through.\n",
182+
"2. Recursive calls are expensive (inefficient) as they take up a lot of memory and time.\n",
183+
"3. Recursive functions are hard to debug."
184+
]
185+
},
186+
{
187+
"cell_type": "code",
188+
"execution_count": null,
189+
"metadata": {},
190+
"outputs": [],
191+
"source": []
192+
}
193+
],
194+
"metadata": {
195+
"hide_input": false,
196+
"kernelspec": {
197+
"display_name": "Python 3",
198+
"language": "python",
199+
"name": "python3"
200+
},
201+
"language_info": {
202+
"codemirror_mode": {
203+
"name": "ipython",
204+
"version": 3
205+
},
206+
"file_extension": ".py",
207+
"mimetype": "text/x-python",
208+
"name": "python",
209+
"nbconvert_exporter": "python",
210+
"pygments_lexer": "ipython3",
211+
"version": "3.8.8"
212+
},
213+
"toc": {
214+
"base_numbering": 1,
215+
"nav_menu": {},
216+
"number_sections": true,
217+
"sideBar": true,
218+
"skip_h1_title": false,
219+
"title_cell": "Table of Contents",
220+
"title_sidebar": "Contents",
221+
"toc_cell": false,
222+
"toc_position": {},
223+
"toc_section_display": true,
224+
"toc_window_display": false
225+
},
226+
"varInspector": {
227+
"cols": {
228+
"lenName": 16,
229+
"lenType": 16,
230+
"lenVar": 40
231+
},
232+
"kernels_config": {
233+
"python": {
234+
"delete_cmd_postfix": "",
235+
"delete_cmd_prefix": "del ",
236+
"library": "var_list.py",
237+
"varRefreshCmd": "print(var_dic_list())"
238+
},
239+
"r": {
240+
"delete_cmd_postfix": ") ",
241+
"delete_cmd_prefix": "rm(",
242+
"library": "var_list.r",
243+
"varRefreshCmd": "cat(var_dic_list()) "
244+
}
245+
},
246+
"types_to_exclude": [
247+
"module",
248+
"function",
249+
"builtin_function_or_method",
250+
"instance",
251+
"_Feature"
252+
],
253+
"window_display": false
254+
}
255+
},
256+
"nbformat": 4,
257+
"nbformat_minor": 2
258+
}

0 commit comments

Comments
 (0)