Data Structures¶
There are many types of data structures in Python. Data structures are used for storing and organizing data. In this chapter we will learn about some of the most common data structures in Python such as lists, tuples, dictionaries, and sets.
Create a new Jupyter Notebook called data_structures and follow along.
Lists¶
You have already learned about lists and have used them a lot. Here we will learn some more things about lists. It’s important to remember that lists are mutable which means you can edit and them and change them after they are created.
Here we will learn about some more common
list methods. We have already learned some list
methods such as extend
and append
. Methods
are a little different then functions and we will
learn more about methods when we learn about
object oriented programming. For now, you can sort
of think as a method as similar to a function.
We will not cover all the list methods but you can
check the official documentation for more details
sort
¶
We can use the sort
method to sort a list.
The sort
method does not return any value
and sorts the list in place.
x = [10,60,90,100,-5]
print(x)
[10, 60, 90, 100, -5]
x.sort()
print(x)
[-5, 10, 60, 90, 100]
To sort it in reverse you can use the reverse
argument.
y = [0,1,2,3,4]
y.sort(reverse=True)
print(y)
[4, 3, 2, 1, 0]
things = ['apple', 'ape', 'dog', 'cat']
print(things)
things.sort()
print(things)
things.sort(reverse=True)
print(things)
['apple', 'ape', 'dog', 'cat']
['ape', 'apple', 'cat', 'dog']
['dog', 'cat', 'apple', 'ape']
count
¶
The count
method can count
the number of times an item is in a list.
x = [1,2,2,2,3,5]
x.count(-1)
0
x.count(1)
1
x.count(3)
1
x.count(2)
3
pop
¶
The pop
method is used to remove an item
at a specific index. It removes the item from the
list and returns the value of the item that was removed.
If you do not specify the position of the item to remove,
it will automatically remove the last item in the list.
y = [10, 20, 30, 40, 50]
y.pop(2)
30
print(y)
[10, 20, 40, 50]
y.pop(1)
20
print(y)
[10, 40, 50]
y.pop()
50
print(y)
[10, 40]
remove
¶
The remove
method is used to remove the
first item in a list that is equal to some
value (provided as an argument). If there is no
such value, a ValueError
is raised.
some_stuff = ['hello', 'bye', 1, 2, -10, 'good', 'bad', 3.14, 'hello']
some_stuff.remove('hello')
print(some_stuff)
['bye', 1, 2, -10, 'good', 'bad', 3.14, 'hello']
some_stuff.remove(3.14)
some_stuff
['bye', 1, 2, -10, 'good', 'bad', 'hello']
List Comprehension¶
List comprehensions give you a very convenient way to define lists quickly. In this section I will show you several types of examples and you can always Google more examples too. As you read and write Python code, you will find you will be using list comprehensions all the time.
Suppose you wanted to create a list with the integers between 0 and 10. One approach would be this:
numbers = []
for i in range(11):
numbers.append(i)
print(numbers)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
We can accomplish the same thing in one line using list comprehensions.
numbers = [i for i in range(11)]
print(numbers)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
The general syntax for list comprehensions is
[expression for item in iterable]
Its best to learn these by seeing a bunch of examples.
[x * x for x in range(5)]
[0, 1, 4, 9, 16]
print([character for character in 'Hello there! Hope you have a great day!'])
['H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'e', 'r', 'e', '!', ' ', 'H', 'o', 'p', 'e', ' ', 'y', 'o', 'u', ' ', 'h', 'a', 'v', 'e', ' ', 'a', ' ', 'g', 'r', 'e', 'a', 't', ' ', 'd', 'a', 'y', '!']
print(numbers)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[x for x in numbers]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[x * x for x in numbers]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[x - x for x in numbers]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[x + x for x in numbers]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
[str(x) for x in numbers]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
You can even add conditional logic to the list comprehensions.
numbers = [x for x in range(21)]
print(numbers)
even_numbers = [x for x in numbers if x % 2 == 0]
print(even_numbers)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
You can use enumerate in list comprehensions as well:
some_stuff = ['Chris', True, False, 1, 2, 10.8]
[x for x in some_stuff]
['Chris', True, False, 1, 2, 10.8]
[x for i,x in enumerate(some_stuff)]
['Chris', True, False, 1, 2, 10.8]
[i for i,x in enumerate(some_stuff)]
[0, 1, 2, 3, 4, 5]
[[i,x] for i,x in enumerate(some_stuff)]
[[0, 'Chris'], [1, True], [2, False], [3, 1], [4, 2], [5, 10.8]]
countries = ['Canada', 'USA', 'Mexico']
populations = [38000000, 328000000, 126000000]
country_stats = []
for c, p in zip(countries,populations):
country_stats.append([c,p])
print(country_stats)
[['Canada', 38000000], ['USA', 328000000], ['Mexico', 126000000]]
With list comprehensions you can do the above in one line.
country_stats = [[c,p] for c,p in zip(countries, populations)]
print(country_stats)
[['Canada', 38000000], ['USA', 328000000], ['Mexico', 126000000]]
[x[0] for x in country_stats]
['Canada', 'USA', 'Mexico']
[x[1] for x in country_stats]
[38000000, 328000000, 126000000]
print(country_stats)
[['Canada', 38000000], ['USA', 328000000], ['Mexico', 126000000]]
You can even nest list comprehensions to together.
For example we can unpack/flatten the country_stats
list like this:
[value for stats in country_stats for value in stats]
['Canada', 38000000, 'USA', 328000000, 'Mexico', 126000000]
If we wanted to do that same thing with for loops we would have to do:
values = []
for stats in country_stats:
for value in stats:
values.append(value)
print(values)
['Canada', 38000000, 'USA', 328000000, 'Mexico', 126000000]
There is probably more we could say about list comprehensions but this is a good start. Begin to use them when you code and you will get the hang of it.
Tuples¶
Now we will learn about tuples. Tuples are sort of like lists
but are immutable which means you can not change or edit them
after creation. Instead of using []
brackets you use the round brackets
()
which are also called parenthesis.
x = (1, 2, 3)
x
(1, 2, 3)
type(x)
tuple
len(x)
3
x[0]
1
x[2]
3
x[-1]
3
x
(1, 2, 3)
Seems sort of like a list right? But they are immutable. You can not change them or their values etc.
x[0] = 2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-55-ebac946b3580> in <module>
----> 1 x[0] = 2
TypeError: 'tuple' object does not support item assignment
x.append(10)
x.pop(1)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-56-c18350cddf27> in <module>
----> 1 x.pop(1)
AttributeError: 'tuple' object has no attribute 'pop'
So in that sense, they behave differently then lists.
When you input a tuple you can do so without entering the round brackets.
y = 1,1,1
print(y)
(1, 1, 1)
type(y)
tuple
But it is often a good idea to use the ()
when entering a tuple because
the code is easier to read. Also, sometimes its necessary.
You can nest tuples just like you did with lists.
nested_tuple = ((0, 0), (1, 2), (1, 3), (9, 9))
nested_tuple[-1]
(9, 9)
nested_tuple[-2]
(1, 3)
nested_tuple[-2][0]
1
nested_tuple[-2][1]
3
One thing to watch out for is the syntax when creating a tuple with a single element.
x = (1) # this is not a tuple !
type(x) # it's just an integer
int
print(x)
1
To create a tuple with a single element you must put a trailing comma.
x = (1,)
type(x)
tuple
print(x)
(1,)
x[0]
1
x[1] # only has one element so this index is out of range
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-72-a81caa627b71> in <module>
----> 1 x[1] # only has one element so this index is out of range
IndexError: tuple index out of range
Tuple packing is when you pack things together in a tuple. For example:
t = ('hello world', 1, True, False, 'Bye')
print(t)
('hello world', 1, True, False, 'Bye')
type(t)
tuple
len(t)
5
You can unpack the tuple t
like this for example:
print(t)
a, b, c, d, e = t
('hello world', 1, True, False, 'Bye')
a
'hello world'
b
1
c
True
d
False
e
'Bye'
Tuples are used with enumerate.
print(some_stuff)
['Chris', True, False, 1, 2, 10.8]
[type(x) for x in enumerate(some_stuff)]
[tuple, tuple, tuple, tuple, tuple, tuple]
[x for x in enumerate(some_stuff)]
[(0, 'Chris'), (1, True), (2, False), (3, 1), (4, 2), (5, 10.8)]
To grab just the second element (or first) in each tuple you could do:
[b for a,b in enumerate(some_stuff)]
['Chris', True, False, 1, 2, 10.8]
[a for a,b in enumerate(some_stuff)]
[0, 1, 2, 3, 4, 5]
Here is a list of tuples.
data = [(0,-1,2), (0,4,8), (-2,-2,5), (4,5,6)]
for d in data:
print(d)
(0, -1, 2)
(0, 4, 8)
(-2, -2, 5)
(4, 5, 6)
Or we can unpack each tuple in the loop like this:
for a,b,c in data:
print(f'{a} + {b} + {c} is {a + b + c}')
0 + -1 + 2 is 1
0 + 4 + 8 is 12
-2 + -2 + 5 is 1
4 + 5 + 6 is 15
Because data
is a list we can change it.
data.append('Chris')
print(data)
[(0, -1, 2), (0, 4, 8), (-2, -2, 5), (4, 5, 6), 'Chris']
data.pop(0)
(0, -1, 2)
data
[(0, 4, 8), (-2, -2, 5), (4, 5, 6), 'Chris']
data[2] = False
data
[(0, 4, 8), (-2, -2, 5), False, 'Chris']
But we still can not change one of the tuple items directly.
data[0]
(0, 4, 8)
data[0][-1] = 9
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-98-2b4bf7263d17> in <module>
----> 1 data[0][-1] = 9
TypeError: 'tuple' object does not support item assignment
We will work with tuples more later.
Dictionaries¶
Dictionaries are another type of data structure in Python
and they are super useful. They are mutable so you can
edit them and change them after they are created. Think of them
as a “look up” where you look up a key and get a value.
Dictionaries are essentially a mapping between keys and values.
You can define a dictionary by enclosing a comma separated list of key-value pairs in curly braces {}
. You use a colon :
to separate each key from its associated value.
Here is an example of a dictionary with a persons name as the key and their age as the value.
ages = {'Chris': 35, 'Joanna': 37, 'Penny': 11}
print(ages)
{'Chris': 35, 'Joanna': 37, 'Penny': 11}
type(ages)
dict
len(ages)
3
keys()
¶
To list the keys in a dictionary you can use the keys()
method.
ages.keys()
dict_keys(['Chris', 'Joanna', 'Penny'])
list(ages.keys())
['Chris', 'Joanna', 'Penny']
values()
¶
To get the values you can use the values()
method.
ages.values()
dict_values([35, 37, 11])
list(ages.values())
[35, 37, 11]
If you wrap a dictionary within list
you will only get the keys.
list(ages)
['Chris', 'Joanna', 'Penny']
Extracting and Storing Values¶
So the dictionary is a mapping between the key and the value.
KEY ——–> VALUE
'Chris'
——–> 35
'Joanna'
——–> 37
'Penny'
——–> 11
The two main operations your perform on a dictionary are
extracting the value given the key
storing a value with some key
To extract the value of a key you do this:
ages['Penny']
11
It is sort of like getting the value at a position of a list. But instead of indexing the position, which is an integer, you use the key as the index.
ages['Chris']
35
ages['Joanna']
37
If you try to get the value of a key that is not in the dictionary
you will get an error. In particular, a KeyError
.
ages['Hazel']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-111-bde46f9036a6> in <module>
----> 1 ages['Hazel']
KeyError: 'Hazel'
Dictionaries are mutable so we can keep adding additional key value pairs. This is how you store a value with some key.
ages['Hazel'] = 7
print(ages)
{'Chris': 35, 'Joanna': 37, 'Penny': 11, 'Hazel': 7}
ages['Isaac'] = 9
print(ages)
{'Chris': 35, 'Joanna': 37, 'Penny': 11, 'Hazel': 7, 'Isaac': 9}
print(list(ages.keys()))
['Chris', 'Joanna', 'Penny', 'Hazel', 'Isaac']
print(list(ages.values()))
[35, 37, 11, 7, 9]
ages['Isaac']
9
ages['Hazel']
7
in
¶
You can use the in
membership operator to see if a key is in a dictionary
or if a value is in the dictionary. More common to check if a key is in a dictionary though.
names = ['Larry', 'Joanna', 'Karen', 'Hazel', 'Isaac', 'Penny', 'Chris', 'Matt', 'Jen']
len(names)
9
ages
{'Chris': 35, 'Joanna': 37, 'Penny': 11, 'Hazel': 7, 'Isaac': 9}
'Chris' in ages # is checking if 'Chris' is one of the keys
True
'Matt' in ages
False
35 in ages
False
35 in ages.values()
True
'Chris' in ages.keys()
True
9 in ages # same as 9 in ages.keys()
False
9 in ages.keys()
False
9 in ages.values()
True
names
['Larry', 'Joanna', 'Karen', 'Hazel', 'Isaac', 'Penny', 'Chris', 'Matt', 'Jen']
ages
{'Chris': 35, 'Joanna': 37, 'Penny': 11, 'Hazel': 7, 'Isaac': 9}
for name in names:
if name in ages:
print(f'{name} is in the dictionary ages and their age is {ages[name]}.')
else:
print(f'{name} is not in the dictionary ages so we do not know their age.')
Larry is not in the dictionary ages so we do not know their age.
Joanna is in the dictionary ages and their age is 37.
Karen is not in the dictionary ages so we do not know their age.
Hazel is in the dictionary ages and their age is 7.
Isaac is in the dictionary ages and their age is 9.
Penny is in the dictionary ages and their age is 11.
Chris is in the dictionary ages and their age is 35.
Matt is not in the dictionary ages so we do not know their age.
Jen is not in the dictionary ages so we do not know their age.
Different ways to create¶
There are multiple ways to create/build dictionaries. We saw one above where we
we just explicitly defined the initial dictionary within the curly braces {}
.
You can use dict
to build a dictionary from a list of key-value pairs.
list_of_ages = [('Joanna', 37), ('Chris', 35), ('Penny', 11)] # list of tuples
dict(list_of_ages)
{'Joanna': 37, 'Chris': 35, 'Penny': 11}
If the keys are simple strings then you can even use keyword arguments like this.
dict(Joanna=1, Chris=35, Penny=11) # only works when the keys will be strings
{'Joanna': 1, 'Chris': 35, 'Penny': 11}
You can use dict comprehension to build dictionaries too. Suppose we wanted to create a dictionary with the keys as integers and the values as those integers squared (the number times it self).
numbers_squared = {
0: 0 * 0,
1: 1 * 1,
2: 2 * 2,
3: 3 * 3,
4: 4 * 4,
5: 5 * 5,
6: 6 * 6,
7: 7 * 7,
8: 8 * 8,
9: 9 * 9
}
numbers_squared
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
numbers_squared[6]
36
We can use a dict comprehension to generate the above dictionary.
{x: x * x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
Looping techniques¶
Now we will look at some looping techniques when working with dictionaries.
ages
{'Chris': 35, 'Joanna': 37, 'Penny': 11, 'Hazel': 7, 'Isaac': 9}
numbers_squared
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
# this will only give the keys
for k in ages:
print(k)
Chris
Joanna
Penny
Hazel
Isaac
# this will only give the keys
for k in numbers_squared:
print(k)
0
1
2
3
4
5
6
7
8
9
for k in ages:
print(k, ages[k])
Chris 35
Joanna 37
Penny 11
Hazel 7
Isaac 9
for k in numbers_squared:
print(k, numbers_squared[k])
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
You can use items()
method to iterate over a dictionary
and get the key and value at the same time.
for k,v in ages.items():
print(k,v)
Chris 35
Joanna 37
Penny 11
Hazel 7
Isaac 9
for k,v in numbers_squared.items():
print(k,v)
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
You can create an empty dictionary like this
ages = {}
print(ages)
{}
names_list = ['Larry', 'Joanna', 'Karen', 'Hazel', 'Isaac', 'Penny', 'Chris', 'Matt', 'Jen']
ages_list = [60, 37, 58, 7, 9, 11, 35, 38, 40]
for name,age in zip(names_list,ages_list):
print(name,age)
Larry 60
Joanna 37
Karen 58
Hazel 7
Isaac 9
Penny 11
Chris 35
Matt 38
Jen 40
We can add these names and ages to the empty dict ages, and populate it within a loop.
ages = {}
for name,age in zip(names_list,ages_list):
ages[name] = age
ages
{'Larry': 60,
'Joanna': 37,
'Karen': 58,
'Hazel': 7,
'Isaac': 9,
'Penny': 11,
'Chris': 35,
'Matt': 38,
'Jen': 40}
Keys are unique¶
list(ages.keys())
['Larry', 'Joanna', 'Karen', 'Hazel', 'Isaac', 'Penny', 'Chris', 'Matt', 'Jen']
list(ages.values())
[60, 37, 58, 7, 9, 11, 35, 38, 40]
ages['Larry']
60
ages['Chris']
35
ages['Henry'] # not a key in the dict
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-159-e2b0d9f786ff> in <module>
----> 1 ages['Henry'] # not a key in the dict
KeyError: 'Henry'
# add the key and a value
ages['Henry'] = 'eleven years old'
ages
{'Larry': 60,
'Joanna': 37,
'Karen': 58,
'Hazel': 7,
'Isaac': 9,
'Penny': 11,
'Chris': 35,
'Matt': 38,
'Jen': 40,
'Henry': 'eleven years old'}
There can not be duplicate keys in a dictionary. The keys must be unique. So if you assign a value to a key that is already in the dictionary it will be updated.
ages['Henry']
'eleven years old'
ages['Henry'] = 11
ages
{'Larry': 60,
'Joanna': 37,
'Karen': 58,
'Hazel': 7,
'Isaac': 9,
'Penny': 11,
'Chris': 35,
'Matt': 38,
'Jen': 40,
'Henry': 11}
for k, v in ages.items():
print(f'{k} is {v} years old.')
Larry is 60 years old.
Joanna is 37 years old.
Karen is 58 years old.
Hazel is 7 years old.
Isaac is 9 years old.
Penny is 11 years old.
Chris is 35 years old.
Matt is 38 years old.
Jen is 40 years old.
Henry is 11 years old.
Sets¶
Python sets are quite simple but can be very useful in certain situations. A set is an unordered collection with no duplicate elements.
fruits_list = [ 'oranges', 'grapefruits', 'mandarins', 'limes', 'limes', 'apple', 'apple']
print(fruits_list)
['oranges', 'grapefruits', 'mandarins', 'limes', 'limes', 'apple', 'apple']
With a regular list, like the list of fruits_list
above, you can have duplicates.
You can use set
to get the unique items.
fruits_set = set(fruits_list)
print(fruits_set)
type(fruits_set)
{'limes', 'apple', 'oranges', 'grapefruits', 'mandarins'}
set
You see that a set is a list of item between curly braces {}
.
my_set_of_stuff = {'Hello', 10, 20, True, False, 3.1459, 'a', False, True, 20}
my_set_of_stuff # see how the duplicates were removed
{10, 20, 3.1459, False, 'Hello', True, 'a'}
You can create an empty set like this:
x = set()
type(x)
set
Don’t use {}
to create any empty set because it will actually create an empty dictionary.
y = {}
type(y)
dict
add()
¶
You can use the add()
method to add items to a set.
x = set() # empty set
x.add('HELLO')
x
{'HELLO'}
x.add(True)
x
{'HELLO', True}
x.add(True) # is already in the set
x
{'HELLO', True}
for i in range(11):
if 3 < i < 7:
x.add(i)
len(x)
5
x
{4, 5, 6, 'HELLO', True}
5 in x
True
4 in x
True
7 in x
False
remove
¶
print(x)
{True, 4, 5, 6, 'HELLO'}
x.remove(8) # not in the set so raises error
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-187-ed5a54533654> in <module>
----> 1 x.remove(8) # not in the set so raises error
KeyError: 8
x.remove('HELLO')
x
{True, 4, 5, 6}
x.remove(5)
x
{True, 4, 6}
Like many of the different data structures introduced here, there is more that could be said. Google is your friend when it comes to learning Python. It’s not possible to cover every single topic here. The objective here is to introduce you to the main concepts so you can use these tools when building programs. Then when you get stuck or need some extra functionality, you can do some searching with Google about more information related to these data structures.
We will end this chapter by returning to functions and
learning about *args
and **kwargs
. I left this topic until now because
it requires some knowledge of tuples and dictionaries.
Function *args
and **kwargs
¶
In this section we show how you can have a variable number of
positional arguments or keyword arguments with the use of
*args
and **kwargs
. Sometimes you don’t know exactly the future
use cases of a function or you may need to have support for additional
arguments without defining them up front. These are examples where
you can use a variable number of arguments which means
you do not specify the exact number of arguments. Let’s look at some examples.
*args
¶
*args
is used for positional arguments.
def add_numbers(a, b):
return a + b
add_numbers(1,2)
3
The above function takes two arguments and adds them together.
But what if we wanted to have any number of arguments and add them all
together? You can do that with the unpacking operator *
. First we will
use *args
which supports any number of positional arguments.
The function will not add the arguments yet. First we will
see that by using*args
, you can pass any number of positional arguments
and args
is a tuple in the function definition.
def add_numbers(*args):
print(args)
print(type(args))
add_numbers()
()
<class 'tuple'>
add_numbers(1)
(1,)
<class 'tuple'>
add_numbers(1,2)
(1, 2)
<class 'tuple'>
add_numbers(1,2,4)
(1, 2, 4)
<class 'tuple'>
add_numbers(1,2,4,-9)
(1, 2, 4, -9)
<class 'tuple'>
You see? We can pass any number of positional arguments
to the function and they are all available within a variable name
called args
which is a tuple. So to actually add the numbers
we can just sum the elements in the tuple.
def add_numbers(*args):
return sum(args)
add_numbers()
0
add_numbers(1,2,3)
6
add_numbers(10,20,30,40,50,60)
210
Here is another example.
def do_stuff_with_args(*args):
print(f'You passed {len(args)} positional arguments.')
print(f'These positional arguments are available in the tuple {args}.')
for i,x in enumerate(args):
print(f'The argument at position {i} is {x}.')
print('We will return the last argument:')
return args[-1]
do_stuff_with_args(1,2,3)
You passed 3 positional arguments.
These positional arguments are available in the tuple (1, 2, 3).
The argument at position 0 is 1.
The argument at position 1 is 2.
The argument at position 2 is 3.
We will return the last argument:
3
do_stuff_with_args('HI', 'BYE', True, False, 3.14159)
You passed 5 positional arguments.
These positional arguments are available in the tuple ('HI', 'BYE', True, False, 3.14159).
The argument at position 0 is HI.
The argument at position 1 is BYE.
The argument at position 2 is True.
The argument at position 3 is False.
The argument at position 4 is 3.14159.
We will return the last argument:
3.14159
And it’s typical to use the name args
but you can actually use any name at all
provided that you use the unpacking *
operator. For example:
def do_stuff_with_args(*stuff):
print(f'You passed {len(stuff)} arguments.')
print(f'There are available in the tuple {stuff}')
for i,x in enumerate(stuff):
print(f'The argument at position {i} is {x}')
print('We will return the last argument:')
return stuff[-1]
do_stuff_with_args(3+4,6+4)
You passed 2 arguments.
There are available in the tuple (7, 10)
The argument at position 0 is 7
The argument at position 1 is 10
We will return the last argument:
10
**kwargs
¶
**kwargs
is similar to *args
but instead is used for
a variable number of keyword arguments. Instead of a tuple,
kwargs
is a dictionary.
def get_person_details(**kwargs):
print(kwargs)
print(type(kwargs))
get_person_details(name='Chris', age=36, city='Halifax')
{'name': 'Chris', 'age': 36, 'city': 'Halifax'}
<class 'dict'>
def get_person_details(**kwargs):
for k,v in kwargs.items():
print(f'The argument {k} has the value {v}.')
get_person_details(name='Chris', age=36, city='Halifax')
The argument name has the value Chris.
The argument age has the value 36.
The argument city has the value Halifax.
So that’s how you can pass a variable number (i.e. any number)
of keyword arguments using **kwargs
. And you can use any other name
as long as you use the **
. For example
def get_person_details(**details):
for k,v in details.items():
print(f'The argument {k} has the value {v}.')
get_person_details(name='Chris', age=36, city='Halifax', country='Canada')
The argument name has the value Chris.
The argument age has the value 36.
The argument city has the value Halifax.
The argument country has the value Canada.
It’s just common to see *args
and **kwargs
but you can use any names
for these that you want.
*
is for positional arguments and are accessed with a tuple**
is for keyword arguments and are accessed with a dictionary
Ordering of arguments¶
We saw in an earlier section that positional
arguments must come before keyword arguments.
So that means *args
must come before **kwargs
.
def get_person_details(*args, **kwargs):
print(args)
print(kwargs)
get_person_details('Chris', 36, city='Halifax', country='Canada')
('Chris', 36)
{'city': 'Halifax', 'country': 'Canada'}
Just remember that positional arguments come before keyword arguments. In general the ordering for arguments is:
regular positional arguments
*args
regular keyword arguments
**kwargs
Like in this example:
def get_person_details(name, age, *args, country='Canada', **kwargs):
print(f'Name is {name}.')
print(f'Age is {age}.')
print(f'Country is {country}.')
print(f'Other positional arguments given were: {args}.')
print(f'Other keyword arguments given were:')
for k,v in kwargs.items():
print(f'{k}: {v}')
get_person_details('Chris',
35,
'Short hair',
'6 feet tall',
hair_color='brown',
eye_color='blue',
sport='basketball',
movie='LOTR')
Name is Chris.
Age is 35.
Country is Canada.
Other positional arguments given were: ('Short hair', '6 feet tall').
Other keyword arguments given were:
hair_color: brown
eye_color: blue
sport: basketball
movie: LOTR
Okay so that’s an introduction to *args
and **kwargs
. I’m sure
we will use them later throughout the course. It’s good to be aware of them.