WEBVTT 1 00:00:01.230 --> 00:00:04.970 so I mentioned at the end of the previous video the parabola function 2 00:00:04.970 --> 00:00:10.010 itself on line 7 isn't really doing all it could do though because the main 3 00:00:10.010 --> 00:00:15.059 program needs still needs to loop through on line 34 where the loop is starting on line 34 4 00:00:15.059 --> 00:00:20.480 and go through all the values it returns in order to print a parabola so 5 00:00:20.480 --> 00:00:24.009 I think it'd be more useful if the function plotted the points and all we 6 00:00:24.009 --> 00:00:28.249 had to do was tell it how big the parabola should be and then give it a 7 00:00:28.249 --> 00:00:33.460 canvas to draw on now before we get into that though I just want to talk about 8 00:00:33.460 --> 00:00:36.710 some of the warnings that are on the screen and remember these warnings here on the 9 00:00:36.710 --> 00:00:40.989 right hand side let's just fix a couple of these up so the first one is at least 10 00:00:40.989 --> 00:00:44.989 two spaces so I made a mistake we need 2 spaces when we are putting a comment 11 00:00:44.989 --> 00:00:49.320 in line at the end of a line so that should fix that one up the second one 12 00:00:49.320 --> 00:00:53.899 camel case variable import as lower case that's because we're doing import with a 13 00:00:53.899 --> 00:00:59.489 capital T for Tkinter and s the lowercase Tkinter for Pythont 2 so that is ok we 14 00:00:59.489 --> 00:01:04.879 don't need to fix that but these other ones here are all the same shadow name x show named 15 00:01:04.879 --> 00:01:10.510 Shadow named canvas the errors is the same basically it's a different name but 16 00:01:10.510 --> 00:01:16.070 shadow name from out of scope is the error now what it is is one of the variables 17 00:01:16.070 --> 00:01:20.890 in our function shadows of variable with the same name in the main program 18 00:01:20.890 --> 00:01:27.700 so the first one actually reads if you go back here and have a look actually we will do a better 19 00:01:27.700 --> 00:01:33.730 example come down here to the canvas so shadow name canvas from outer scope 20 00:01:33.730 --> 00:01:38.720 inspection that detects shadowing names defining outer scope so when they talk about 21 00:01:38.720 --> 00:01:43.630 the outer scope what they mean is the main program where we created a variable 22 00:01:43.630 --> 00:01:47.820 called canvas and you can see that we did get on line 29 the errors actually 23 00:01:47.820 --> 00:01:51.950 coming up talking about the canvas variable that is defined on line 12 as a 24 00:01:51.950 --> 00:01:56.070 parameter to the draw_axis function and that's because when I 25 00:01:56.070 --> 00:01:59.690 gave the parameter to the draw_axis function and name it canvas it the function 26 00:01:59.690 --> 00:02:04.710 then lost the ability to see the canvas variable in the main program that's 27 00:02:04.710 --> 00:02:09.530 because they're both the same name so all references to canvas within the draw_axis 28 00:02:09.530 --> 00:02:11.540 function 29 00:02:11.540 --> 00:02:16.480 mean that the perimeter referred to the parameter that was passed in and not the 30 00:02:16.480 --> 00:02:20.560 canvas variable from the main part of the program even thought they are called the same thing 31 00:02:20.560 --> 00:02:24.989 that's actually the reason why its confusing so it's really important to 32 00:02:24.989 --> 00:02:29.950 understand this variable scope as this is what it is and as 33 00:02:29.950 --> 00:02:33.819 functions are one of the few big things in Python that actually introduce new scope 34 00:02:33.819 --> 00:02:37.189 it's worth spending a bit of time here just to understand that so you are aware 35 00:02:37.189 --> 00:02:41.219 of how this actually works so to explain the difference between the canvas that 36 00:02:41.219 --> 00:02:45.889 is local to the draw_axis function and the one thats global what we gotta do is 37 00:02:45.889 --> 00:02:50.090 create another canvas and then side those both so that they can each occupies half 38 00:02:50.090 --> 00:02:52.760 of the window now our original canvas 39 00:02:52.760 --> 00:02:58.650 will need its width changed to 2320 and this is one on line 29 and the reason for that is 40 00:02:58.650 --> 00:03:02.269 because we gotta put two canvases where there was one before the same space so 41 00:03:02.269 --> 00:03:05.010 if you're using a larger width and height 42 00:03:05.010 --> 00:03:09.379 you will just basically divide it by 2 in this case we are going to make it 320 that's the first one 43 00:03:09.379 --> 00:03:17.139 and we are adding it to grid which is correct but then we are gonna add the second variable..... 44 00:03:17.139 --> 00:03:28.489 ..... 45 00:03:28.489 --> 00:03:34.609 ....the difference will be on the next line we're going to 46 00:03:34.609 --> 00:03:38.489 add it into the next column so of course it appears to the right hand side so... 47 00:03:38.489 --> 00:03:45.099 ..... 48 00:03:45.099 --> 00:03:53.709 ...and we got a draw_axis function on line 35 which is correct but on line 49 00:03:53.709 --> 00:03:58.629 36 we're going to add the draw_axis for the other side so....... 50 00:03:58.629 --> 00:04:03.389 ....so just confirming that if we actually 51 00:04:03.389 --> 00:04:10.530 run that to see that it does work and you could see it basically got 52 00:04:10.530 --> 00:04:13.750 two canvases now we've got to the first canvas which were drawing on the half 53 00:04:14.530 --> 00:04:18.349 basically left hand side of the screen and our parabola drawing just on 54 00:04:18.349 --> 00:04:22.019 that and we also got this canvas on the right hand side as well 55 00:04:22.019 --> 00:04:25.509 and we are drawing the axis to that so in the past in the previous program of course 56 00:04:25.509 --> 00:04:31.169 it was just one occupying the entire 640 by 480 for our window so that's working 57 00:04:31.169 --> 00:04:35.909 and actually what I didn't do what I might do now is I am going to come back here just to make it a bit more obvious 58 00:04:35.909 --> 00:04:43.310 and then I'm gonna put.... 59 00:04:43.310 --> 00:04:48.409 ....and that will make it clearer because we got a blue background as you can 60 00:04:48.409 --> 00:04:52.819 probably guess that will do now its a little bit more obvious now that we got this new 61 00:04:52.819 --> 00:04:57.590 canvas which we actually added which is now got a blue background ok so each time it's called 62 00:04:57.590 --> 00:05:01.650 it's own variable called canvas is assigned the canvas object that is pass to 63 00:05:01.650 --> 00:05:07.180 the parameter in the call so here basically on line 35 passes up a 64 00:05:07.180 --> 00:05:12.000 passes the canvas object and the passes on to line 12 to the draw_axis 65 00:05:12.000 --> 00:05:17.340 function the that calls that canvasses as well and likewise for canvas 2 even though we 66 00:05:17.340 --> 00:05:21.289 referred to it as canvas 2 its referred to as canvas for the function 67 00:05:21.289 --> 00:05:25.219 name and it's going to be using that name when it's processing that for also for canvas 2 68 00:05:25.219 --> 00:05:29.889 now we can see that a little bit better by printing out some details of the canvas 69 00:05:29.889 --> 00:05:34.710 objects so there's a function that shows the representation of the object called 70 00:05:34.710 --> 00:05:39.699 repr r-e-p-r so let's just put that in and you can actually just sort of 71 00:05:39.699 --> 00:05:44.349 print out some details about an object in a format suitable for printing 72 00:05:44.349 --> 00:05:55.240 so i can type.......and that will just printed 73 00:05:55.240 --> 00:05:59.190 it out each time it's called it's going to print out the basically the memory reserved 74 00:05:59.190 --> 00:06:03.090 so if we just run that to confirm it is actually working you notice now that we've actually got this 75 00:06:03.090 --> 00:06:08.419 little print out on the screen now and you can see here the number at the end of each 76 00:06:08.419 --> 00:06:13.680 part of this tkinter.Canvas object print out is meant to represent the memory 77 00:06:13.680 --> 00:06:17.840 location where that particular object was created in memory so obviously there 78 00:06:17.840 --> 00:06:20.779 we got a different number in both cases in which means that they're obviously 79 00:06:20.779 --> 00:06:23.870 separate objects which is correct but the other thing is just out of interest 80 00:06:23.870 --> 00:06:30.139 if we stop this close it and run again you will note those numbers will be different 81 00:06:30.700 --> 00:06:34.260 basically different each time you run the program different in that these will be 82 00:06:34.260 --> 00:06:38.020 different to each other because they are separate objects but also the individual 83 00:06:38.020 --> 00:06:42.190 numbers allocated to each object is also different because the computer every 84 00:06:42.190 --> 00:06:46.950 time you run it is a assigning its using making a decision where to put these in memory and 85 00:06:46.950 --> 00:06:51.280 that changes each time you run it and no doubt these numbers are likely to be 86 00:06:51.280 --> 00:06:55.420 a bit different when you run it on your computer as well that's good so we can see that their 87 00:06:55.420 --> 00:06:58.420 separate objects 88 00:06:59.780 --> 00:07:03.230 but what is also cool is we can print local variables 89 00:07:03.920 --> 00:07:08.120 so Python has this ability called using the locals function to print out all the 90 00:07:08.120 --> 00:07:14.100 local variables for a method so what we can do is make a change to that so lets put this at the end of 91 00:07:14.100 --> 00:07:20.490 line 18 so type....and that is the locals is the method that enables a printout of 92 00:07:20.490 --> 00:07:24.430 all the variables that have been defined for that particular function obviously 93 00:07:24.430 --> 00:07:27.950 has to be the code has to be in a function too be called its 94 00:07:27.950 --> 00:07:32.810 going to just basically look at all the variables in that function so if we run 95 00:07:32.810 --> 00:07:40.570 that you can see their its showing us that we got the canvas object and note that the numbers here 96 00:07:40.570 --> 00:07:44.370 so for the first time we call it canvas represents the same variable 97 00:07:44.370 --> 00:07:49.060 canvas this first one here as we pointed that out and then also its got a y location 98 00:07:49.060 --> 00:07:56.060 y_origin and x_origin and that is the variables that we are creating on line 14 and 15 but note 99 00:07:56.060 --> 00:08:00.000 that we are getting consistency here we got the number their corresponding to that 100 00:08:00.000 --> 00:08:03.120 number the first time it's called and the second time that number corresponds to 101 00:08:03.120 --> 00:08:07.000 that one so we can see that it actually is working so it can be useful tool when 102 00:08:07.000 --> 00:08:10.490 you're debugging to have the locals function and also the representation code 103 00:08:11.310 --> 00:08:15.600 the repr function as well so you think at this point ok so everything's working fine 104 00:08:15.600 --> 00:08:20.320 so why is IntelliJ actually coming up with these warnings what is the problem 105 00:08:20.320 --> 00:08:24.190 well firstly with a small program like this where we can pretty much see 106 00:08:24.190 --> 00:08:27.740 everything at once on the screen is not really that big a deal I mean all the 107 00:08:27.740 --> 00:08:31.650 codes there on the screen we can access it and you probably not gonna get into 108 00:08:31.650 --> 00:08:35.430 difficulty but chances are that you gonna be ending up writing much larger 109 00:08:35.430 --> 00:08:39.950 programs and you can find it can cause unexpected problems if we make a mistake 110 00:08:39.950 --> 00:08:42.590 somewhere pretty much I can guarantee that will happen on 111 00:08:42.590 --> 00:08:48.350 some point on your programming journey that you make a mistake so what I'm going to do is 112 00:08:48.350 --> 00:08:52.840 simulate one possible mistakes in the way to simulate that is to rename the 113 00:08:52.840 --> 00:08:58.190 parameter canvas and to call a page so I'm talking about the parameter here 114 00:08:58.190 --> 00:09:04.310 on line 12 so we are gonna change that to page you can see their and we need to make a few 115 00:09:04.310 --> 00:09:10.020 other changes we need to call this now page.update so..... 116 00:09:10.020 --> 00:09:12.800 and as I'm going to be doing this you might be thinking well Tim why aren't you using the 117 00:09:12.800 --> 00:09:14.540 refactor facility 118 00:09:14.540 --> 00:09:18.980 well it's slightly contrived example here because obviously that would 119 00:09:18.980 --> 00:09:22.220 automatically rename all occurrences for us but it's possible that you might 120 00:09:22.220 --> 00:09:25.590 be making a quick change using some other editor as I'm doing it manually 121 00:09:25.590 --> 00:09:29.490 to simulate a potential problem so lets just assume I did that and I remembered most 122 00:09:29.490 --> 00:09:31.430 of these so I'll change that one as well 123 00:09:31.430 --> 00:09:38.200 ..... 124 00:09:38.200 --> 00:09:42.990 ......so if I actually run this having knowing that I forgot to make the change on line 125 00:09:42.990 --> 00:09:50.370 18 and you notice we've got a different output here we've got no y axis 126 00:09:50.370 --> 00:09:54.170 showing in the right hand canvas so you might be looking at that thinking well 127 00:09:54.170 --> 00:09:56.150 why that suddenly stopped working 128 00:09:56.150 --> 00:10:00.610 you know if you made this quick change like I have and you neglected to make that change as I did 129 00:10:00.610 --> 00:10:07.870 on line 18 and what I need to do is run it again so we can see now that with the output from 130 00:10:07.870 --> 00:10:13.400 the locals function that the variables is called page so on line 18 the yaxis is 131 00:10:13.400 --> 00:10:17.580 being drawn on the canvas from the main program so that one has its axis drawn 132 00:10:17.580 --> 00:10:21.050 twice effectively so I basically we can see what's happening their the canvas 133 00:10:21.050 --> 00:10:26.160 variable that's been referred to their on line 18 is actually the canvass 134 00:10:26.160 --> 00:10:29.720 variable that was defined in the main part of the 135 00:10:29.720 --> 00:10:33.780 program and not from this function now again I did say this was a bit contrived 136 00:10:33.780 --> 00:10:38.180 but if I originally called the parameter graph instead of canvas for arguments sake so if we 137 00:10:38.180 --> 00:10:39.190 comeback and do that lets 138 00:10:39.190 --> 00:10:42.190 presume that it was called graph...... 139 00:10:44.470 --> 00:10:49.730 and we actually run this clearly we get a different error altogether and the reason we've now got 140 00:10:49.730 --> 00:10:54.490 an error is it Python notice that ok this variable graph doesn't exist we are not 141 00:10:54.490 --> 00:11:01.650 shadowing the canvas variable from the main program anymore and consequently 142 00:11:01.650 --> 00:11:05.210 we've got you know we know that there's a problem we can actually fix it this is 143 00:11:05.210 --> 00:11:09.880 probably not only crops up if you try to use a name the same name in your 144 00:11:09.880 --> 00:11:13.800 parameter as your using for your variable that is defined in the main part of the program so 145 00:11:13.800 --> 00:11:17.540 although python did mind that local main variables have the same name it can 146 00:11:17.540 --> 00:11:21.230 be a source error and that's one reason why IntelliJ is warning you about that for 147 00:11:21.230 --> 00:11:25.280 these types of errors that you might run into and it's probably a bad idea to 148 00:11:25.280 --> 00:11:29.070 have the same names but with that said there's also another reason why 149 00:11:29.070 --> 00:11:33.010 shadowing is a bad idea in Python and will have a look at that a little bit 150 00:11:33.010 --> 00:11:38.140 later so this example has also hopefully demonstrated the scope of the variables 151 00:11:38.140 --> 00:11:41.870 so draw axis has its own local variable called canvas 152 00:11:41.870 --> 00:11:46.830 that is now called page and in the main program there were two canvases called canvas and canvas 2 153 00:11:46.830 --> 00:11:51.920 but inside the draw_axis function we can and did actually refer to the 154 00:11:51.920 --> 00:11:56.080 canvas from the main program but if we now we try to refer to pages in main program 155 00:11:56.080 --> 00:12:01.910 it won't work so it doesn't go 2 ways so firstly I'll fix this Graph put that back to page so 156 00:12:01.910 --> 00:12:05.620 clearly in the draw_axis function we're able to refer to these variables 157 00:12:05.620 --> 00:12:09.620 defined in the main part of the program of the Python program but we can't do 158 00:12:09.620 --> 00:12:14.070 things in other ways in other words we can't come back here for example and put print 159 00:12:14.070 --> 00:12:23.150 ...if you try to do that you can already see you got an error and if we try to run it name page is not defined and that is 160 00:12:23.150 --> 00:12:28.590 because we're a variable is visible it can be used is called scope and that's really 161 00:12:28.590 --> 00:12:32.040 all there is to understanding the scope in Python now their is some other some other things we 162 00:12:32.040 --> 00:12:36.280 can do to specify the scope of a variable but we'll look at that later but for now 163 00:12:36.280 --> 00:12:40.560 just remember that a function can use the variables from the main program but 164 00:12:40.560 --> 00:12:45.250 the main program cannot see variables that are local to the function so I'm gonna 165 00:12:45.250 --> 00:12:51.610 end the video here actually what I'll do before I end I'm gonna delete line 40 so 166 00:12:51.610 --> 00:12:54.520 that we haven't got any code errors their 167 00:12:54.520 --> 00:12:57.910 and will continue on with this in the next video