WEBVTT 1 00:00:01.920 --> 00:00:06.790 ok so moving on what will do now in the deal_player function 2 00:00:06.790 --> 00:00:12.059 is will just add that command that we saw in the previous video to print all the local 3 00:00:12.059 --> 00:00:16.789 variables just so we're 100% clear on which variables are local to the deal_player 4 00:00:16.789 --> 00:00:20.850 function so you can do this right down here at the bottom will do 5 00:00:20.850 --> 00:00:27.160 a print out....and that is going 6 00:00:27.160 --> 00:00:32.219 to do just that print a list of all the local variables so if we run the program 7 00:00:32.219 --> 00:00:44.059 now and go back to our game that is running click the player function and 8 00:00:44.059 --> 00:00:48.159 you can see card_value which has a score of 10 or value of ten and player_score 9 00:00:48.159 --> 00:00:54.280 which also has a value of ten they are he 2 only local variables in this 10 00:00:54.280 --> 00:00:59.449 function so it can really be useful because any confusion in your programs to use this 11 00:00:59.449 --> 00:01:07.270 locals function to call just so you are aware fully which variables are local ok and it 12 00:01:07.270 --> 00:01:10.920 just bares repeating the rule again one more time when you use the name of a 13 00:01:10.920 --> 00:01:16.100 global variable inside a function Python is going to use the global variable as 14 00:01:16.100 --> 00:01:20.640 long as you don't assign a new value to it as soon as you add code that tries to 15 00:01:20.640 --> 00:01:25.469 change the value the variable itself becomes local and shadows the global 16 00:01:25.469 --> 00:01:29.750 variable with the same name so because the function assigns the value in 17 00:01:29.750 --> 00:01:34.759 this case 0 to players_score I'm talking about the code on line 47 player_score 18 00:01:34.759 --> 00:01:39.060 becomes local to the function and because no values was assigned to player_ace 19 00:01:39.060 --> 00:01:44.289 we've only used the value we haven't actually stored anything in there it's still 20 00:01:44.289 --> 00:01:48.429 refers to the global variable that also means that you can have a function that 21 00:01:48.429 --> 00:01:53.159 happily using a global variable but will suddenly switched to being local if you 22 00:01:53.159 --> 00:01:56.619 happen to add code to change the value of the variable and that can be really really 23 00:01:56.619 --> 00:02:02.210 a gotcha their that will start potentially unpredictable things or giving you unpredictable results 24 00:02:02.210 --> 00:02:07.609 in your program now the deal_player function provides a 25 00:02:07.609 --> 00:02:09.929 good way to see this in action because 26 00:02:09.929 --> 00:02:14.819 should actually change the value of player_ace and looking at the code on 27 00:02:14.819 --> 00:02:19.909 line 50 the card values is set to 11 if this is the first ace dealt so if that 28 00:02:19.909 --> 00:02:23.760 is the case then what we really should be doing is setting player_ace the 29 00:02:23.760 --> 00:02:27.540 variable player_ace to true so that we know that there is a ace with a 30 00:02:27.540 --> 00:02:29.010 value 11 31 00:02:29.010 --> 00:02:34.189 so similarly you should also set to false when we subtract 10 from score on line 54 so 32 00:02:34.189 --> 00:02:42.819 if you go ahead and add it to line 50 so up here and we put.... 33 00:02:45.010 --> 00:02:48.419 now immediately we gonna get an error well two things happen when we did that 34 00:02:48.419 --> 00:02:51.689 there's an error on now on line 49 35 00:02:51.689 --> 00:02:57.200 and also IntelliJ is now warning about player_ace shadowing the global variable 36 00:02:57.200 --> 00:03:02.980 of the same name so the errors is unresolved reference player_ace and this can 37 00:03:02.980 --> 00:03:08.010 be confusing probably thinking well hang on player_ace tim you've just told me 38 00:03:08.010 --> 00:03:13.189 that that's a global variable why isn't that working well again because we've assigned a value 39 00:03:13.189 --> 00:03:17.579 assigned a value now on line 50 what's actually happened is its now being 40 00:03:17.579 --> 00:03:23.489 converted into a variable a local variable for this method and on line 49 when we're 41 00:03:23.489 --> 00:03:28.329 doing a test for the value it hasn't been initialize it hasn't been created as 42 00:03:28.329 --> 00:03:31.180 such and it doesn't exist so that's its coming and saying unresolved 43 00:03:31.180 --> 00:03:37.290 reference to player_ace and the other era in terms of the shadowing 44 00:03:37.290 --> 00:03:40.189 name well we talk about that extensively we know why that's coming up and that's 45 00:03:40.189 --> 00:03:44.540 just because we're using the same variable name of the variable in the 46 00:03:44.540 --> 00:03:51.109 global variable as we are in this case in the local variable so deal_player wasn't working 47 00:03:51.109 --> 00:03:55.290 function but as soon as perfectly valid assignment on line 50 was actually added 48 00:03:55.290 --> 00:03:59.829 then we started getting an error now before you actually gone 49 00:03:59.829 --> 00:04:04.169 through this video this type of error would probably have driven you nuts now though 50 00:04:04.169 --> 00:04:07.400 you can see why the IntelliJ warnings are coming up and immediately know 51 00:04:07.400 --> 00:04:12.509 what's going on so in a while what I'm gonna do is rewrite the function so that 52 00:04:12.509 --> 00:04:17.079 it doesn't try to make use of global variables ideally a function should be 53 00:04:17.079 --> 00:04:21.250 self-contained and not make changes to anything outside itself now when a 54 00:04:21.250 --> 00:04:22.860 function does change things like 55 00:04:22.860 --> 00:04:26.669 global variables the changes are know as side effects and it should really be avoided 56 00:04:26.669 --> 00:04:30.289 wherever possible but with that said sometimes side effects 57 00:04:30.289 --> 00:04:35.050 are necessary so they are allowed but aren't discouraged Python 58 00:04:35.050 --> 00:04:39.710 automatically changing a global variable to local when you try to change when you 59 00:04:39.710 --> 00:04:43.550 try to change it is Python's way of discouraging us from doing that because 60 00:04:43.550 --> 00:04:47.650 they are occasionally necessary Python does provide a way to make changes to global 61 00:04:47.650 --> 00:04:51.569 variables within a function because of course this is what the problem is here we 62 00:04:51.569 --> 00:04:56.400 actually on line 50 when it change the value of a global variable and it's not 63 00:04:56.400 --> 00:04:59.699 allowing us to do that because as soon as we've type in the same name and type in 64 00:04:59.699 --> 00:05:04.710 an assignment to save a value to that variable it's created a 65 00:05:04.710 --> 00:05:09.029 local variable and then consequently in this case we got an error saying that 66 00:05:09.550 --> 00:05:13.810 as of line 49 that variable didn't exist so how do we go about changing a global 67 00:05:13.810 --> 00:05:17.719 variable well the way to do that is to specify that your intent on using global 68 00:05:17.719 --> 00:05:22.490 variable by using the global keyword but before doing that let's get rid of the 69 00:05:22.490 --> 00:05:26.129 error on this line that sets player score to 0 every time the function is 70 00:05:26.129 --> 00:05:32.120 called because that shouldn't be there this is the code on line 467 because we really do want to use the 71 00:05:32.120 --> 00:05:38.339 the score actually saved globally so let's go ahead and delete that and as soon 72 00:05:38.339 --> 00:05:45.250 as we have done that you can see now their are other errors on line 51 53 54 55 and 56 their is now errors 73 00:05:45.250 --> 00:05:49.509 relating to player_score so before I hover over and show you what the 74 00:05:49.509 --> 00:05:53.580 error is and taking into account what I've said in the video the mini challenge 75 00:05:53.580 --> 00:05:57.449 for you is to answer this question and it's why is now their an error when players_score 76 00:05:57.449 --> 00:06:00.990 is being accessed and the hint here is that we've talked about this 77 00:06:00.990 --> 00:06:05.620 player_ace so have a think about that pause the video and try and figure out why 78 00:06:05.620 --> 00:06:09.779 we're getting an error with player_score now and when we come back i'll go through that with you 79 00:06:11.969 --> 00:06:18.549 ok hopefully that made sense in terms of why that error came up and what it is it's really the 80 00:06:18.549 --> 00:06:22.229 same reason that player_ace returned an error and of course I talked about 81 00:06:22.229 --> 00:06:25.909 that earlier in this video so by removing the assignment that I did when I 82 00:06:25.909 --> 00:06:30.669 deleted line 47 player_score now doesn't have a value as far as 83 00:06:30.669 --> 00:06:34.269 this functions concerned and this is just primarily because we're trying to save 84 00:06:34.269 --> 00:06:38.309 a value into player_score so as of the code on line 51 player_score 85 00:06:39.219 --> 00:06:43.829 doesn't exist as a variable because of the shadowing functionality 86 00:06:43.829 --> 00:06:47.419 that Python does that the local variable variable hasn't been initialized and 87 00:06:47.419 --> 00:06:50.929 that's why we are getting those errors again similarly to what was happening with 88 00:06:50.929 --> 00:06:54.789 player_ace and specifically the augmented assignment like we're seeing 89 00:06:54.789 --> 00:06:59.409 on line 51 requires that the variable already has a value and of course because 90 00:06:59.409 --> 00:07:03.659 of the shadowing technique Python knows that we're using a variable of the same 91 00:07:03.659 --> 00:07:07.969 name and it's trying to create it would normally create a local variable but we 92 00:07:07.969 --> 00:07:11.419 haven't actually done that we haven't initialized that variable at this point 93 00:07:11.419 --> 00:07:15.889 in time because their assignments player_score is still a local variable 94 00:07:15.889 --> 00:07:20.829 but of course we just deleted the line that gave it a value ok so enough talks so how in 95 00:07:20.829 --> 00:07:25.249 other words do we get the function in this case to use the global variables of 96 00:07:25.249 --> 00:07:29.679 the same name well to tell Python we want to used the global variables we just use the global 97 00:07:29.679 --> 00:07:34.249 keyword at the start of the function so we came up here and on line 47 I'm gonna add 98 00:07:34.249 --> 00:07:44.959 global.....and what that immediately 99 00:07:44.959 --> 00:07:50.679 tells the function to use is to use the global versions of those variables and 100 00:07:50.679 --> 00:07:54.759 not trying to create a local variable of the same name and consequently 101 00:07:54.759 --> 00:07:58.969 all the errors disappear at that point in time and also the 102 00:07:58.969 --> 00:08:02.879 the errors about shadowing or the warnings about 103 00:08:02.879 --> 00:08:06.329 shadowing have also disappeared as well because in fact we're not shadowing 104 00:08:06.329 --> 00:08:10.999 anymore because the global keyword essentially is really as I said 105 00:08:10.999 --> 00:08:14.749 telling the function to use the global variables from this point forward in 106 00:08:14.749 --> 00:08:20.319 that function so now if we run the program again and actually I need to make another 107 00:08:20.319 --> 00:08:21.650 change so just close it down 108 00:08:21.650 --> 00:08:26.710 before we do that because we needed to make the change here to add player_ace = 109 00:08:26.710 --> 00:08:27.280 false 110 00:08:27.280 --> 00:08:32.080 so when we are deducting 10 from the ace if you recall we need to actually say.... 111 00:08:32.080 --> 00:08:39.210 .....so basically if the card value is 1 in other words an ace and they haven't already 112 00:08:39.210 --> 00:08:43.839 got an ace then we're going to assign the player_ace variable which now global to 113 00:08:43.839 --> 00:08:49.240 true but in the case of where there was an ace their was an ace being treated as a 114 00:08:49.240 --> 00:08:54.110 value of 11 and we've detected 10 from it then for all intent and purposes we haven't got 115 00:08:54.110 --> 00:09:02.589 that ace any more we are setting it back to false so now we should be able to run this and now when we run it 116 00:09:11.840 --> 00:09:19.380 we click on player a value of ten their value of twenty and one more and we get the 117 00:09:19.380 --> 00:09:22.380 right message correctly coming up now saying dealer wins so it's obviously 118 00:09:22.380 --> 00:09:26.670 working out clearly it's using the global scope and just make sure this is 119 00:09:26.670 --> 00:09:39.560 working and it's random running game again their is an ace 11 oh we got 21 we got blackjack now obviously 120 00:09:39.560 --> 00:09:43.070 we haven't got a calculation in here to check for blackjack we actually only 121 00:09:43.070 --> 00:09:47.040 doing the score here score check if the player scores greater than 21 122 00:09:47.740 --> 00:09:51.090 we are not basically figuring out whether the players won yet and we should bust 123 00:09:51.090 --> 00:09:54.920 and if we click on one now it is clearly it's just drawing random cards so its all working nicely 124 00:09:54.920 --> 00:10:00.040 so what we've determined now is that Python does allow 125 00:10:00.040 --> 00:10:03.910 global variables to be modified inside a function because of course that was the 126 00:10:03.910 --> 00:10:07.780 problem we're always been able to get access to global variables but we're 127 00:10:07.780 --> 00:10:12.230 talking specifically about changing those variables changing the values to 128 00:10:12.230 --> 00:10:15.650 do that in a function you need to use the global keyword that I've 129 00:10:15.650 --> 00:10:20.400 shown you how to use on line 47 through 48 so the functions now working as we saw 130 00:10:20.400 --> 00:10:25.510 when we ran the game but if this functions modifying the two global variables player_score 131 00:10:25.510 --> 00:10:30.050 and player_ace how can we will be sure that some other function isn't also 132 00:10:30.050 --> 00:10:34.300 changing them and its quite possible when a game in that could happen and if something else 133 00:10:34.300 --> 00:10:37.650 does change them then the deal_plater function is no longer going to work 134 00:10:37.650 --> 00:10:41.510 correctly because it really is assuming that it's got full control over those 135 00:10:41.510 --> 00:10:46.270 variables or the way that the code has been written and this is the main reason why 136 00:10:46.270 --> 00:10:49.690 side effects are discouraged and why functions really should only be modified 137 00:10:49.690 --> 00:10:55.780 varaibles in the outer scope i.e. globally if there's really no other way to perform 138 00:10:55.780 --> 00:10:58.790 the functionality that are you creating and usually there is actually way 139 00:10:58.790 --> 00:11:03.170 around so before we write in the function to remove the side effects it is actually 140 00:11:03.170 --> 00:11:08.140 worth revisiting the design so the deal_player gets a new card and 141 00:11:08.140 --> 00:11:12.330 maintains a total by adding the value of that card to its tally and that 142 00:11:12.330 --> 00:11:15.410 tallies now stored in player_score as a global variable 143 00:11:16.339 --> 00:11:19.949 and we are gonna have to do the same thing for the dealers so it may make sense to 144 00:11:19.949 --> 00:11:24.759 create a function that returns a score if it's given a list of cards so what we 145 00:11:24.759 --> 00:11:28.870 gonna do is we are going to add a score _hand function and its purpose is 146 00:11:28.870 --> 00:11:33.779 to do that it to look at a hand and calculate a score based on that hand so 147 00:11:33.779 --> 00:11:41.309 we are gonna create that under deal_cards so down here we are gonna call it... 148 00:11:41.309 --> 00:11:45.870 .... 149 00:11:46.610 --> 00:11:54.589 .... 150 00:11:54.589 --> 00:12:18.420 ..... 151 00:12:18.420 --> 00:12:24.720 ....because when we first 152 00:12:24.720 --> 00:12:30.309 starting we haven't got any cards so obviously we haven't got an ace and lets go through all the cards so.... 153 00:12:30.309 --> 00:12:33.339 .... 154 00:12:33.339 --> 00:12:44.749 ...... 155 00:12:44.749 --> 00:13:22.370 .... 156 00:13:22.370 --> 00:13:27.630 ..... 157 00:13:27.630 --> 00:13:34.690 .... 158 00:13:34.690 --> 00:13:42.300 ..... 159 00:13:42.880 --> 00:13:50.000 .... 160 00:13:50.000 --> 00:13:58.040 .....and that's basically the method that's the 161 00:13:58.040 --> 00:14:06.760 loop that goes through each hand then when we finish we return the score so given a list 162 00:14:06.760 --> 00:14:10.630 containing tuples wether the first item in the tuple is the value that function is going 163 00:14:10.630 --> 00:14:15.190 add up all the values and return the score and as I mention the first ace will have the value 11 164 00:14:15.190 --> 00:14:20.240 rather than 1 and if the total score goes above 21 and there is at least one ace then 165 00:14:20.240 --> 00:14:23.730 the total has decreased by 10 and hopefully the player won't have busted but in 166 00:14:23.730 --> 00:14:27.420 any case we are going to return the score so that is pretty much the same as what we're doing 167 00:14:27.420 --> 00:14:31.740 when dealing the card and it now goes through the entire hand rather than the single 168 00:14:31.740 --> 00:14:36.160 card at a time so now that we've done that we can actually implement this 169 00:14:36.160 --> 00:14:40.780 in deal_player and before calling it the card just dealt is added to the 170 00:14:40.780 --> 00:14:44.340 list that contains the player's hands so going back to deal_player 171 00:14:47.400 --> 00:14:52.260 obviously our designed has changed dramatically so what we gonna do here is 172 00:14:52.260 --> 00:14:56.030 we are going to delete all this function well what I'll do I'll just comment it 173 00:14:56.030 --> 00:15:02.130 out so you still got access to that if you want to but it's now a lot easier so.... 174 00:15:02.130 --> 00:15:27.870 .... 175 00:15:29.060 --> 00:15:51.810 .... 176 00:15:51.810 --> 00:16:01.400 ...and that should 177 00:16:01.400 --> 00:16:06.890 be it so basically what we're doing now is what we've done is we've 178 00:16:06.890 --> 00:16:12.800 rewritten the deal_player function to put all that logic call 179 00:16:12.800 --> 00:16:16.670 the logic that we've just created in the score_hand and we are still getting 180 00:16:16.670 --> 00:16:21.700 this warning about shadowing but we no longer need these global variables 181 00:16:21.700 --> 00:16:29.480 anymore so we are gonna delete player score = 0 and player ace = false so gonna go down and delete these 182 00:16:29.480 --> 00:16:34.360 now so player_score = 0 and player_ace = false so delete those 183 00:16:34.360 --> 00:16:39.930 now because we no longer need those and the video is getting a little bit long so I'm gonna stop 184 00:16:39.930 --> 00:16:43.670 this video here and in the next video when we come back we're going to look at the 185 00:16:43.670 --> 00:16:48.770 deal_dealer function because that is now very very similar to the deal_player 186 00:16:48.770 --> 00:16:52.320 but obviously need to do a test to see whether the player wins and etc 187 00:16:52.320 --> 00:16:54.290 so I'll see you in the next video