Table of contents
Mastering Python function arguments is crucial for any programmer looking to elevate their skills in this versatile language. This comprehensive guide will walk you through the intricacies of parameters and arguments, their differences, and how to effectively use positional and keyword arguments. Additionally, you'll learn about unpacking iterables, leveraging args and *kwargs, and how to bring it all together for cleaner and more efficient code. By the end of this guide, you'll have a solid understanding of Python function arguments and be well-equipped to tackle complex programming tasks.
Parameters vs Arguments
Let's say we define a function
my_func(a, b)
and it'll receive two valuesa
andb
.In this context
a
andb
are called parameters ofmy_func()
.So, when we define a function, the things that are inside the parentheses are known as parameters.
When we call the function, the things that are inside the parentheses are known as arguments.
So, let's say we created two variables
x = 10
andy = 'a'
.Then, we call the
my_func(x, y)
function. Herex
andy
are arguments of the functionmy_func()
.
Positional and Keyword Arguments
Positional Arguments
The most common way of assigning arguments to parameters is via the order in which they are passed i.e. their position.
Suppose, we defined a function
my_func(a, b)
with parametersa
andb
.While calling the function, if we write
my_func(10, 20)
, then 10 will assign to the variablea
i.e.a = 10
and 20 will assign to the variableb
i.eb = 20
.If we call the function
my_func(20, 10)
, then 20 will assign toa
i.ea = 20
and 10 will assign tob
i.eb = 10
.
def my_func(a, b, c):
print("a={0}, b={1}, c={2}".format(a, b, c))
my_func(1, 2, 3)
my_func(2, 1, 3)
# ------------- OUTPUT --------------- #
a=1, b=2, c=3
a=2, b=1, c=3
Default Values
A positional argument can be made optional by specifying a default value for the corresponding parameter.
Let's say we define a function
my_func(a, b = 10)
, this is how we specify a default value.So, we are saying if the user/function caller doesn't specify any value for parameter
b
, then setb = 10
.We can call this function in two ways:
my_func(10, 20)
with this 10 will be assigned to the first parameter i.e.a
and 20 will be assigned tob
.my_func(10)
with this 10 will be assigned to the first parameter i.e.a
and as the user didn't provide the second argument, python will look at the second parameter and assign it the default value that is present in the function definition.
def my_func(a, b=10):
print(f'a={a} and b={b}')
my_func(10)
my_func(10, 20)
# -------------- OUTPUT -------------- #
a=10 and b=10
a=10 and b=20
Suppose we have three parameters and we want to make the second parameter optional.
Let's say we define a function
my_func(a, b = 100, c)
with these three parameters.So, how would we call this function without specifying a value for the second parameter?
Let's say we call it like this
my_func(10, 20)
.Is this correct?
I don't think so, let's check.
10 will be assigned to
a
and 20 will be assigned to..., which oneb
orc
?Here, python can't tell which one this value should be assigned to.
In conclusion, if a positional parameter is defined with a default value, then every positional parameter after it must also be given a default value.
def my_func(a, b=100, c):
print(f'a={a} and b={b} and c={c}')
my_func(10, 20)
# ------------- OUTPUT ------------- #
def my_func(a, b=100, c):
^
SyntaxError: non-default argument follows default argument
So, in the above example, we have to put a default value for
c
.Let's say we defined a function
my_func(a, b=2, c=3)
with these parameters.Here, all the following calls are possible:
my_func(1)
, here 1 will be assigned toa
, and forb
andc
the respective default values will be assigned.my_func(1,20)
, here 1 will be assigned toa
, 20 will be assigned tob
and forc
, the default value will be assigned.my_func(1,20,30)
, here 1 will be assigned toa
, 20 will be assigned tob
and 30 will be assigned toc
.
def my_func(a, b=2, c=3):
print("a={0}, b={1}, c={2}".format(a, b, c))
my_func(1)
my_func(1, 10)
my_func(1, 10, 100)
# ----------------- OUTPUT ---------------- #
a=1, b=2, c=3
a=1, b=10, c=3
a=1, b=10, c=100
But let's say we want to specify the first and the third parameter arguments and take the default value for the second parameter.
Then, how can we do this?
Here, we need the help of keyword arguments.
Keyword Arguments
To accomplish the above task, you can do this:
my_func(a=30, c=10)
, by calling this way, you are saying that you want the value fora
to be 30 and the value forc
to be 10.Positional arguments, can optionally, be specified using their corresponding parameter name.
This allows us to pass the arguments without sticking to the order of parameters.
Remember, the argument names must be the same as the parameter names.
The following calls are possible:
my_func(a=30, c=10)
, by calling this way, you are saying that you want the value fora
to be 30 and the value forc
to be 10.my_func(10, c=30)
, by calling this way, you are saying that you want the value fora
to be 10, the value forb
should be the default value and the value forc
should be 30.
my_func(a=30, c=10)
my_func(10, c=30)
# ---------------- OUTPUT --------------- #
a=30, b=2, c=10
a=10, b=2, c=30
We can also use keyword arguments even if the function parameter doesn't have any default values.
Let's say we define a function
my_func(a, b, c)
, notice none of the parameters have a default value.We can call the above function in multiple ways:
my_func(1, 2, 3)
my_func(1, 2, c=3)
my_func(a=1, b=2, c=3)
my_func(b=2, a=1, c=3)
def my_func(a, b, c):
print(f'a={a} and b={b} and c={c}')
my_func(1, 2, 3)
my_func(1, 2, c=3)
my_func(a=1, b=2, c=3)
my_func(b=2, a=1, c=3)
# -------------- OUTPUT ---------------- #
a=1 and b=2 and c=3
a=1 and b=2 and c=3
a=1 and b=2 and c=3
a=1 and b=2 and c=3
In conclusion, by using keyword arguments, you don't need to stick to the order of parameters, you can write them in whichever way you want.
Remember, once you use a named argument, all arguments thereafter must be named too.
Let's say you call the above-defined function like this:
my_func(c=1, 2, 4)
, now Python looks at this and it's like okay, 1 is assigned toc
, but then what, python can't determine which value is for which parameter.
Lastly, using keyword arguments and default arguments, the following calls are possible:
my_func(1)
, here 1 will be assigned toa
,b
andc
will be assigned to their respective default values.my_func(a=1, b=2)
, here 1 will be assigned toa
, 2 will be assigned tob
and c will get its default value.my_func(c=3, a=1)
, here 3 will be assigned toc
, 1 will be assigned toa
and b will get its default value.
Unpacking Iterables
What defines a tuple in Python, it's not
()
, instead, it's,
.()
is used to make it look clearer.1,2,3
is also a tuple.To create a tuple with a single element, you can do
1,
or(1,)
.To create an empty tuple, you can do
tuple()
or()
.
a = (1, 2, 3)
type(a)
# ------------ OUTPUT ------------ #
tuple
a = 1, 2, 3
type(a)
# ------------ OUTPUT ------------- #
tuple
a = (1,)
type(a)
# --------------- OUTPUT ------------ #
tuple
a = 1,
type(a)
# ------------- OUTPUT -------------- #
tuple
It won't be a tuple if you removed the ,
.
a = (1)
type(a)
# -------------- OUTPUT ------------- #
int
To create an empty tuple, there are two ways:
a = ()
type(a)
# -------------- OUTPUT ------------ #
tuple
a = tuple()
type(a)
# ------------- OUTPUT ------------- #
tuple
Packed values refer to values that are bundled together in some way.
Tuples and lists are obvious.
Strings are considered packed values because characters are bundled together.
Sets and dictionaries are also packed values.
A dictionary is a collection of key-value pairs.
Any iterable can be considered a packed value.
Unpacking packed values
Unpacking is the act of splitting packed values into individual variables contained in a list or tuple.
In other words, you create a tuple or a list that contains variable names and then you unpack the iterable into the variable names.
Let's say you have a list
[1, 2, 3]
and you want to unpack the list into a tuplea, b, c
.Remember, there are 3 variables in the list, so we need 3 variables to unpack.
So, the result will be:
a
will be 1b
will be 2c
will be 3
l = [1, 2, 3, 4]
a, b, c, d = l
print(a, b, c, d)
# ----------- OUTPUT -------------- #
1 2 3 4
Unpacking into individual variables is based on the relative positions of each element.
Unpacking other iterables:
a, b, c = 10, 20, 'hello'
a, b, c = 'XYZ'
a, b, c = 'XYZ'
print(a, b, c)
# --------------- OUTPUT ------------- #
X Y Z
- You can use this while swapping two values.
# traditional way for swapping two variables
a = 10
b = 20
print("a={0}, b={1}".format(a, b))
tmp = a
a = b
b = tmp
print("a={0}, b={1}".format(a, b))
# ---------------- OUTPUT -------------- #
a=10, b=20
a=20, b=10
# using unpacking
a = 10
b = 20
print("a={0}, b={1}".format(a, b))
a, b = b, a
print("a={0}, b={1}".format(a, b))
# ---------------- OUTPUT --------------- #
a=10, b=20
a=20, b=10
While unpacking dictionaries:
let's say we have a dictionary
d = {'key1': 1, 'key2': 2, 'key3': 3}
Then, if we write
a, b, c = d
, we will get the keys of the dictionary and not the values.
dict1 = {'p': 1, 'y': 2, 't': 3, 'h': 4, 'o': 5, 'n': 6}
dict1
a, b, c, d, e, f = dict1
print(a)
print(b)
print(c)
print(d)
print(e)
print(f)
# ------------ OUTPUT ------------ #
p
y
t
h
o
n
Note: Python Dictionary is ordered after Python 3.6 but sets are still unordered.
Here,
a
will bekey1
,b
will bekey2
andc
will bekey3
.While using sets:
let's say we have a set
s = {'h', 'e', 'l', 'l', 'o'}
If we unpack we can get different answers this is also an unordered type.
s = {'p', 'y', 't', 'h', 'o', 'n'}
print(s)
a, b, c, d, e, f = s
# ----------- OUTPUT ----------------- #
{'t', 'h', 'n', 'o', 'p', 'y'}
p
t
y
n
o
h
Extended Unpacking(* and ** )
Use case for *
We always don't want to unpack every single element in an iterable.
We may, for example, want to unpack the first value, and then unpack the remaining values into another variable.
Let's say we have a list
l = [1, 2, 3, 4, 5, 6]
.We can achieve our goal in multiple ways:
Using slicing:
- You can do
a = l[0]
andb = l[1:]
.
- You can do
Using simple unpacking:
a, b = l[0], l[1:]
Using * operator:
a, *b = l
l = [1, 2, 3, 4, 5, 6]
# using slicing
a = l[0]
b = l[1:]
print(a)
print(b)
# ---------- OUTPUT -------------- #
1
[2, 3, 4, 5, 6]
# using unpacking
a, b = l[0], l[1:]
print(a)
print(b)
# ----------- OUTPUT ------------- #
1
[2, 3, 4, 5, 6]
# using * operator
a, *b = l
print(a)
print(b)
# ----------- OUTPUT ------------- #
1
[2, 3, 4, 5, 6]
Let's see another example with tuples
a, *b = -10, 5, 2, 100
print(a)
print(b)
# ------------ OUTPUT ------------ #
-10
[5, 2, 100]
Let's take another example with strings
a, *b = 'python'
print(a)
print(b)
# ------------ OUTPUT ----------- #
p
['y', 't', 'h', 'o', 'n']
What about extracting the first, second, last and the rest elements?
# with slicing
s = 'python'
a, b, c, d = s[0], s[1], s[2:-1], s[-1]
print(a)
print(b)
print(c)
print(d)
# ------------- OUTPUT ------------ #
p
y
tho
n
# with unpacking
a, b, *c, d = s
print(a)
print(b)
print(c)
print(d)
# ---------- OUTPUT ----------- #
p
y
['t', 'h', 'o']
n
Here, c
is a list of characters and not a string, if that's a problem then you can use the join()
function to get the string from list.
Usage with Ordered Types
a, *b = [1, 2, 3, 4]
, thena = 1
andb = [2, 3, 4]
a, *b = (10, 20, 30, 40)
, thena = 10
andb = [20, 30, 40]
(notice we always get a list type after unpacking).a, *b = 'XYZ'
, thena = 'X'
andb = ['Y', 'Z']
.a, b, *c = 1, 2, 3, 4, 5
, thena = 1
,b = 2
, andc = [3, 4, 5]
.a, b, *c, d = 1, 2, 3, 4, 5, 6
, thena = 1
,b = 2
,c = [3, 4]
, andd = 5
.a, *b, c, d = 'python'
, thena = 'p'
,b = ['y', 't', 'h']
,c = 'o'
andd = 'n'
.a, *b = {'p':1, 'y': 2, 't': 3, 'h': 4, 'o': 5, 'n': 6}
, thena='p'
andb = ['y', 't', 'h', 'o', 'n']
.We can't get key-value pairs by unpacking from RHS, but we can get key-value pairs while unpacking from LHS.
Till now, we have seen that we can unpack from RHS, but we can also unpack from LHS.
Let's say we have
l1 = [1, 2, 3]
andl2 = [4, 5, 6]
.Then to unpack this we can write
l = [*l1, *l2]
This will result in
l = [1,2,3,4,5,6]
.As you can see this unpacks the two lists into individual elements.
Let's take another example with dictionaries.
d1 = {'key1': 1, 'key2': 2}
d2 = {'key2': 3, 'key3': 3}
[*d1, *d2]
# ----------- OUTPUT --------- #
['key1', 'key2', 'key2', 'key3']
- But how can we unpack both key and value?
d1 = {'key1': 1, 'key2': 2}
d2 = {'key2': 3, 'key3': 3}
{**d1, **d2}
# ------------ OUTPUT ---------- #
{'key1': 1, 'key2': 3, 'key3': 3}
Notice that the value for key
key2
is 3 and not 2, but why?It's because the dictionary
d2
is merged last, so it overwrote the value for keykey2
.
Usage with Unordered Types
You can use the * operator in unordered types, but the problem is you will never know what's the first element, what's the second element and so on.
But this is useful when you want to unpack in the RHS.
Let's say we have 3 dictionaries:
d1 = {'p': 1, 'y': 2}
d2 = {'t': 3, 'h': 4}
d3 = {'h': 5, 'o': 6, 'n': 7}
Let's say we want to get all the unique keys, then what we can do is we can unpack all the keys of these dictionaries into a set.
So,
s = {*d1, *d2, *d2}
.This will result in
s = {'p', 'y', 't', 'h', 'o', 'n'}
.
Use case for **
You can't use the ** operator on the LHS, you can only use it on RHS.
Let's say we have 3 dictionaries:
d1 = {'p': 1, 'y': 2}
d2 = {'t': 3, 'h': 4}
d3 = {'h': 5, 'o': 6, 'n': 7}
d = {**d1, **d2, **d3}
d = {'p': 1, 'y': 2, 't': 3, 'h': 5, 'o': 6, 'n': 7}
As you may have noticed, the value of
h
ind
is 5 even though there are two different values for the keyh
.The resulting dictionary took the value
5
becaused3
is mergerd at the end and it overwrote the value for the keyh
.You can even use it to add key-value pairs from one or more dictionaries into a dictionary literal.
Let's say we have a dictionary
d1 = {'a': 1, 'b': 2}
.Let's say we create another dictionary and we want to add/merge the
d1
dictionary into this dictionary, then to do this:d2 = {'a': 10, 'c': 3, **d1}
.This will result in
d2 = {'a': 1, 'b': 2, 'c': 3}
.You may ask why the value of
a
is 1.The reason is
d1
is merged at the end so it overwrote the value ofa
.
d1 = {'key1': 1, 'key2': 2}
d2 = {'key2': 3, 'key3': 3}
{**d1, **d2}
# --------- OUTPUT ---------- #
{'key1': 1, 'key2': 3, 'key3': 3}
{**d2, **d1}
# --------- OUTPUT ----------- #
{'key2': 2, 'key3': 3, 'key1': 1}
Here, you can see that the value for key2
is 2 as d1
is merged at the end.
{'a': 1, 'b': 2, **d1, **d2, 'c':3}
# ---------- OUTPUT ----------- #
{'a': 1, 'b': 2, 'key1': 1, 'key2': 3, 'key3': 3, 'c': 3}
{'key1': 100, **d1, **d2, 'key3': 200}
# ---------- OUTPUT ----------- #
{'key1': 1, 'key2': 3, 'key3': 200}
Nested Unpacking
Python supports nested unpacking as well.
Let's say we have a nested list
l = [1, 2, [3, 4]]
.We can unpack this in multiple ways:
a, b, c = l
, this will result ina = 1
,b = 2
, andc = [3, 4]
and then we'll have to unpackc
.a, b, (c, d) = l
, this will reslult ina = 1
,b = 2
,c = 3
,d = 4
.The above method will work with string as well.
a, *b, (c, *d) = [1, 2, 3, 'python']
This will result in
a = 1
,b = [2, 3]
,c = 'p'
, andd = ['y ,'t' ,'h' ,'o' ,'n']
.
a, b, (c, d) = [1, 2, ['X', 'Y']]
print(a)
print(b)
print(c)
print(d)
# ---------- OUTPUT --------- #
1
2
X
Y
a, b, (c, d) = [1, 2, 'XY']
print(a)
print(b)
print(c)
print(d)
# ----------- OUTPUT ----------- #
1
2
X
Y
a, b, (c, d, *e) = [1, 2, 'python']
print(a)
print(b)
print(c)
print(d)
print(e)
# ---------- OUTPUT ---------- #
1
2
p
y
['t', 'h', 'o', 'n']
a, *b, (c, d, *e) = [1, 2, 3, 'python']
print(a)
print(b)
print(c)
print(d)
print(e)
# ----------- OUTPUT ---------- #
1
[2, 3]
p
y
['t', 'h', 'o', 'n']
a, *b, tmp = [1, 2, 3, 'python']
print(a)
print(b)
print(tmp)
# --------- OUTPUT --------- #
1
[2, 3]
python
c, d, *e = tmp
print(c)
print(d)
print(e)
# ---------- OUTPUT ---------- #
p
y
['t', 'h', 'o', 'n']
Args
In Python, the
*args
concept is used to pass a variable number of arguments to a function. The*args
parameter allows you to pass any number of positional arguments to a function, and it collects them into a tuple within the function. The asterisk (*) beforeargs
is what enables this behavior.Now let's see how we can use *args in function parameters.
Recall that in unpacking,
a, b, *c = 10, 20, 'a', 'b'
will result ina = 10
,b = 20
andc = ['a', 'b']
.
a, b, *c = 10, 20, 'a', 'b'
print(a, b)
print(c)
# ------------ OUTPUT ------------ #
10 20
['a', 'b']
- A similar thing happens with function parameters.
def func1(a, b, *args):
print(a)
print(b)
print(args)
func1(1, 2, 'a', 'b')
# ------------ OUTPUT ------------ #
1
2
('a', 'b')
In functions, args will be a tuple and not a list
The
*args
syntax allows flexibility since you don't have to specify the exact number of arguments in advance. You can pass any number of arguments to the function, including none at all.The name of parameter args is a convention, you can use any name you want.
def func1(a, b, *my_vars):
print(a)
print(b)
print(my_vars)
func1(10, 20, 'a', 'b', 'c')
# ---------- OUTPUT ----------- #
10
20
('a', 'b', 'c')
You can't use any positional arguments after the args parameter.
When you call a function with some arguments, the arguments get unpacked in multiple variables which are the parameters of the function.
# unpacking an iterable into positional arguments
def func1(a, b, c):
print(a)
print(b)
print(c)
l = [10, 20, 30]
func1(*l)
# ------------ OUTPUT ------------ #
10
20
30
- Conventionally, we call it *args.
Args with keyword Arguments
- Let's recall positional arguments.
def func1(a, b, c):
print(a, b, c)
func1(10, 20, 30)
# --------------- OUTPUT ----------- #
10 20 30
Here,
a = 10
,b = 20
andc = 30
.Remember, positional parameters defined in the function can also be passed as named/keyword arguments.
func1(b=20, c=30, a=10)
# --------- OUTPUT --------- #
10 20 30
- We can make users use keyword arguments by exhausting all positional arguments using
*args
.
def func1(a, b, *args, d):
print(a, b, args, d)
func1(10, 20, 'a', 'b', d=100)
# ------------ OUTPUT ------------ #
10 20 ('a', 'b') 100
Here, you can see the variables
a
andb
gets assigned to the first and second arguments respectively, the args get assigned to the next two string arguments and finally the keyword argumentd
gets assigned to the value100
.You can also use args when you don't want mandatory positional arguments.
# optional positional arguments and mandatory keyword arguments
def func1(*args, d):
print(args)
print(d)
func1(1, 2, 3, d='hello')
# ---------- OUTPUT --------- #
(1, 2, 3)
hello
func1(d='hello')
# ----------- OUTPUT ----------- #
()
hello
- Let's say you want a function that will only accept keyword arguments and no positional arguments.
def func1(*, d='hello'):
print(d)
func1(d='bye')
# ----------- OUTPUT ----------- #
bye
In this function definition, the * operator is used before the parameter list, indicating that all subsequent parameters should be keyword-only arguments. In other words, these parameters can only be passed using their corresponding keywords.
Let's take another example, which takes no positional arguments and 2 keyword arguments.
# two keyword arguments are compulsory
def func1(*, a, b):
print(a)
print(b)
func1(a=10, b=20)
# ------------ OUTPUT ---------- #
10
20
- Unlike positional parameters, keyword arguments do not have to be defined with non-defaulted and then defaulted arguments
def func1(a, *, b='hello', c):
print(a, b, c)
func1(5, c='bye')
# ---------- OUTPUT ---------- #
5 hello bye
Here,
a = 5
, then*
denotes no positional argument after this only keyword arguments will be allowed, thenc = 'bye'
,b = 'hello'
.Let's see some examples.
def func1(a, b=20, *args, d=0, e='n/a'):
print(a, b, args, d, e)
func1(5, 4, 3, 2, 1, d=0, e='all engines running')
# ------------ OUTPUT ------------ #
5 4 (3, 2, 1) 0 all engines running
Here,
a = 5
,b = 4
,args = (3, 2, 1)
.After this only keyword arguments are there and there are 2 keyword arguments.
d = 0
ande = 'all engines running'
.
func1(0, 600, d='goooood morning', e='python!')
# ----------- OUTPUT ----------- #
0 600 () goooood morning python!
Here,
a = 0
,b = 600
, and as there are no more positional arguments soargs = ()
.d = goooood morning
ande = 'python!'
.
func1(11, 'm/s', 24, 'mph', d='unladen', e='swallow')
# ------------- OUTPUT ------------ #
11 m/s (24, 'mph') unladen swallow
Here,
a = 11
,b = 'm/s'
,args = (24, 'mph')
.d = 'unladen'
ande = 'swallow'
kwargs
*args is used to scoop up a variable amount of remaining positional arguments and it returns a tuple.
Here the parameter name args is arbitrary, the real parameter here is *.
**kwargs is used to scoop up a variable amount of remaining keyword arguments.
It'll return a dictionary
**kwargs can be specified even if the positional arguments have not been exhausted.
Let's see some examples
def func(**kwargs):
print(kwargs)
func(x=100, y=200)
# ------------ OUTPUT ----------- #
{'x': 100, 'y': 200}
- We can also use it in conjunction with *args:
def func(*args, **kwargs):
print(args)
print(kwargs)
func(1, 2, a=100, b=200)
# ------------ OUTPUT ----------- #
(1, 2)
{'a': 100, 'b': 200}
- Note: You cannot do the following:
def func(*, **kwargs):
print(kwargs)
- There is no need to even do this, since **kwargs essentially indicates no more positional arguments.
def func(a, b, **kwargs):
print(a)
print(b)
print(kwargs)
func(1, 2, x=100, y=200)
# ------------ OUTPUT ---------- #
1
2
{'x': 100, 'y': 200}
- Also, you cannot specify parameters after **kwargs has been used:
def func(a, b, **kwargs, c):
pass
# ------------ OUTPUT ----------- #
def func(a, b, **kwargs, c):
^
SyntaxError: invalid syntax
- If you want to specify both specific keyword-only arguments and **kwargs you will need to first get to a point where you can define a keyword-only argument (i.e. exhaust the positional arguments, using either *args or just *)
def func(*, d, **kwargs):
print(d)
print(kwargs)
func(d=1, x=100, y=200)
# ---------- OUTPUT ---------- #
1
{'x': 100, 'y': 200}
Putting It All Together
#positionals only
def func(a, b):
print(a, b)
func('hello', 'world')
# ----------- OUTPUT --------- #
hello world
func(b='world', a='hello')
# ------------ OUTPUT ------------ #
hello world
#positionals only: no extra positionals, only defaults
def func(a, b='world', c=10):
print(a, b, c)
func('hello')
# ----------- OUTPUT ------------ #
hello world 10
func('hello', c='!')
# ----------- OUTPUT ----------- #
hello world !
# positionals only: extra positionals, no defaults
def func(a, b, *args):
print(a, b, args)
func(1, 2, 'x', 'y', 'z')
# ---------- OUTPUT ---------- #
1 2 ('x', 'y', 'z')
# keywords only: no positionals, no defaults
def func(*, a, b):
print(a, b)
func(a=1, b=2)
# ------------ OUTPUT ----------- #
1 2
# keywords only: no positionals, some defaults
def func(*, a=1, b):
print(a, b)
func(a=10, b=20)
# ---------- OUTPUT ----------- #
10 20
func(b=2)
# ---------- OUTPUT ----------- #
1 2
# keywords and positionals: some positionals(no defaults), keywords(no defaults)
def func(a, b, *, c, d):
print(a, b, c, d)
func(1, 2, c=3, d=4)
# ----------- OUTPUT ---------- #
1 2 3 4
func(1, 2, d=4, c=3)
# ---------- OUTPUT ---------- #
1 2 3 4
func(1, c=3, d=4, b=2)
# ---------- OUTPUT ---------- #
1 2 3 4
# keywords and positionals: some positional defaults
def func(a, b=2, *, c, d=4):
print(a, b, c, d)
func(1, c=3)
# ------------ OUTPUT ----------- #
1 2 3 4
func(c=3, a=1)
# ---------- OUTPUT ------------ #
1 2 3 4
func(1, 2, c=3, d=4)
# ---------- OUTPUT ----------- #
1 2 3 4
func(c=3, a=1, b=2, d=4)
# ---------- OUTPUT ---------- #
1 2 3 4
# keywords and positionals: extra positionals
def func(a, b=2, *args, c=3, d):
print(a, b, args, c, d)
func(1, 2, 'x', 'y', 'z', c=3, d=4)
# ----------- OUTPUT ----------- #
1 2 ('x', 'y', 'z') 3 4
func(1, 'x', 'y', 'z', c=3, d=4)
# --------- OUTPUT ---------- #
1 x ('y', 'z') 3 4
# keywrods and positionals: no extra positionals, extra keywords
def func(a, b, *, c, d=4, **kwargs):
print(a, b, c, d, kwargs)
func(1, 2, c=3, x=100, y=200, z=300)
# ---------- OUTPUT ----------- #
1 2 3 4 {'x': 100, 'y': 200, 'z': 300}
func(x=100, y=200, z=300, c=3, b=2, a=1)
# ----------- OUTPUT ------------ #
1 2 3 4 {'x': 100, 'y': 200, 'z': 300}
# keywords and positionals: extra positionals, extra keywords
def func(a, b, *args, c, d=4, **kwargs):
print(a, b, args, c, d, kwargs)
func(1, 2, 'x', 'y', 'z', c=3, d=5, x=100, y=200, z=300)
# ------------ OUTPUT ---------- #
1 2 ('x', 'y', 'z') 3 5 {'x': 100, 'y': 200, 'z': 300}
#keywords and positionals: extra positionals and extra keywords
def func(*args, **kwargs):
print(args, kwargs)
func(1, 2, 3, x=100, y=200, z=300)
# ----------- OUTPUT ------------- #
(1, 2, 3) {'x': 100, 'y': 200, 'z': 300}
Conclusion
In conclusion, mastering Python function arguments is essential for writing efficient and clean code. By understanding the differences between parameters and arguments, utilizing positional and keyword arguments, and leveraging unpacking, args, and *kwargs, you'll be better equipped to tackle complex programming tasks in Python.