1
1

00:00:00,620  -->  00:00:02,220
<v Instructor>Hi guys and welcome back.</v>
2

2

00:00:02,220  -->  00:00:05,420
In this video we're going to learn about unpacking arguments
3

3

00:00:05,420  -->  00:00:07,360
and this is a little bit more complicated
4

4

00:00:07,360  -->  00:00:10,263
than what we've seen so far, so pleased do bear with me.
5

5

00:00:11,100  -->  00:00:13,660
I'm going to define a multiply function
6

6

00:00:13,660  -->  00:00:16,680
that takes in any number of arguments.
7

7

00:00:16,680  -->  00:00:17,513
Here's how.
8

8

00:00:19,060  -->  00:00:21,900
We create the multiply function as normal,
9

9

00:00:21,900  -->  00:00:26,123
and in here, we're going to put, star, args.
10

10

00:00:27,030  -->  00:00:31,040
Now the star is the important part, the args
11

11

00:00:31,040  -->  00:00:33,580
is just a variable name that will be used
12

12

00:00:33,580  -->  00:00:36,290
to collect the arguments.
13

13

00:00:36,290  -->  00:00:38,573
So let's print the args out.
14

14

00:00:39,730  -->  00:00:41,101
For now it's not going to multiply anything,
15

15

00:00:41,101  -->  00:00:42,560
it's just going to print them out,
16

16

00:00:42,560  -->  00:00:44,910
so what's happening here is we've defined a function
17

17

00:00:44,910  -->  00:00:47,340
and we've said, that the function has
18

18

00:00:48,780  -->  00:00:53,550
a set of arguments that will be collected into
19

19

00:00:53,550  -->  00:00:57,720
a tuple of arguments when the function gets called.
20

20

00:00:57,720  -->  00:01:02,010
So if we do multiply and then we do one, three and five,
21

21

00:01:02,010  -->  00:01:06,185
notice that here I'm passing different arguments.
22

22

00:01:06,185  -->  00:01:09,303
But this only has seemingly a single parameter.
23

23

00:01:09,303  -->  00:01:10,890
So I'm passing three different arguments
24

24

00:01:10,890  -->  00:01:14,870
and what's gonna happen is they are going to be collected
25

25

00:01:14,870  -->  00:01:19,870
into this args variable, so I'm gonna save this and run it.
26

26

00:01:19,950  -->  00:01:22,010
And you can see that what we get printed out
27

27

00:01:22,010  -->  00:01:25,410
when we run the function is a tuple of my arguments,
28

28

00:01:25,410  -->  00:01:28,423
so we've got one, three and five printed out as a tuple.
29

29

00:01:29,370  -->  00:01:32,470
If we wanted to multiply all these numbers together,
30

30

00:01:32,470  -->  00:01:36,990
we can just iterate over the arguments so for arg in args
31

31

00:01:36,990  -->  00:01:40,750
we can say total, equal total times arg,
32

32

00:01:40,750  -->  00:01:45,710
and then return total, then we can print that out.
33

33

00:01:45,710  -->  00:01:47,330
Now what we're doing here is we're starting off
34

34

00:01:47,330  -->  00:01:49,710
with a variable which is one and then we're multiplying
35

35

00:01:49,710  -->  00:01:52,380
that variable each of the arguments,
36

36

00:01:52,380  -->  00:01:54,330
and then we're returning the final value.
37

37

00:01:54,330  -->  00:01:59,180
If we run that we get an error because we left the S there
38

38

00:01:59,180  -->  00:02:01,330
so let's run that again.
39

39

00:02:01,330  -->  00:02:04,180
There we go we get 15 printed out.
40

40

00:02:04,180  -->  00:02:08,030
So this is a way collecting multiple arguments
41

41

00:02:08,030  -->  00:02:11,590
into a single variable when you are calling a function.
42

42

00:02:11,590  -->  00:02:14,730
And this has a number of uses that you will definitely
43

43

00:02:14,730  -->  00:02:18,210
be seeing quite a lot as you programme in Python.
44

44

00:02:18,210  -->  00:02:21,560
Notice that you can call this function with one argument
45

45

00:02:21,560  -->  00:02:23,980
if you want, and that's totally fine as well,
46

46

00:02:23,980  -->  00:02:27,170
it just creates a tuple of a single element.
47

47

00:02:27,170  -->  00:02:29,710
Let's go into another example let's say we have
48

48

00:02:29,710  -->  00:02:33,190
an add function with two parameters x and y,
49

49

00:02:33,190  -->  00:02:36,660
and then you have a list of numbers, three and five.
50

50

00:02:36,660  -->  00:02:40,560
So just as we can use the asterisk to collect arguments
51

51

00:02:40,560  -->  00:02:44,170
into one parameter, we can go the other way round
52

52

00:02:44,170  -->  00:02:47,750
and we can use the asterisk to de-structure arguments
53

53

00:02:47,750  -->  00:02:49,340
into multiple parameters.
54

54

00:02:49,340  -->  00:02:53,480
So you can do add, star nums, and what this'll do
55

55

00:02:53,480  -->  00:02:58,240
is it will use three for x and five for y
56

56

00:02:58,240  -->  00:03:01,550
so it is de-structuring the nums variable
57

57

00:03:01,550  -->  00:03:04,060
and splitting it out into multiple values
58

58

00:03:04,060  -->  00:03:07,367
such that one value can go to one parameter.
59

59

00:03:07,367  -->  00:03:10,170
Notice that if you do just nums here,
60

60

00:03:10,170  -->  00:03:13,820
you're going to pass three and five, the list itself
61

61

00:03:13,820  -->  00:03:17,310
as the value for x and y is not going to have a value
62

62

00:03:17,310  -->  00:03:18,950
so you're going to get an error.
63

63

00:03:18,950  -->  00:03:23,950
So by doing this it passes one value for each parameter.
64

64

00:03:23,980  -->  00:03:26,570
Of course you do need to have the same number of values
65

65

00:03:26,570  -->  00:03:29,210
in this list, as parameters in this function,
66

66

00:03:29,210  -->  00:03:30,610
otherwise you're going to have an error
67

67

00:03:30,610  -->  00:03:32,030
where you're gonna have too many parameters
68

68

00:03:32,030  -->  00:03:33,654
or too many arguments.
69

69

00:03:33,654  -->  00:03:37,130
Let's print this out so you can check that it works.
70

70

00:03:37,130  -->  00:03:39,270
There you have it, eight comes out.
71

71

00:03:39,270  -->  00:03:43,160
Now this can also work with named arguments
72

72

00:03:43,160  -->  00:03:45,690
so remember you can call the add function
73

73

00:03:45,690  -->  00:03:49,530
by doing x equals three and y equal five.
74

74

00:03:49,530  -->  00:03:53,270
So you can do something like that using these asterisks.
75

75

00:03:53,270  -->  00:03:55,840
Let's say that you've got your nums and these are now
76

76

00:03:55,840  -->  00:04:00,840
a dictionary with a value for x, and a value for y.
77

77

00:04:00,940  -->  00:04:04,740
If you wanted to use this dictionary as the argument
78

78

00:04:04,740  -->  00:04:09,420
to these functions, you would have to do nums x
79

79

00:04:09,420  -->  00:04:13,700
and nums y, like that, which is kind of ugly
80

80

00:04:13,700  -->  00:04:15,770
and also difficult to read, you've started to get a lot
81

81

00:04:15,770  -->  00:04:17,470
of brackets and square brackets and so on.
82

82

00:04:17,470  -->  00:04:19,940
If you wanted to be even more specific you can do
83

83

00:04:19,940  -->  00:04:24,580
x equals nums x and y equal nums y.
84

84

00:04:24,580  -->  00:04:27,740
And here is where the magic happens.
85

85

00:04:27,740  -->  00:04:29,630
You can see that the parameter name
86

86

00:04:30,660  -->  00:04:35,170
is the same as the key in the dictionary that we are using
87

87

00:04:35,170  -->  00:04:40,170
as a value for that parameter, so x is the key x
88

88

00:04:40,470  -->  00:04:43,220
and y is the key y.
89

89

00:04:43,220  -->  00:04:47,200
Instead of doing this entire thing, we can tell Python
90

90

00:04:47,200  -->  00:04:52,200
to pass in this dictionary as named arguments,
91

91

00:04:52,630  -->  00:04:54,970
where the argument will be equal to the value
92

92

00:04:54,970  -->  00:04:58,750
associated with that same name for a key.
93

93

00:04:58,750  -->  00:05:02,240
So essentially doing exactly this, but just do
94

94

00:05:02,240  -->  00:05:05,940
start star, nums, and that will do the same thing.
95

95

00:05:05,940  -->  00:05:08,240
So because we're using start star, it will say
96

96

00:05:08,240  -->  00:05:11,020
okay you've got a dictionary with two keys,
97

97

00:05:11,020  -->  00:05:13,160
what I'm gonna do is I'm gonna pass in each key
98

98

00:05:13,160  -->  00:05:16,300
as a named argument, and the value is going to be
99

99

00:05:16,300  -->  00:05:18,590
that associated with the key, so it'll say
100

100

00:05:18,590  -->  00:05:21,760
x equals nums x and y equals nums y.
101

101

00:05:21,760  -->  00:05:24,220
I know that's quite complicated thing,
102

102

00:05:24,220  -->  00:05:26,760
but it simplifies your code so much
103

103

00:05:26,760  -->  00:05:29,370
when you can use dictionaries like that.
104

104

00:05:29,370  -->  00:05:31,960
Let's go back to our multiply function
105

105

00:05:31,960  -->  00:05:35,750
that we had earlier on with this collected set of arguments.
106

106

00:05:35,750  -->  00:05:38,310
And I'm going to create anther function called apply
107

107

00:05:38,310  -->  00:05:42,463
and now we're going to say start args, comma operator.
108

108

00:05:43,340  -->  00:05:46,030
So this is a special bit of syntax in Python
109

109

00:05:46,030  -->  00:05:49,930
and what it means is collect all the positional arguments
110

110

00:05:49,930  -->  00:05:54,510
into this tuple args, and also have
111

111

00:05:54,510  -->  00:05:57,780
a named argument at the end.
112

112

00:05:57,780  -->  00:06:02,710
This creates a compulsory or required named argument.
113

113

00:06:02,710  -->  00:06:04,640
So when you're calling this function you're gonna pass in
114

114

00:06:04,640  -->  00:06:07,610
as many arguments as you want and they will all be collected
115

115

00:06:07,610  -->  00:06:11,120
into args and at the end you must pass in
116

116

00:06:11,120  -->  00:06:13,350
a named argument for this one.
117

117

00:06:13,350  -->  00:06:16,160
So let me just give it a body there, and we're gonna say
118

118

00:06:16,160  -->  00:06:18,620
if the operator is equal to the asterisk,
119

119

00:06:18,620  -->  00:06:21,130
we're going to return multiply of args,
120

120

00:06:21,130  -->  00:06:23,940
otherwise if the operator is equal to plus,
121

121

00:06:23,940  -->  00:06:25,620
we're going to return the sum of args
122

122

00:06:25,620  -->  00:06:27,660
and finally we're going to return no valid operator
123

123

00:06:27,660  -->  00:06:28,810
if it's neither of them.
124

124

00:06:28,810  -->  00:06:30,790
Now I have a bug in this function
125

125

00:06:30,790  -->  00:06:33,300
and you may notice what it is based on
126

126

00:06:33,300  -->  00:06:35,260
what we've seen already, but I know that you don't have
127

127

00:06:35,260  -->  00:06:38,430
a lot of practise with this yet so it is possible
128

128

00:06:38,430  -->  00:06:40,650
to not notice it, that's fine.
129

129

00:06:40,650  -->  00:06:44,890
We're going to print apply of one three six and seven,
130

130

00:06:44,890  -->  00:06:47,660
and the operator is going to be plus.
131

131

00:06:47,660  -->  00:06:49,780
So this is how this function must be called.
132

132

00:06:49,780  -->  00:06:52,290
You can pass in as many arguments as you want.
133

133

00:06:52,290  -->  00:06:54,043
They will be collected by args.
134

134

00:06:54,043  -->  00:06:57,710
Finally you must pass in a named argument
135

135

00:06:57,710  -->  00:06:59,180
for this one there.
136

136

00:06:59,180  -->  00:07:02,030
If you just pass in plus, Python's gonna try to
137

137

00:07:02,030  -->  00:07:05,438
collect it with args, so you're gonna miss this parameter.
138

138

00:07:05,438  -->  00:07:09,560
Indeed if we run this, you'll see that you get an error.
139

139

00:07:09,560  -->  00:07:12,590
Missing one required keyword only argument.
140

140

00:07:12,590  -->  00:07:15,310
So you do need the operator in there.
141

141

00:07:15,310  -->  00:07:18,700
So if we run this, it'll all work, you get 17 back
142

142

00:07:18,700  -->  00:07:21,230
because that's the addition of all of these numbers.
143

143

00:07:21,230  -->  00:07:24,833
However if you change this to a asterisk,
144

144

00:07:25,880  -->  00:07:30,570
then you get back a tuple, so why this tuple?
145

145

00:07:30,570  -->  00:07:33,850
Why not the multiplication of all the numbers?
146

146

00:07:33,850  -->  00:07:37,030
Is there a bug in our multiply function?
147

147

00:07:37,030  -->  00:07:39,520
Well you might be tempted to go through
148

148

00:07:39,520  -->  00:07:41,860
and see what the multiply function is doing.
149

149

00:07:41,860  -->  00:07:45,040
Multiply function starts with a variable called total
150

150

00:07:45,040  -->  00:07:47,220
that has the value one, and then it goes through
151

151

00:07:47,220  -->  00:07:50,560
the arguments and makes total equal to
152

152

00:07:50,560  -->  00:07:53,010
total multiplied by the arg.
153

153

00:07:53,010  -->  00:07:56,500
So how on earth is it managing to end up
154

154

00:07:56,500  -->  00:07:58,580
with a tuple being returned?
155

155

00:07:58,580  -->  00:08:02,260
Well if you multiply by a tuple,
156

156

00:08:02,260  -->  00:08:04,650
you actually end up with that tuple.
157

157

00:08:04,650  -->  00:08:09,650
So that means that args must be a tuple of tuples
158

158

00:08:10,260  -->  00:08:15,260
such that the first argument, the first arg in the tuple
159

159

00:08:15,272  -->  00:08:18,680
is itself a tuple, such that you're multiplying
160

160

00:08:18,680  -->  00:08:23,130
the tuple by one, and ending up with the tuple itself
161

161

00:08:23,130  -->  00:08:26,600
and then returning that, so the best way to do this
162

162

00:08:26,600  -->  00:08:28,410
is to use a debugger, but we haven't learned
163

163

00:08:28,410  -->  00:08:29,790
how to use a debugger yet.
164

164

00:08:29,790  -->  00:08:31,860
So we're gonna print the argumetns and you'll see that
165

165

00:08:31,860  -->  00:08:33,830
you're gonna get something a little bit weird.
166

166

00:08:33,830  -->  00:08:37,650
When you print the args, you get a tuple of tuples.
167

167

00:08:37,650  -->  00:08:39,870
And then when you iterate over the args,
168

168

00:08:39,870  -->  00:08:42,520
arg is the inner tuple.
169

169

00:08:42,520  -->  00:08:45,951
You're multiplying that by one, making it equal to the total
170

170

00:08:45,951  -->  00:08:49,570
such that total is the tuple, and then because that's
171

171

00:08:49,570  -->  00:08:53,150
the only value in args, that is the end of the for loop
172

172

00:08:53,150  -->  00:08:54,910
and you return the tuple.
173

173

00:08:54,910  -->  00:08:59,000
The reason for that is because we did not pass in
174

174

00:08:59,000  -->  00:09:01,580
individual arguments to the multiply function,
175

175

00:09:01,580  -->  00:09:02,963
we passed in a tuple.
176

176

00:09:04,010  -->  00:09:06,540
We want to put a star here.
177

177

00:09:06,540  -->  00:09:08,310
The reason for that is because when we call
178

178

00:09:08,310  -->  00:09:11,540
the apply function we are passing in four different
179

179

00:09:11,540  -->  00:09:13,430
arguments that are being collected
180

180

00:09:13,430  -->  00:09:16,850
into one tuple, by this star.
181

181

00:09:16,850  -->  00:09:19,330
But when we call the multiply function,
182

182

00:09:19,330  -->  00:09:22,360
we wanna pass in four different arguments
183

183

00:09:22,360  -->  00:09:25,630
so that they can be collected by args,
184

184

00:09:25,630  -->  00:09:29,410
inside the multiplier function and then used in here.
185

185

00:09:29,410  -->  00:09:32,460
But before, we were passing the args tuple itself,
186

186

00:09:32,460  -->  00:09:34,590
the collected tuple in this function.
187

187

00:09:34,590  -->  00:09:38,350
What we wanna do is we wanna unpack it into four values
188

188

00:09:38,350  -->  00:09:41,590
and pass them as individual values to this function
189

189

00:09:41,590  -->  00:09:44,920
so that they can be re-collected by args here.
190

190

00:09:44,920  -->  00:09:47,530
The other option is to remove the star
191

191

00:09:47,530  -->  00:09:49,970
so that you are passing a tuple directly
192

192

00:09:49,970  -->  00:09:52,940
to the multiplier function, and then moving this star
193

193

00:09:52,940  -->  00:09:56,150
so that the multiply function won't try to collect
194

194

00:09:56,150  -->  00:09:59,520
all its positional arguments into another tuple.
195

195

00:09:59,520  -->  00:10:02,740
However I do like passing multiple different arguments
196

196

00:10:02,740  -->  00:10:04,500
so I'm going to keep this stars there,
197

197

00:10:04,500  -->  00:10:05,820
but that's a choice for you to make,
198

198

00:10:05,820  -->  00:10:09,160
you can either pass arguments, or you can pass a tuple.
199

199

00:10:09,160  -->  00:10:11,830
That is a very common problem and quite a difficult
200

200

00:10:11,830  -->  00:10:13,890
to diagnose problem as well.
201

201

00:10:13,890  -->  00:10:15,690
So I just wanted to go through it so that
202

202

00:10:15,690  -->  00:10:17,400
if you encounter that in the future,
203

203

00:10:17,400  -->  00:10:18,510
you'll know what's going on.
204

204

00:10:18,510  -->  00:10:19,880
Thanks for joining me in this video.
205

205

00:10:19,880  -->  00:10:22,070
Hope it's been useful and not too confusing.
206

206

00:10:22,070  -->  00:10:23,720
And I'll see you in the next one.
