1 00:00:00,000 --> 00:00:04,550 Scope is a fancy way of saying we're going to use this variable, 2 00:00:04,550 --> 00:00:06,200 or we're going to use this function. 3 00:00:06,240 --> 00:00:10,440 And I think the best way to learn about scope is to really 4 00:00:10,450 --> 00:00:13,410 just experience it, because I find trying to describe it 5 00:00:13,420 --> 00:00:15,120 in words doesn't actually make sense. 6 00:00:15,130 --> 00:00:17,640 And when I was first learning scope, someone tried describing it 7 00:00:17,640 --> 00:00:19,300 to me, and I was like, "I don't get it. 8 00:00:19,300 --> 00:00:22,300 Like I can use a variable in one place, but not another place", 9 00:00:22,300 --> 00:00:24,800 which is effectively, yeah, that's what it is, 10 00:00:24,800 --> 00:00:26,500 but there are rules behind it. 11 00:00:27,700 --> 00:00:29,100 So let's go ahead and create an example here. 12 00:00:29,170 --> 00:00:32,850 We've got 'language = "Python", and then if I do 'def 13 00:00:32,939 --> 00:00:38,570 change_language(): language = "JavaScript"'. 14 00:00:38,570 --> 00:00:43,500 And let's return that 'language' in this function, and we 'print( 15 00:00:43,860 --> 00:00:47,220 language)'. This is a really good example of scope. 16 00:00:47,220 --> 00:00:50,100 So we've originally set it to be "Python", 17 00:00:50,160 --> 00:00:53,570 we've got this function in here called 'change_language()', and 18 00:00:53,570 --> 00:00:57,400 it's reassigning the exact same variable here to be called "JavaScript". 19 00:00:58,900 --> 00:01:01,600 So when I run this cell, do you think this is 20 00:01:01,600 --> 00:01:04,200 going to be "Python", or do you think this is going to be "JavaScript"? 21 00:01:04,200 --> 00:01:06,500 [no audio] 22 00:01:06,500 --> 00:01:09,100 Let's go ahead and run this cell, and we're going to see 23 00:01:09,100 --> 00:01:10,200 that it's "Python". 24 00:01:10,240 --> 00:01:14,610 Now, the reason for this is because this 'language = "Python"', 25 00:01:14,620 --> 00:01:20,160 'language' variable is in a higher scope, and the "JavaScript" 26 00:01:20,160 --> 00:01:22,100 variable is in a function. 27 00:01:22,180 --> 00:01:25,120 So essentially, the "JavaScript" variable isn't allowed to 28 00:01:25,130 --> 00:01:27,160 be accessed outside of this function at all. 29 00:01:27,170 --> 00:01:31,170 This is called scope, where we have sure, we have a variable 30 00:01:31,180 --> 00:01:32,520 called 'language' here and here. 31 00:01:32,640 --> 00:01:37,900 But inside of this function, Python is saying, "Hey, there 32 00:01:37,900 --> 00:01:42,010 is another variable in here called 'language', and I'm going 33 00:01:42,020 --> 00:01:44,860 to use this one in here", and it's going to be completely 34 00:01:44,870 --> 00:01:47,680 unaware of this other one for the time being. 35 00:01:48,200 --> 00:01:51,500 Now what happens if I actually run this function? 36 00:01:51,500 --> 00:01:55,900 So I'm going to run 'change_language', and I try to figure out 37 00:01:55,900 --> 00:01:57,100 what 'language' is again. 38 00:01:57,110 --> 00:01:58,340 So I've run this language. 39 00:01:58,350 --> 00:02:01,510 It has now said, okay, 'language = "JavaScript", and 40 00:02:01,510 --> 00:02:04,200 it returned that 'language', as we can see here. 41 00:02:04,200 --> 00:02:07,900 So now that it's been overwritten, should 'language' be "JavaScript", 42 00:02:07,900 --> 00:02:08,900 or should it be "Python", 43 00:02:08,900 --> 00:02:13,199 because we executed some code that overwrote that variable. 44 00:02:13,199 --> 00:02:16,500 Well, if we run the cell, we're still going to see that it's still "Python". 45 00:02:16,500 --> 00:02:21,400 So Python uses this thing called the LEGB rule. 46 00:02:21,400 --> 00:02:23,300 'L' stands for 'Local'. 47 00:02:23,350 --> 00:02:28,090 So names assigned in any way with a function like 'def' or 48 00:02:28,100 --> 00:02:32,900 'lambda'. So it's going to look for a variable in here, and then 49 00:02:32,900 --> 00:02:36,500 it's going to look for, enclosed function locals, that's the 50 00:02:36,560 --> 00:02:40,680 'E', and that's names in local scope and any enclosing functions 51 00:02:40,700 --> 00:02:43,400 or functions that are outside of functions, 52 00:02:43,400 --> 00:02:46,100 because in Python, we can nest functions inside of other 53 00:02:46,100 --> 00:02:48,100 functions. We'll touch on that a little bit later. 54 00:02:48,100 --> 00:02:49,800 Then the 'G' is 'Global'. 55 00:02:49,800 --> 00:02:53,500 So the global module that's outside of here. And then the 56 00:02:53,500 --> 00:02:56,600 built-in Python library, that's the 'B'. 57 00:02:56,620 --> 00:03:02,500 And that means if there is a variable that Python is already 58 00:03:02,500 --> 00:03:05,000 using, then it's going to look for that. 59 00:03:05,000 --> 00:03:09,200 It's one of those keywords, such as the word 'for', or 'while', 60 00:03:09,290 --> 00:03:12,200 or 'True' or 'False', those are all keywords, 61 00:03:12,210 --> 00:03:14,420 and so Python is going to try to reserve those. 62 00:03:14,430 --> 00:03:16,900 You can overwrite them, but please don't, because you're 63 00:03:16,910 --> 00:03:19,790 going to cause a lot of problems if you overwrite them. 64 00:03:19,800 --> 00:03:23,550 So that's why we try not to overwrite keyword variables that 65 00:03:23,560 --> 00:03:26,340 Python already gives us, or keywords that Python gives us. 66 00:03:26,440 --> 00:03:27,940 So a good way to look at this 67 00:03:27,950 --> 00:03:32,800 is really Python is going to say, "Okay, there's language 68 00:03:32,810 --> 00:03:34,900 = "Python"." 69 00:03:34,910 --> 00:03:38,080 There's a function in here, but it doesn't actually execute 70 00:03:38,090 --> 00:03:40,030 that function right away. 71 00:03:40,040 --> 00:03:43,600 It just says, because this code is basically touching this 72 00:03:43,610 --> 00:03:46,930 line here that is going to register it, but it isn't actually 73 00:03:46,940 --> 00:03:50,260 executed. But when you do execute, this function, it's going 74 00:03:50,260 --> 00:03:52,400 to look from the inside to the outside. 75 00:03:52,400 --> 00:03:54,800 So it's going to look for a 'language' in here called "JavaScript", 76 00:03:54,970 --> 00:03:57,790 and if that does not exist, it's going to then use the 'language' 77 00:03:57,800 --> 00:03:58,800 up here called "Python". 78 00:03:58,810 --> 00:04:01,900 So let's go ahead, comment this line out, and let's rerun 79 00:04:01,900 --> 00:04:06,400 this. Okay, it still says, "Python", but when we run 80 00:04:06,400 --> 00:04:08,500 'change_language()', it's going to 'return language'. 81 00:04:08,500 --> 00:04:12,000 Now, this used to say "JavaScript", but this now says "Python". 82 00:04:12,000 --> 00:04:15,900 'language', here for all intents of purposes, does not exist. 83 00:04:15,900 --> 00:04:21,000 And so because it couldn't find a variable in here called 'language', 84 00:04:21,000 --> 00:04:23,000 this just simply didn't exist, 85 00:04:24,399 --> 00:04:26,399 it looked outside of its own scope. 86 00:04:26,399 --> 00:04:29,400 And so it looked up here for the word 'language', or the variable 87 00:04:29,400 --> 00:04:30,900 'language', and used that one. 88 00:04:30,900 --> 00:04:36,180 Now, let's create a little more complicated example, and 89 00:04:36,190 --> 00:04:39,090 I don't expect you to totally know what's going on here, 90 00:04:39,100 --> 00:04:41,600 but we are going to take a look at nested functions. 91 00:04:41,600 --> 00:04:48,700 So if I have 'name = "Kalob"', this is a global variable. 92 00:04:48,780 --> 00:04:54,330 If I then create a function called 'greeting', and I put the 93 00:04:54,330 --> 00:05:00,900 'name' in here as "Zephyr", this is an 'enclosing variable'. 94 00:05:00,900 --> 00:05:06,400 And if I put another function in here 'def say_hello', and 95 00:05:06,400 --> 00:05:13,400 this 'name = "Henry", this one is local. 96 00:05:13,400 --> 00:05:17,000 And so what we can say, because this is a function inside of a function, 97 00:05:17,000 --> 00:05:20,200 we can run this function inside of the 'greeting' function, 98 00:05:20,200 --> 00:05:22,360 and then we can run 'greeting' on its own. 99 00:05:22,370 --> 00:05:24,130 So let's go ahead and run 'greeting'. 100 00:05:24,140 --> 00:05:27,190 And before I do that, let's take a look at what we think 101 00:05:27,200 --> 00:05:28,300 is going to happen here. 102 00:05:28,300 --> 00:05:29,600 So I'm going to run 'greeting'. 103 00:05:29,600 --> 00:05:31,600 'name' is already defined outside of it. 104 00:05:32,600 --> 00:05:36,500 Then we're defining 'name' inside of this to be 'name = "Zephyr"'. 105 00:05:36,500 --> 00:05:38,200 And inside of here, 106 00:05:38,230 --> 00:05:39,340 the 'name = "Henry"'. 107 00:05:39,340 --> 00:05:41,900 And actually, what we should do is print this out. 108 00:05:42,900 --> 00:05:46,800 'print("Name is ", name)'. 109 00:05:46,800 --> 00:05:48,600 There we go. That's actually going to work for us. 110 00:05:49,600 --> 00:05:53,100 And so remember, it's going to go from the inside to the outside. 111 00:05:53,100 --> 00:05:54,620 And so we're running 'greeting', 112 00:05:54,620 --> 00:05:56,600 but inside of 'greeting' it's running 'say_hello', 113 00:05:56,600 --> 00:06:00,100 so it's running another function in here, and that 'name' is 114 00:06:00,100 --> 00:06:01,200 currently "Henry". 115 00:06:02,500 --> 00:06:07,000 And so if we have this correct, this should say 'Name is Henry", 116 00:06:08,700 --> 00:06:09,700 as we expect. 117 00:06:09,700 --> 00:06:12,400 But let's comment this out, 118 00:06:12,400 --> 00:06:15,200 so that 'name' effectively no longer exists inside of the 119 00:06:15,200 --> 00:06:16,600 'say_hello' function. 120 00:06:16,640 --> 00:06:19,640 We run this again, and it's going to say "Zephyr", because 121 00:06:19,640 --> 00:06:23,000 I can't find it in here, but it's going to look just outside of its function. 122 00:06:24,000 --> 00:06:27,200 Now, let's say 'name' doesn't exist inside of 'greeting'. 123 00:06:27,900 --> 00:06:30,000 Well, because it's looking for a 'name' here, it doesn't exist; 124 00:06:30,040 --> 00:06:32,400 it's looking for a 'name' in here, also doesn't exist; 125 00:06:32,410 --> 00:06:36,080 it's now going to look outside of all of the functions in 126 00:06:36,080 --> 00:06:37,300 the global scope. 127 00:06:37,300 --> 00:06:39,500 Let's run this cell and run that once more, and we're going 128 00:06:39,500 --> 00:06:40,700 to see the "Name is Kalob". 129 00:06:40,700 --> 00:06:44,100 Now, what this means, is you can create a function in here 130 00:06:44,180 --> 00:06:46,220 with absolutely no variables, 131 00:06:46,230 --> 00:06:48,860 and as long as there is a variable that it's using that's 132 00:06:48,860 --> 00:06:50,700 outside of it, you can use it. 133 00:06:50,720 --> 00:06:52,280 Now, that sounds a little crazy. 134 00:06:52,280 --> 00:06:58,400 But let's say the 'website = "pythonforverybody.com", 135 00:06:59,200 --> 00:07:02,600 and we have a new function in here called 'def get_website'. 136 00:07:02,600 --> 00:07:05,100 We can 'return website'. 137 00:07:05,100 --> 00:07:09,700 And when we run 'get_website', this will return 'pythonforeverybody.com', 138 00:07:09,700 --> 00:07:11,600 despite the fact that there is no variable 139 00:07:11,600 --> 00:07:14,400 in here, and that's because it exists just outside of the 140 00:07:14,400 --> 00:07:15,800 function scope. 141 00:07:16,100 --> 00:07:21,110 But we can now say 'website = 'nothing because Kalob 142 00:07:21,200 --> 00:07:22,700 ruined this''. 143 00:07:22,700 --> 00:07:24,900 [no audio] 144 00:07:24,900 --> 00:07:27,300 It now exists in here, so it exists in two places, but the 145 00:07:27,330 --> 00:07:28,910 function is going to look inside of itself 146 00:07:28,910 --> 00:07:29,900 first. Says, "Oh, yep. 147 00:07:29,900 --> 00:07:33,000 Okay, there is actually a variable called website. 148 00:07:33,900 --> 00:07:35,600 So let's use that one". 149 00:07:35,670 --> 00:07:39,430 But again, if that variable didn't exist in here, it would 150 00:07:39,440 --> 00:07:40,600 look in the global scope. 151 00:07:40,610 --> 00:07:44,020 Now, that's actually sort of a really bad way of using a 152 00:07:44,050 --> 00:07:46,750 function, and that can get very, very confusing for other 153 00:07:46,760 --> 00:07:48,130 people who are looking at your code. 154 00:07:48,430 --> 00:07:51,640 So typically we avoid that, and we just put the 'website' 155 00:07:51,650 --> 00:07:56,060 in here. So the 'website' could be "pythonforeverybody.com" 156 00:07:56,060 --> 00:07:58,500 as a default, and that would be fine. 157 00:07:59,900 --> 00:08:04,900 We can get rid of this, or we could overwrite this with, "anything 158 00:08:04,980 --> 00:08:09,630 else", assuming I could spell. There we go. 159 00:08:10,000 --> 00:08:11,000 "anything else". 160 00:08:11,050 --> 00:08:15,390 And so this is a much better way than leveraging the Python 161 00:08:15,400 --> 00:08:18,530 scope. Now, if you come from JavaScript, it's not uncommon 162 00:08:18,540 --> 00:08:20,900 for JavaScript to leverage its own scope like that. 163 00:08:20,910 --> 00:08:23,120 But in Python, we try really hard not to do that. 164 00:08:23,130 --> 00:08:27,270 We try to explicitly pass in data into our functions just 165 00:08:27,270 --> 00:08:30,500 so we know exactly what's going on in here. 166 00:08:30,520 --> 00:08:34,630 And the reason for that is if I just gave you this piece 167 00:08:34,640 --> 00:08:35,830 of code here, that's a 'def 168 00:08:35,860 --> 00:08:37,510 get_website', and 'return website', 169 00:08:37,510 --> 00:08:39,530 but you didn't know where 'website' came from. 170 00:08:39,539 --> 00:08:42,020 Maybe you're looking at a file that has 2,000 lines of code, 171 00:08:42,030 --> 00:08:45,559 and you can't seem to find this variable, that's going to 172 00:08:45,570 --> 00:08:47,630 be very confusing because you're going to look at this, and say, 173 00:08:47,630 --> 00:08:50,600 "Yep, this is a function, and it's returning a variable called website. 174 00:08:50,600 --> 00:08:52,039 But where is website?" 175 00:08:52,600 --> 00:08:56,299 And if you have to stop and ask yourself, where is that, 176 00:08:56,299 --> 00:09:01,400 then that's probably a good case for using a function argument 177 00:09:01,400 --> 00:09:02,400 or a parameter. 178 00:09:02,400 --> 00:09:03,500 [no audio]