Skip to content

Commit 8a4defb

Browse files
committed
Typos and fixes for function arguments concept.
1 parent ec002b4 commit 8a4defb

2 files changed

Lines changed: 105 additions & 99 deletions

File tree

concepts/function-arguments/about.md

Lines changed: 60 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,20 @@ Parameter names should not contain spaces or punctuation.
1212
Positional arguments are values passed to a function in the same order as the parameters which bind to them.
1313
Positional arguments can optionally be passed by using their parameter name.
1414

15-
Following is an example of positional arguments being passed by position and by their parameter name:
15+
Positional arguments being passed by position and by their parameter name:
1616

1717
```python
1818
>>> def concat(greeting, name):
19-
... return f"{greeting}{name}"
20-
...
19+
... return f"{greeting}{name}"
20+
2121
# Passing data to the function by position.
2222
>>> print(concat("Hello, ", "Bob"))
23-
2423
Hello, Bob
25-
...
24+
2625
# Passing data to the function using the parameter name.
2726
>>> print(concat(name="Bob", greeting="Hello, "))
2827

2928
Hello, Bob
30-
3129
```
3230

3331
The first call to `concat` passes the arguments by position.
@@ -38,7 +36,7 @@ Note that positional arguments cannot follow keyword arguments.
3836
This
3937

4038
```python
41-
>>> print(concat(greeting="Hello, ", "Bob"))
39+
>>> print(concat(greeting="Hello, ", "Gregor"))
4240
```
4341

4442
results in this error:
@@ -50,68 +48,62 @@ SyntaxError: positional argument follows keyword argument
5048
Requiring positional-only arguments for function calls can be done through the use of the `/` operator in the parameter list.
5149

5250

53-
Following is an example of positional-only arguments:
51+
Positional-only arguments:
5452

5553
```python
5654
# Parameters showing a position-only operator.
5755
>>> def concat(greeting, name, /):
58-
... return f"{greeting}{name}"
56+
... return f"{greeting}{name}"
5957

60-
...
6158
>>> print(concat("Hello, ", "Bob"))
6259
Hello, Bob
63-
...
60+
6461
# Call to the function using keyword arguments.
6562
>>> print(concat(name="Bob", greeting="Hello, "))
6663
Traceback (most recent call last):
6764
print(concat(name="Bob", greeting="Hello, "))
6865
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting, name'
69-
70-
7166
```
7267

7368
## Keyword Arguments
7469

7570
Keyword arguments use the parameter name when calling a function.
7671
Keyword arguments can optionally be referred to by position.
7772

78-
Following is an example of keyword arguments being referred to by their parameter name and by position:
73+
Keyword arguments being referred to by their parameter name and by position:
7974

8075
```python
8176
>>> def concat(greeting, name):
82-
... return f"{greeting}{name}"
83-
...
77+
... return f"{greeting}{name}"
78+
8479
# Function call using parameter names as argument keywords.
8580
>>> print(concat(name="Bob", greeting="Hello, "))
8681
Hello, Bob
87-
...
82+
8883
# Function call with positional data as arguments.
8984
>>> print(concat("Hello, ", "Bob"))
9085
Hello, Bob
91-
9286
```
9387

9488
Requiring keyword-only arguments for function calls can be done through the use of the `*` operator in the parameter list.
9589

9690

97-
Following is an example of keyword-only arguments:
91+
Keyword-only arguments:
9892

9993
```python
10094
# Function definition requiring keyword-only arguments.
10195
>>> def concat(*, greeting, name):
102-
... return f"{greeting}{name}"
103-
...
96+
... return f"{greeting}{name}"
97+
10498
# Keyword arguments can be in an arbitrary order.
10599
>>> print(concat(name="Bob", greeting="Hello, "))
106100
Hello, Bob
107-
...
101+
108102
# Calling the function with positional data raises an error.
109103
>>> print(concat("Hello, ", "Bob"))
110104
Traceback (most recent call last):
111105
print(concat("Hello, ", "Bob"))
112106
TypeError: concat() takes 0 positional arguments but 2 were given
113-
114-
115107
```
116108

117109
## Default Argument Values
@@ -123,8 +115,8 @@ Default values can be overridden by calling the function with a new argument val
123115
```python
124116
# Function with default argument values.
125117
>>> def concat(greeting, name="you", punctuation="!"):
126-
... return f"{greeting}, {name}{punctuation}"
127-
...
118+
... return f"{greeting}, {name}{punctuation}"
119+
128120
>>> print(concat("Hello"))
129121
Hello, you!
130122

@@ -138,23 +130,23 @@ Hello, Bob.
138130
Arguments can be positional or keyword if neither the `/` nor `*` operators are used in the parameter definitions.
139131
Alternately, the positional-or-keyword arguments can be placed between the positional-only parameters on the left and the keyword-only parameters on the right.
140132

141-
Following is an example of positional-only, positional-or-keyword, and keyword-only arguments:
133+
Positional-only, positional-or-keyword, and keyword-only arguments:
142134

143135
```python
144136
# Position-only argument followed by position-or-keyword, followed by keyword-only.
145-
>>> def concat(greeting, /, name, *, ending):
146-
... return f"{greeting}{name}{ending}"
147-
...
137+
>>> def concat(greeting, /, name, *, ending):
138+
... return f"{greeting}{name}{ending}"
139+
148140
>>> print(concat("Hello, ", "Bob", ending="!"))
149141
Hello, Bob!
142+
150143
>>> print(concat("Hello, ", name="Bob", ending="!"))
151144
Hello, Bob!
152-
...
145+
153146
>>> print(concat(greeting="Hello, ", name="Bob", ending="!"))
154147
Traceback (most recent call last):
155148
print(concat(greeting="Hello, ", name="Bob", ending="!"))
156149
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting'
157-
158150
```
159151

160152
## `*args`
@@ -164,7 +156,6 @@ Code examples will often use a function definition something like the following:
164156
```python
165157
def my_function(*args, **kwargs):
166158
# code snipped
167-
168159
```
169160

170161
`*args` is a two-part name that represents a `tuple` with an indefinite number of separate positional arguments, also known as a [`variadic argument`][variadic argument].
@@ -175,77 +166,77 @@ The `*` is the operator which transforms the group of separate arguments into a
175166
If you have ever [unpacked a tuple][unpack a tuple] you may find the `*` in `*args` to be confusing.
176167
The `*` in a _parameter_ definition, instead of unpacking a tuple, converts one or more positional arguments _into_ a tuple.
177168
178-
We say that the `*` operator is [overloaded], as it has different behavior in different contexts.
169+
We say that the `*` operator is [_overloaded_][overloading], as it has different behavior in different contexts.
179170
For instance, `*` is used for multiplication, it is used for unpacking, and it is used to define an arbitrary number of positional parameters.
171+
172+
[overloading]: https://therenegadecoder.com/code/abusing-pythons-operator-overloading-feature/
173+
[unpacking]: https://www.geeksforgeeks.org/unpacking-a-tuple-in-python/
180174
~~~~
181175

182-
Since a tuple can be iterated, `args` can be passed to any other function which takes an iterable.
176+
Since a tuple can be iterated over, `args` can be passed to any other function which takes an iterable.
183177
Although `*args` is commonly juxtaposed with `**kwargs`, it doesn't have to be.
184178

185-
Following is an example of an arbitrary number of values being passed to a function:
179+
An arbitrary number of values being passed to a function:
186180

187181
```python
188-
189182
>>> def add(*args):
190-
# args is passed to the sum function, which takes an iterable
191-
... return sum(args)
192-
...
183+
# args is passed to the sum function, which iterates over it.
184+
... return sum(args)
185+
193186
>>> print(add(1, 2, 3))
194187
6
195188
```
196189

197190
If `*args` follows one or more positional arguments, then `*args` will be what is left over after the positional arguments.
198191

199-
Following is an example of an arbitrary number of values being passed to a function after a positional argument:
192+
An arbitrary number of values being passed to a function after a positional argument:
200193

201194
```python
202-
203195
>>> def add(first, *args):
204196
# first will be 1, leaving the values 2 and 3 in *args
205197
... return first + sum(args)
206-
...
198+
207199
>>> print(add(1, 2, 3))
208200
6
209201
```
210202

211-
If one or more default arguments are defined after `*args` they are separate from the `*args` values.
203+
If one or more [default arguments][default arguments] are defined after `*args`, they are separate from the `*args` values.
212204

213-
To put it all together is an example of an arbitrary number of values being passed to a function that also has a positional argument and a default argument:
205+
To put it all together:
214206

215207
```python
216208

217209
>>> def add(first, *args, last=0):
218-
... return first + sum(args) + last
219-
...
210+
... return first + sum(args) + last
211+
220212
>>> print(add(1, 2, 3))
221213
6
222214
>>> print(add(1, 2, 3, last=4))
223215
10
216+
224217
# This uses the unpacking operator * to separate the list elements into positional arguments.
225-
# It does not have the same behavior as the * in *args.
218+
# It does not have the same behavior as the * (packing) in *args.
226219
>>> print(add(*[1, 2, 3]))
227220
6
228-
229221
```
230222

231-
Note that when an argument is already in an iterable, such as a tuple or list, it needs to be unpacked before being passed to a function that takes an arbitrary number of separate arguments.
223+
Note that when an argument is already inside an `iterable`, such as a `tuple` or `list`, it needs to be [_unpacked_][unpacking-and-multiple-assignment] before being passed to a function that takes an arbitrary number of separate arguments.
232224
This is accomplished by using `*`, which is the [unpacking operator][unpacking operator].
233225

234226
`*` in this context _unpacks_ the container into its separate elements which are then transformed by `*args` into a tuple.
235-
Where there are only positional arguments, the unpacking action must result in the same number of arguments as there are formal parameters.
227+
Where there are only positional arguments, the unpacking action must result in the same number of arguments as there are formal parameters defined.
236228

237229
Without unpacking the list passed into `add`, the program would error.
238230

239231
```python
240-
>>>> def add(first, *args, last=0):
241-
... return first + sum(args) + last
242-
...
243-
>>>> print(add([1, 2, 3]))
232+
>>> def add(first, *args, last=0):
233+
... return first + sum(args) + last
234+
235+
>>> print(add([1, 2, 3]))
244236
Traceback (most recent call last):
245237
print(add([1, 2, 3]))
246238
return first + sum(args) + last
247239
TypeError: can only concatenate list (not "int") to list
248-
249240
```
250241

251242
## `**kwargs`
@@ -254,42 +245,37 @@ TypeError: can only concatenate list (not "int") to list
254245
`kwargs` is the name of the group of arguments and could be any other name, such as `my_args`, `arguments`, etc.
255246
The `**` transforms the group of named arguments into a [`dictionary`][dictionary] of `{argument name: argument value}` pairs.
256247

257-
Since a dictionary can be iterated, `kwargs` can be passed to any other function which takes an iterable.
248+
Since a dictionary can be iterated over, `kwargs` can be passed to any other function which takes an iterable.
258249
Although `**kwargs` is commonly juxtaposed with `*args`, it doesn't have to be.
259250

260-
Following is an example of an arbitrary number of key-value pairs being passed to a function:
251+
An arbitrary number of key-value pairs being passed to a function:
261252

262253
```python
263254
>>> def add(**kwargs):
264-
... return sum(kwargs.values())
265-
...
255+
... return sum(kwargs.values())
256+
266257
>>> print(add(one=1, two=2, three=3))
267258
6
268259
```
269260

270261
Note that the `dict.values()` method is called to iterate through the `kwargs` dictionary values.
271-
272-
When iterating a dictionary the default is to iterate the keys.
273-
274-
Following is an example of an arbitrary number of key-value pairs being passed to a function that then iterates over `kwargs.keys()`:
262+
When iterating over a dictionary the default is to iterate through the _keys_, so `dict.values()` needs to be specified explicitly.
263+
Following is an example of an arbitrary number of key-value pairs being passed to a function that then iterates over `kwargs.items()`:
275264

276265
```python
277266
>>> def concat(**kwargs):
278-
# Join concatenates the key names from `kwargs.keys()`
279-
... return " ".join(kwargs)
280-
...
281-
>>> print(concat(one=1, two=2, three=3))
282-
one two three
267+
... # Join concatenates the tuples from `kwargs.items()`
268+
... return " ".join((str(item) for item in kwargs.items()))
283269

270+
>>> print(concat(one=1, two=2, three=3))
271+
('one', 1) ('two', 2) ('three', 3)
284272
```
285273

286-
287274
[default arguments]: https://www.geeksforgeeks.org/default-arguments-in-python/
288-
[dictionary]: https://www.w3schools.com/python/python_dictionaries.asp
289-
[function concept]: ../functions/about.md
275+
[dictionary]: https://exercism.org/tracks/python/concepts/dicts
276+
[function concept]: https://github.com/exercism/python/blob/main/concepts/functions/about.md
290277
[key-value]: https://www.pythontutorial.net/python-basics/python-dictionary/
291-
[overloaded]: https://www.geeksforgeeks.org/operator-overloading-in-python/
292278
[tuple]: https://www.w3schools.com/python/python_tuples.asp
293-
[unpack a tuple]: https://www.geeksforgeeks.org/unpacking-a-tuple-in-python/
294279
[unpacking operator]: https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists
280+
[unpacking-and-multiple-assignment]: https://exercism.org/tracks/python/concepts/unpacking-and-multiple-assignment
295281
[variadic argument]: https://en.wikipedia.org/wiki/Variadic_function

0 commit comments

Comments
 (0)