WEBVTT 1 00:00:00.140 --> 00:00:01.510 Hi, welcome back. 2 00:00:01.510 --> 00:00:03.430 The last video we looked at mutability 3 00:00:03.430 --> 00:00:06.380 and now we're going to look at passing arguments in Python. 4 00:00:08.030 --> 00:00:10.310 Let's look at a couple examples of arguments in Python. 5 00:00:10.310 --> 00:00:12.660 And I'm going to show you this dictionary here. 6 00:00:14.960 --> 00:00:18.403 Dictionaries are a great example of mutable data structures. 7 00:00:19.240 --> 00:00:23.300 And then we'll create a function called see_friend, 8 00:00:23.300 --> 00:00:25.390 that is going to allow us to see a friend 9 00:00:25.390 --> 00:00:26.910 that we didn't see for a long time. 10 00:00:26.910 --> 00:00:31.910 So see_friend, friends, name, and this function, 11 00:00:32.620 --> 00:00:36.810 all it will do, it will say friends[name] = zero. 12 00:00:36.810 --> 00:00:40.530 If we pass in friends_last_seen, and 'Rolf', 13 00:00:40.530 --> 00:00:44.260 it'll set 'Rolf''s value to zero instead of 31. 14 00:00:44.260 --> 00:00:47.033 Now, here comes the interesting bit, 15 00:00:47.870 --> 00:00:51.603 we're going to print out the id of friends here. 16 00:00:52.880 --> 00:00:56.450 Inside the function, this is the parameter friends. 17 00:00:56.450 --> 00:01:00.760 Then we'll also go into print the id of friends_last_seen, 18 00:01:00.760 --> 00:01:03.360 which is our dictionary that is in the global scope. 19 00:01:05.300 --> 00:01:10.223 Finally, we are going to call see_friend, 20 00:01:11.830 --> 00:01:14.717 with friends_last_seen, and 'Rolf', 21 00:01:15.700 --> 00:01:18.803 and we're going to print the id of friends_last_seen. 22 00:01:20.030 --> 00:01:22.190 How many different numbers do you think 23 00:01:22.190 --> 00:01:24.490 we are going to see here? 24 00:01:24.490 --> 00:01:28.410 Hopefully, the answer was one, one number only. 25 00:01:28.410 --> 00:01:29.833 But I mean, we'll see. 26 00:01:32.260 --> 00:01:35.210 Notice how, the first thing we printed out 27 00:01:35.210 --> 00:01:37.103 was this friends_last_seen here. 28 00:01:38.110 --> 00:01:39.633 And it's a number. 29 00:01:40.730 --> 00:01:42.700 Then we called see_friends, 30 00:01:42.700 --> 00:01:46.100 and we passed in friends_last_seen. 31 00:01:46.100 --> 00:01:48.470 The name changed over to friends, 32 00:01:48.470 --> 00:01:51.800 but actually the number is still the same. 33 00:01:51.800 --> 00:01:54.773 It's still the same dictionary, this one here. 34 00:01:56.190 --> 00:01:57.730 Finally, when we exited the function, 35 00:01:57.730 --> 00:01:59.724 after changing the inners property 36 00:01:59.724 --> 00:02:03.450 of the friends dictionary, we printed out the id, 37 00:02:03.450 --> 00:02:04.863 and it was still the same. 38 00:02:07.710 --> 00:02:09.470 Now let's do something else. 39 00:02:09.470 --> 00:02:13.520 I'm going to print the id of friends_last_seen, 'Rolf', 40 00:02:13.520 --> 00:02:15.050 before we call the function 41 00:02:16.270 --> 00:02:18.530 and then we'll go into print the id 42 00:02:18.530 --> 00:02:22.543 of friends_last_seen['Rolf'], after we call the function. 43 00:02:23.680 --> 00:02:25.470 Notice how friends_last_seen['Rolf'] 44 00:02:25.470 --> 00:02:29.490 will have changed from 31 to zero. 45 00:02:29.490 --> 00:02:31.470 Now, how many different numbers do you think 46 00:02:31.470 --> 00:02:33.270 we're gonna see printed out in total? 47 00:02:33.270 --> 00:02:35.373 One, two, or three? 48 00:02:38.920 --> 00:02:42.180 Hopefully, you said three, friends_last_seen['Rolf'] here 49 00:02:42.180 --> 00:02:43.823 is the number 31. 50 00:02:44.730 --> 00:02:47.650 Friend last seen 'Rolf' here is the number zero. 51 00:02:47.650 --> 00:02:51.280 Integers are immutable, so whenever we change one, 52 00:02:51.280 --> 00:02:53.780 that is a new integer being created, let's run it. 53 00:02:55.360 --> 00:03:00.360 And as you can see, we have now three dictionaries here, 54 00:03:00.650 --> 00:03:03.500 we have three different numbers here. 55 00:03:03.500 --> 00:03:06.823 The first one is this friends_last_seen. 56 00:03:08.380 --> 00:03:12.203 The second one is this id of 'Rolf', that's this one here. 57 00:03:13.260 --> 00:03:15.740 Then we print the id of the friends dictionary, 58 00:03:15.740 --> 00:03:17.040 same one as the first one. 59 00:03:18.370 --> 00:03:21.670 Then we print the id of the new 'Rolf' number, 60 00:03:21.670 --> 00:03:24.883 and notice how two and four are different. 61 00:03:26.330 --> 00:03:27.908 And finally, we print the idea of the dictionary again, 62 00:03:27.908 --> 00:03:29.113 which is the same. 63 00:03:31.230 --> 00:03:34.730 So this is mutability in action. 64 00:03:34.730 --> 00:03:37.840 What we've seen is that the friends_last_seen dictionary 65 00:03:39.150 --> 00:03:41.320 has not changed itself. 66 00:03:41.320 --> 00:03:44.290 But one of the properties inside it has. 67 00:03:44.290 --> 00:03:46.120 Even though at no point, 68 00:03:46.120 --> 00:03:49.090 we have modified the friends_last_seen dictionary, 69 00:03:49.090 --> 00:03:51.480 we've only modified the value 70 00:03:51.480 --> 00:03:54.413 that we passed to the function in there. 71 00:03:55.510 --> 00:03:58.370 Let me delete the ids so I can explain things a bit better, 72 00:03:58.370 --> 00:04:00.823 without all that gibberish. 73 00:04:02.000 --> 00:04:05.265 So again, what's happening is that these variables, 74 00:04:05.265 --> 00:04:08.590 friends_last_seen, and friends are just post-it notes 75 00:04:08.590 --> 00:04:12.310 on the value, the value being this dictionary. 76 00:04:12.310 --> 00:04:16.933 This dictionary, specifically with this id that we got. 77 00:04:18.060 --> 00:04:21.680 When we pass the value here, 78 00:04:21.680 --> 00:04:24.410 what's happening is that we are passing the value 79 00:04:24.410 --> 00:04:27.510 of the variable, we're not passing the variable itself. 80 00:04:27.510 --> 00:04:31.283 So the dictionary now gets assigned to friends. 81 00:04:32.400 --> 00:04:37.223 Friends, is just another post-it note on the dictionary. 82 00:04:38.780 --> 00:04:40.630 Indeed, we can print 83 00:04:40.630 --> 00:04:44.700 whether friends = friends_last_seen. 84 00:04:44.700 --> 00:04:49.173 The ==, is going to compare the contents. 85 00:04:50.060 --> 00:04:52.870 So if there were two distinct dictionaries 86 00:04:52.870 --> 00:04:55.170 with the same contents, this would return true. 87 00:04:55.170 --> 00:04:58.950 But is compares for the ids. 88 00:04:58.950 --> 00:05:02.620 So it's gonna tell us what they are exactly the same object. 89 00:05:02.620 --> 00:05:05.710 And when we run it, we get true. 90 00:05:05.710 --> 00:05:08.530 Because this friends variable here, 91 00:05:08.530 --> 00:05:10.950 that has the value of friends_last_seen 92 00:05:10.950 --> 00:05:13.390 is actually the same as the friends_last_seen variable 93 00:05:13.390 --> 00:05:17.420 that was defined up here, the same dictionary exactly. 94 00:05:17.420 --> 00:05:20.663 Therefore, when we mutate one, 95 00:05:21.680 --> 00:05:24.610 that is changing the 'Rolf' property 96 00:05:24.610 --> 00:05:25.960 of this dictionary up here. 97 00:05:27.130 --> 00:05:31.320 Therefore, friends_last_seen['Rolf'] 98 00:05:31.320 --> 00:05:33.030 will have the value zero, 99 00:05:33.030 --> 00:05:36.023 after we run the function, there we have it. 100 00:05:39.060 --> 00:05:42.000 So immutability can be quite dangerous. 101 00:05:42.000 --> 00:05:44.470 Because if you change the dictionary in this function, 102 00:05:44.470 --> 00:05:46.300 and you're thinking, hey, yeah, we change the dictionary 103 00:05:46.300 --> 00:05:47.480 now we can use it, for example, 104 00:05:47.480 --> 00:05:51.803 say you wanted to use it here, some more, 105 00:05:52.900 --> 00:05:55.550 you may not realise that it's actually changing 106 00:05:55.550 --> 00:05:57.910 everywhere else that you use that same dictionary, 107 00:05:57.910 --> 00:05:59.743 so it can be quite dangerous. 108 00:06:01.220 --> 00:06:03.873 Okay, that's the concept of mutability. 109 00:06:06.050 --> 00:06:11.050 However, if you go and have something like, age is 20, 110 00:06:11.720 --> 00:06:14.177 and then a function that is increase_age, 111 00:06:20.360 --> 00:06:25.089 and you do this, then you say id of age, 112 00:06:25.089 --> 00:06:29.023 increase_age, id of age. 113 00:06:30.190 --> 00:06:32.450 What we're doing here is defining a variable, 114 00:06:32.450 --> 00:06:34.903 that is a post-it on the value 20. 115 00:06:36.600 --> 00:06:40.300 Then we are getting the id of that 20. 116 00:06:40.300 --> 00:06:43.070 We're calling increase_age, which has the value 20. 117 00:06:43.070 --> 00:06:46.870 So current_age is another post-it on 20. 118 00:06:46.870 --> 00:06:51.870 And now we're seeing this post-it now points to 20 plus one, 119 00:06:53.200 --> 00:06:55.870 so that's 21, an entirely different number. 120 00:06:55.870 --> 00:06:58.923 Then when we return, we print out the id of age. 121 00:07:00.090 --> 00:07:02.150 What do you think we're going to see? 122 00:07:02.150 --> 00:07:04.360 Are we going to see the same number twice? 123 00:07:04.360 --> 00:07:07.923 Or are we going to see two different numbers? 124 00:07:09.250 --> 00:07:12.220 Oh, we see nothing 'cause we didn't print them out. 125 00:07:12.220 --> 00:07:15.773 Let's see if you guess that one, let's print it. 126 00:07:18.840 --> 00:07:22.020 We get the same number twice. 127 00:07:22.020 --> 00:07:24.950 What does that tell us on the value of age? 128 00:07:24.950 --> 00:07:27.240 What is age here? 129 00:07:27.240 --> 00:07:30.053 Age here is 20, what is age here? 130 00:07:31.200 --> 00:07:33.970 But it must be 20 because it's got the same id 131 00:07:33.970 --> 00:07:37.523 and we know that numbers are all different objects. 132 00:07:39.370 --> 00:07:42.920 So what's happened is that this current_age variable 133 00:07:42.920 --> 00:07:45.793 has the number 20 assigned to it. 134 00:07:46.740 --> 00:07:48.050 But then what we've done is we've said 135 00:07:48.050 --> 00:07:52.140 now the current_age variable is a post-it on 21. 136 00:07:52.140 --> 00:07:55.373 Not on 20, age is still a post-it on 20. 137 00:07:57.100 --> 00:08:00.200 So the number 20 has not changed, 138 00:08:00.200 --> 00:08:02.090 it is only the variables that have moved 139 00:08:02.090 --> 00:08:03.853 from one to another. 140 00:08:05.870 --> 00:08:09.650 Again, an important concept for mutability. 141 00:08:09.650 --> 00:08:12.740 If you do this on an immutable object, 142 00:08:12.740 --> 00:08:14.600 it will just change within the function, 143 00:08:14.600 --> 00:08:17.620 this variable will now point somewhere else, 144 00:08:17.620 --> 00:08:19.933 but the outer elements will not change. 145 00:08:21.770 --> 00:08:23.320 Let's give you a third example. 146 00:08:25.040 --> 00:08:26.463 A list of prime numbers. 147 00:08:28.000 --> 00:08:30.600 The id of primes will be something 148 00:08:30.600 --> 00:08:33.350 we have to remember to print at this time though, 149 00:08:33.350 --> 00:08:36.917 then we say primes += [7, 11]. 150 00:08:37.950 --> 00:08:40.720 And then we print the id of primes. 151 00:08:40.720 --> 00:08:42.720 What do we think we're going to see now? 152 00:08:44.440 --> 00:08:46.333 We get the same id back. 153 00:08:47.230 --> 00:08:50.690 That is some bizarre functionality, right? 154 00:08:50.690 --> 00:08:55.690 This one is primes = primes + [7, 11]. 155 00:08:56.070 --> 00:09:00.670 Surely it should be a different thing. 156 00:09:00.670 --> 00:09:03.310 We've moved the variable from pointing to this list 157 00:09:03.310 --> 00:09:05.683 now points to the longer list. 158 00:09:06.860 --> 00:09:11.420 But remember, when I said that this is equivalent to this, 159 00:09:11.420 --> 00:09:14.090 I was lying, it is not. 160 00:09:14.090 --> 00:09:19.090 What's happening here is that primes = primes.iadd, that. 161 00:09:26.230 --> 00:09:29.160 And it is up to the implementation of this function, 162 00:09:29.160 --> 00:09:31.720 whether it's going to modify primes, 163 00:09:31.720 --> 00:09:34.380 or whether it's going to create a new list 164 00:09:34.380 --> 00:09:37.140 that determines whether this is going to be the same object 165 00:09:37.140 --> 00:09:38.090 or a different one. 166 00:09:42.550 --> 00:09:44.080 In this case, in case of the list, 167 00:09:44.080 --> 00:09:46.810 and in case of a lot of objects, 168 00:09:46.810 --> 00:09:50.740 when you do iadd when you do += or -=, 169 00:09:50.740 --> 00:09:53.907 or *= or /=. 170 00:09:54.790 --> 00:09:56.530 The Python official documentation 171 00:09:56.530 --> 00:10:01.530 says that when you do that, one of these iadd, or isub 172 00:10:02.190 --> 00:10:05.270 or imu, for multiply, 173 00:10:05.270 --> 00:10:08.140 they should modify the object if possible. 174 00:10:08.140 --> 00:10:11.133 So in the case of lists, iadd modifies the list. 175 00:10:14.220 --> 00:10:19.220 Of course, if you do primes = [2, 3, 5] + that, 176 00:10:21.400 --> 00:10:24.300 we're going to see two different numbers printed out here. 177 00:10:25.140 --> 00:10:28.600 Because these are two things. 178 00:10:28.600 --> 00:10:31.253 What if we do primes = primes + that? 179 00:10:34.070 --> 00:10:38.800 We also get two entirely different objects printed out. 180 00:10:38.800 --> 00:10:40.430 Again, what's happening here 181 00:10:40.430 --> 00:10:45.430 is primes = primes add [7, 11]. 182 00:10:46.450 --> 00:10:51.450 It is not iadd, iadd is meant to where possible modify self. 183 00:10:53.200 --> 00:10:55.830 Add does not have that requirement. 184 00:10:55.830 --> 00:10:58.060 And in the case of lists, it has been implemented 185 00:10:58.060 --> 00:11:00.460 so that it creates a new list. 186 00:11:00.460 --> 00:11:03.683 So this is why this creates a new list entirely. 187 00:11:06.757 --> 00:11:08.913 So it's all up to the implementation, 188 00:11:10.262 --> 00:11:12.212 whether the objects are mutable or not. 189 00:11:14.060 --> 00:11:16.630 So enough of this, just remember when you pass something 190 00:11:16.630 --> 00:11:20.220 to a function, that you can potentially mutate that thing, 191 00:11:20.220 --> 00:11:22.140 and then the value outside the function 192 00:11:22.140 --> 00:11:25.470 will have changed too, for example, with dictionaries, 193 00:11:25.470 --> 00:11:28.615 and you can do it with lists as well, if you use +=, 194 00:11:28.615 --> 00:11:31.373 or indeed any other of the isomething functions. 195 00:11:32.580 --> 00:11:35.670 Unless the thing you pass with the function is immutable, 196 00:11:35.670 --> 00:11:37.910 in which case, when you try to change it, 197 00:11:37.910 --> 00:11:41.420 it won't have changed outside the function only inside, 198 00:11:41.420 --> 00:11:43.220 essentially what you've done as you move the variable 199 00:11:43.220 --> 00:11:44.743 from one place to another. 200 00:11:46.610 --> 00:11:47.980 Okay, that's it. 201 00:11:47.980 --> 00:11:52.110 I hope that this, it's not to make a little bit of sense. 202 00:11:52.110 --> 00:11:54.320 As you programme more in Python, 203 00:11:54.320 --> 00:11:56.740 I think you'll be glad to have received this lecture 204 00:11:56.740 --> 00:11:59.090 from me, in order to understand a bit more 205 00:11:59.090 --> 00:12:00.920 of what's going on behind the scenes 206 00:12:00.920 --> 00:12:03.180 with mutability and different variable. 207 00:12:03.180 --> 00:12:05.520 It really is a frequent question 208 00:12:05.520 --> 00:12:07.630 on a lot of online Python forums, 209 00:12:07.630 --> 00:12:09.300 questions on Stack Overflow. 210 00:12:09.300 --> 00:12:10.250 So it's really good to know 211 00:12:10.250 --> 00:12:12.103 that this is how things are handled. 212 00:12:13.140 --> 00:12:15.640 So with that said, I'll see you on the next video.