1 00:00:00,000 --> 00:00:04,099 A long, long time ago in a lesson, a Python lesson, far, far away 2 00:00:04,120 --> 00:00:08,430 I very briefly mentioned that we can nest functions inside 3 00:00:08,430 --> 00:00:11,700 of functions, and I think that was in the scoping lesson. 4 00:00:11,700 --> 00:00:14,300 And I said, "Hey, we would talk about nested functions". 5 00:00:14,300 --> 00:00:16,570 So let's go ahead and talk about nested functions. 6 00:00:16,739 --> 00:00:21,200 So we know we can have a function like this 'def func', and 7 00:00:21,210 --> 00:00:25,790 it can "Do a thing", and we can run that function. 8 00:00:26,420 --> 00:00:29,540 But inside of Python, we can actually write functions inside 9 00:00:29,540 --> 00:00:32,310 of functions. So we could say function, 10 00:00:32,320 --> 00:00:36,810 let's just rename this one to 'main_func'. 11 00:00:36,820 --> 00:00:38,220 It's going to, "Do a thing". 12 00:00:38,230 --> 00:00:42,480 And in here we have another function called 'second_func', 13 00:00:43,000 --> 00:00:46,400 and this one is just going to print 2-2-2-2-2, because it is the second one. 14 00:00:46,400 --> 00:00:51,300 Let's go ahead rerun that cell, and change this to 'main_func()', 15 00:00:51,300 --> 00:00:53,700 and we're going to see that it simply says print, "Do a thing", 16 00:00:54,300 --> 00:00:59,000 and this is not actually going to run 'second_func' at all. 17 00:00:59,040 --> 00:01:00,870 We need to tell it to run that. 18 00:01:00,880 --> 00:01:04,519 Now, due to scoping, we can't run it automatically from here. 19 00:01:04,530 --> 00:01:05,959 It needs to be run from the inside. 20 00:01:05,970 --> 00:01:09,920 So let's go ahead, take that 'second_func', and run it inside 21 00:01:09,920 --> 00:01:11,400 of the 'main_func'. 22 00:01:11,420 --> 00:01:15,140 So if we run that cell and rerun that cell, we can see both 23 00:01:15,140 --> 00:01:16,600 of them now execute. 24 00:01:16,610 --> 00:01:20,720 Now, at this point in time in your Python learning journey, 25 00:01:20,720 --> 00:01:23,800 this really shouldn't come as a surprise at any point. 26 00:01:23,800 --> 00:01:26,560 We've done a lot of nesting with all sorts of different things, 27 00:01:26,560 --> 00:01:30,900 but the reason we would want to do a nested function like 28 00:01:30,900 --> 00:01:32,600 this, well, there's a few reasons. 29 00:01:32,610 --> 00:01:35,060 One is a decorator, which we'll talk about in the future, 30 00:01:35,070 --> 00:01:40,380 but another reason is maybe in here in the 'main_func', 31 00:01:40,380 --> 00:01:44,400 there are several smaller functions, and we need to perform 32 00:01:44,400 --> 00:01:47,500 something that is fairly complex. 33 00:01:47,500 --> 00:01:50,000 But that 'second_func' doesn't necessarily need to be in 34 00:01:50,000 --> 00:01:53,360 the global scope. It only really needs to be inside of this function, 35 00:01:53,360 --> 00:01:55,300 so it's only applicable to 'main_func'. 36 00:01:55,300 --> 00:01:57,700 So this is one example. 37 00:01:57,700 --> 00:02:00,600 Let's go ahead and create one more example, and here something 38 00:02:00,600 --> 00:02:03,100 that might actually be named a little better than 'main_func' 39 00:02:03,100 --> 00:02:04,400 and 'second_func'. 40 00:02:04,440 --> 00:02:08,160 We have a 'parent()' function, and this could take a 'name', 41 00:02:08,160 --> 00:02:10,800 default name of "Henry". 42 00:02:10,800 --> 00:02:18,800 We could say "parent() was run with ", and that's an 43 00:02:18,860 --> 00:02:21,620 f-string so that we can get "Henry" right in there. 44 00:02:23,120 --> 00:02:25,970 Now, inside of here, let's say we have a 'child()' function. 45 00:02:26,160 --> 00:02:32,040 'child' function, and the 'name' in here is going to be "Zephyr", 46 00:02:32,050 --> 00:02:34,460 and we want to say 'print()', f-string, 'f" 47 00:02:35,900 --> 00:02:38,700 child was run with "'. 48 00:02:38,700 --> 00:02:43,000 So even if we run 'parent', the 'child' function is not actually 49 00:02:43,000 --> 00:02:45,400 going to run unless we tell it to run. 50 00:02:45,400 --> 00:02:49,900 So then we need to run 'child' in here and outside 51 00:02:49,950 --> 00:02:51,260 we can simply run 'parent'. 52 00:02:51,400 --> 00:02:55,200 And it says, "parent was run with Henry", and "child was run with Zephyr". 53 00:02:55,240 --> 00:02:58,650 If we comment this out, so effectively it doesn't exist to Python 54 00:02:58,650 --> 00:03:01,700 anymore. We only get the one 'print' statement. 55 00:03:02,100 --> 00:03:06,390 Now, what's interesting about this is we can actually return 56 00:03:06,400 --> 00:03:07,440 entire functions. 57 00:03:07,440 --> 00:03:11,800 We don't need to return just a value in here or a 'print' statement. 58 00:03:11,820 --> 00:03:16,640 So let's say 'child' is actually going to return a number 59 00:03:16,650 --> 00:03:21,280 of 159. I don't know what that number means, if there's any 60 00:03:21,290 --> 00:03:22,270 significance behind it. 61 00:03:22,270 --> 00:03:23,900 I just guessed 159. 62 00:03:23,900 --> 00:03:28,300 And what this is going to do is 'return child', not 'return 63 00:03:28,300 --> 00:03:30,600 child()' with parentheses. 64 00:03:30,600 --> 00:03:35,000 We're going to return the entire 'child' function. 65 00:03:35,000 --> 00:03:36,790 So let's go ahead and run that. 66 00:03:37,000 --> 00:03:41,700 And let's throw this into a variable. Let's just call it 'var'. 67 00:03:41,740 --> 00:03:45,400 When we're going to run 'parent', it's going to automatically run the 68 00:03:45,410 --> 00:03:46,450 'print' statement in here. 69 00:03:46,450 --> 00:03:48,800 'parent' was run with default 'name' of "Henry". 70 00:03:49,900 --> 00:03:52,400 Then we defined a 'child' with a default 'name' of "Zephyr". 71 00:03:52,480 --> 00:03:53,970 That's actually not useful anymore. 72 00:03:53,970 --> 00:03:55,100 We got rid of that. 73 00:03:55,110 --> 00:03:57,840 But the 'child()' function is going to 'return 159', 74 00:03:58,140 --> 00:04:02,320 and then we're going to return the entire 'child' function 75 00:04:02,330 --> 00:04:07,360 itself, not the value of 159, the entire function itself. 76 00:04:07,360 --> 00:04:08,800 So let's run that. Run that. 77 00:04:08,800 --> 00:04:11,100 And what happens when we do 'var'? 78 00:04:11,100 --> 00:04:13,300 [no audio] 79 00:04:13,300 --> 00:04:15,100 We can see that 'var' is a 80 00:04:15,190 --> 00:04:18,500 function. We can see that it was being called from a function 81 00:04:18,500 --> 00:04:21,300 called 'parent'. It has 'locals' in here, 82 00:04:21,410 --> 00:04:25,240 so variables, and it's being called from a function called 83 00:04:25,250 --> 00:04:27,670 'child', a sub-function if you want to call that. 84 00:04:27,670 --> 00:04:31,320 What we can do, is because this is now actually a function, 85 00:04:31,740 --> 00:04:34,350 it's a variable, but it's also technically a function, 86 00:04:34,740 --> 00:04:40,560 we can now just call it as a function, and 'child' is now returning 87 00:04:40,560 --> 00:04:43,000 159 as 'var'. 88 00:04:43,570 --> 00:04:46,300 I would say this was a fairly confusing example because we 89 00:04:46,310 --> 00:04:49,400 use 'parent' and 'child', which I guess sort of makes sense, 90 00:04:49,580 --> 00:04:54,180 but we can actually make a little more relatable chunk of 91 00:04:54,180 --> 00:04:58,080 code as well. So let's create a new function in here, and let's call it 92 00:04:58,090 --> 00:05:01,380 'dog()', and we're going to create a child function in here called 93 00:05:02,400 --> 00:05:06,700 'speak()', and all this is going to do is 'return 94 00:05:07,700 --> 00:05:08,700 "Woof. Woof", 95 00:05:09,900 --> 00:05:15,200 and in here, the 'dog()' function is going to return the entire 96 00:05:15,200 --> 00:05:16,200 'speak' function. 97 00:05:16,200 --> 00:05:20,800 And essentially all this is doing is 'dog' is now a wrapper for 'speak'. 98 00:05:20,800 --> 00:05:24,300 And now we could say 'dog = dog()'. 99 00:05:24,360 --> 00:05:26,550 However, that's going to 'return speak'. 100 00:05:26,560 --> 00:05:28,710 So if we read through this, we're going to run this, 101 00:05:28,720 --> 00:05:31,470 it will register 'speak', and then it will actually return 102 00:05:31,480 --> 00:05:32,610 the entire function itself. 103 00:05:32,800 --> 00:05:35,700 So let's say this is 'woof = dog()'. 104 00:05:36,700 --> 00:05:38,800 'woof' by itself is a function. 105 00:05:38,850 --> 00:05:41,750 And because we know it's a function, and it says that right 106 00:05:41,760 --> 00:05:43,490 there, we can use parentheses around it. 107 00:05:43,500 --> 00:05:46,200 And 'woff' now says, "Woof woof!" 108 00:05:46,200 --> 00:05:50,130 So essentially, we've really just taken a function, a nested 109 00:05:50,130 --> 00:05:53,200 function, and renamed it to any variable that we want. 110 00:05:53,280 --> 00:05:55,740 Now, you might be thinking to yourself, "Kalob, why? 111 00:05:56,220 --> 00:05:57,210 Why is this important? 112 00:05:57,220 --> 00:05:59,430 This doesn't seem like I would ever use something like this". 113 00:05:59,430 --> 00:06:01,250 And you may, you may not. 114 00:06:01,260 --> 00:06:05,240 I use nested functions quite often, because I like to, let's 115 00:06:05,240 --> 00:06:08,600 say, in the 'dog()' function here, I like to wrap up a bunch of logic. 116 00:06:08,640 --> 00:06:12,460 So if I have, let's say, 50 lines of code inside of here, 117 00:06:12,470 --> 00:06:15,700 and it's all just like this one time logic, I don't necessarily 118 00:06:15,710 --> 00:06:17,170 want to write 50 lines of code. 119 00:06:17,180 --> 00:06:18,970 What I want to do is put it in a function, 120 00:06:19,200 --> 00:06:22,680 and then I can say, I don't know, the 'total =', whatever 121 00:06:22,680 --> 00:06:25,200 'speak' would be, the 50 lines of code inside of 'speak()', 122 00:06:25,200 --> 00:06:27,700 and then I could do something with that. 123 00:06:27,740 --> 00:06:32,270 And then in my code editor, and we actually have this from 124 00:06:32,280 --> 00:06:37,220 the last example, I can actually just close up my code, and 125 00:06:37,230 --> 00:06:39,620 just makes it a little easier to maintain. 126 00:06:39,630 --> 00:06:42,680 That way, you can read the code a lot easier if you don't have 127 00:06:42,690 --> 00:06:45,170 to actually look at all the code all the time, especially 128 00:06:45,170 --> 00:06:47,800 if not all the code is totally applicable all the time. 129 00:06:47,840 --> 00:06:52,480 The second reason is for decorators, and we're going to be 130 00:06:52,490 --> 00:06:54,460 learning about decorators pretty soon. 131 00:06:54,470 --> 00:06:57,250 And the idea behind a decorator is basically, instead of 132 00:06:57,260 --> 00:07:02,170 taking a regular variable as a function parameter, it takes 133 00:07:02,170 --> 00:07:04,100 a function as a parameter, 134 00:07:04,120 --> 00:07:05,380 and then we work with that. 135 00:07:05,390 --> 00:07:08,650 So while this may not be super applicable to you right now, 136 00:07:08,660 --> 00:07:11,050 it is good to tuck in your back pocket, because in the next 137 00:07:11,060 --> 00:07:13,150 lesson, we're definitely going to be using this.