print('Welcome to the Genetics and Genomics class!')
Welcome to the Genetics and Genomics class!
'Welcome to the Genetics and Genomics class!'
'Welcome to the practical Python session!' # Only the last line is visualized
'Welcome to the practical Python session!'
You may notice that only the last line of the cell above is visualized. To print both lines you can use the following syntax:
print('Welcome to the Genetics and Genomics class!')
print('Welcome to the practical Python session!') # Both lines are visualized
# print('Something I do not want to print')
Welcome to the Genetics and Genomics class! Welcome to the practical Python session!
Side note: The hash symbol # is used to indicate comments or non-executable parts of the script that you don't want do remove from the code.
Congrats, you just printed several strings! As in many other languages, strings in Python are indicated with either single or double quotation. In most of the cases, single quotes are enough unless the string contains a single character '. For example:
## single quotes will not work in this example
print('I'm familiar with Python')
File "<ipython-input-4-baa0c323ab26>", line 2 print('I'm familiar with Python') ^ SyntaxError: invalid syntax
The special backslash character \ can be used in the single quote setting to avoid errors:
print('I\'m familiar with Python') ## single quotes *will* work in this example
I'm familiar with Python
And finally, double quotes:
print("I'm familiar with Python")
I'm familiar with Python
The backslash character might be useful in cases when quotation inside the string is needed, for example:
print('The concept of \"special characters\" is useful. Backslash \\ is a special character.')
The concept of "special characters" is useful. Backslash \ is a special character.
To print a multiline string, use three single or three double quotes:
print('''Welcome to the Genetics and Genomics class!
Welcome to the practical Python session!''')
Welcome to the Genetics and Genomics class! Welcome to the practical Python session!
Alternatively:
print("""Welcome to the Genetics and Genomics class!
Welcome to the practical Python session!""")
Welcome to the Genetics and Genomics class! Welcome to the practical Python session!
And finally:
print('Welcome to the Genetics and Genomics class!\nWelcome to the practical Python session!')
Welcome to the Genetics and Genomics class! Welcome to the practical Python session!
In the example above, the \n character indicates the new line. Another frequently used character is \t that indicates tab. For example:
print('Welcome to the Genetics and Genomics class!\n\tWelcome to the practical Python session!')
Welcome to the Genetics and Genomics class! Welcome to the practical Python session!
Creating variables in Python is simple, the only thing you need to do is to choose a variable name and assign a value or object to it. The variable can store different data types which we are going to discuss in the next section. As compared to other programing languages, Python doesn't require data type specification when a variable is defined.
Side note: It is impotant to use proper variable names and maintain the same style throughout your code. Variable names in Python should start with either a letter or an underscore! Also keep in mind that letter cases are important, so my_variable
and My_variable
would represent two different variables. To read more on variable names, check out the following links: https://www.w3schools.com/python/python_variables_names.asp and https://realpython.com/python-variables/
For example, we can use the string from the code above, assign it to the variable named my_string
and print this variable:
my_string = 'Welcome to the Genetics and Genomics class!'
print(my_string)
Welcome to the Genetics and Genomics class!
To output the variable content, you may omit the print
function:
my_string
'Welcome to the Genetics and Genomics class!'
One can combine custom strings and variables in the print()
function:
print('The variable my_string contains the following sentence: \"', my_string, '\"')
The variable my_string contains the following sentence: " Welcome to the Genetics and Genomics class! "
If you want to create several variables, you may use the following syntax:
teacher_1, teacher_2 = 'Bart', 'Vincent'
print(teacher_1, 'is giving lectures,', teacher_2, 'is giving practicals')
Bart is giving lectures, Vincent is giving practicals
To create variables with the same values, use the following syntax:
option_1 = option_2 = 'Python'
print('In this course we can use either', option_1, 'or', option_2)
In this course we can use either Python or Python
The variable content can be changed by reassigning it to another value/object, for example:
print('Before: my_string =', my_string)
my_string = 'Hello world!'
print('After: my_string =', my_string)
Before: my_string = Welcome to the Genetics and Genomics class! After: my_string = Hello world!
Side note: If you run the cell above for the second time, both output lines will be the same because the variable has been changed!
Python uses classes to define data types. The most frequently used data types are: str
, int
, float
, range()
, list()
, set()
, dict()
, bool()
, None
(and there are some more).
There are three numerical types in Python, which include integers (int
), floating point numbers (real values, aka float
) and complex numbers (complex
). Here are some examples:
int_number = 3
float_number = 1.5
complex_number = 1j
print('Integer number is ', int_number, 'and its type is', type(int_number))
print('Floating number is ', float_number, 'and its type is', type(float_number))
print('Complex number is ', complex_number, 'and its type is', type(complex_number))
Integer number is 3 and its type is <class 'int'> Floating number is 1.5 and its type is <class 'float'> Complex number is 1j and its type is <class 'complex'>
You can perform standard arithmetical operations numerical types, including:
Excercise 1.
Define the variables x and y, set their values to 2 and 3 respectively. Apply the following operations to x and y, print the output and its type: x + y
, x - y
, x * y
, x / y
, x ** y
, x // y
, x % y
.
x, y = 2, 3
print('x + y =', x + y, type(x + y))
print('x - y =', x - y, type(x - y))
print('x * y =', x * y, type(x * y))
print('x / y =', x / y, type(x / y))
print('x ** y =', x ** y, type(x ** y))
print('x // y =', x // y, type(x // y))
print('x % y =', x % y, type(x % y))
x + y = 5 <class 'int'> x - y = -1 <class 'int'> x * y = 6 <class 'int'> x / y = 0.6666666666666666 <class 'float'> x ** y = 8 <class 'int'> x // y = 0 <class 'int'> x % y = 2 <class 'int'>
Side note: if needed, the variable types can be specified in the following way: x = float(2)
, in this case, python will add a floating point to the number, i.e. x = 2.0
. The process of specifying a variable type is called casting, and the variable type can be changes by using the constructor functions, such as int()
, float()
, etc.
Exercise 2.
x
and y
as in the Exercise 1, but this time define the variable y
as a float. Will output change? If so, how?int()
to the output of the expression x / y
. Did the result change as compared to the previous exercise? If so how?x, y = 2, float(3)
print('x + y =', x + y, type(x + y))
print('x - y =', x - y, type(x - y))
print('x * y =', x * y, type(x * y))
print('x / y =', x / y, type(x / y))
print('x ** y =', x ** y, type(x ** y))
print('x // y =', x // y, type(x // y))
print('x % y =', x % y, type(x % y))
print('-' * 20)
print('x / y =', int(x / y), type(x / y))
x + y = 5.0 <class 'float'> x - y = -1.0 <class 'float'> x * y = 6.0 <class 'float'> x / y = 0.6666666666666666 <class 'float'> x ** y = 8.0 <class 'float'> x // y = 0.0 <class 'float'> x % y = 2.0 <class 'float'> -------------------- x / y = 0 <class 'float'>
If there are a lot of digits after the decimal point, the round()
function can be used to round the floating number to the desired number of decimals. The round()
function takes as the first argument the number, and as the second argument the number of digits for the rounding precision:
print(x / y, round(x / y, 3))
0.6666666666666666 0.667
Important: to check arguments of functions (e.g. the function named my_function()
), use one of the options below:
?my_function
help(my_function)
shift + tab
# For example:
help(round)
Help on built-in function round in module builtins: round(number, ndigits=None) Round a number to a given precision in decimal digits. The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as the number. ndigits may be negative.
Side note: Floating values can be sometimes represented in a scientific form, for example, x = 5e13
which is equivalent to `x = 5 (10 * 13)`
We can compare the numbers with the operators less (<
), greater (>
), equal (==
), not equal (!=
) and, of course, less or equal (<=
) and greater or equal (>=
). For example, let's check if the side note statement is correct!
print(5 * (10 ** 13) == 5e13) # Testing the statement
print(type(5 * (10 ** 13) == 5e13)) # Printing the type of the output
True <class 'bool'>
As we can see, the output of the statement is True
, that has the boolean type. Boolean values are either True
or False
. Note that integers 0
and 1
are equivalent to False
and True
respectively.
print('The statement 15 < 1 is', 15 <= 1)
print('The statement 10 != 12 is', 10 != 12)
print('-' * 10)
print('The statement 0 == False is', 0 == False)
print('The statement 1 == True is', 0 == False)
The statement 15 < 1 is False The statement 10 != 12 is True ---------- The statement 0 == False is True The statement 1 == True is True
and
, or
, not
¶The logical operators and
, or
, not
can be used to test different statements to get a boolean answer, for example:
# 'and' returns True if both statements are True
False and False, False and True, True and True
(False, False, True)
# 'or' returns True if one of the statements is True
False or False, False or True, True or True
(False, True, True)
# 'not' is a negation operator, e.g.
print('not False is', not False)
print('not True is', not True)
not False is True not True is False
print((15 < 1) and (150 < 10))
print((15 > 1) and (150 < 10))
print((15 > 1) or (150 < 10))
print(not ((15 > 1) or (150 < 10)))
False False True False
In the previous section you have already used the variables of the type string (str
in Python). Let's see what we can do with them!
my_name = 'Lola'
print(type(my_name))
<class 'str'>
One can use built-in methods to change the string, i.e. replace a substring (.replace()
), make all letters lowercase (.lower()
) or uppercase (.upper()
), for example:
print(my_name.replace('la', 'ic'))
print(my_name.lower())
print(my_name.upper())
Loic lola LOLA
In Python3.9 additional two methods .removeprefix()
and .removesuffix()
exist for strings. If the substring to be matched is found in either prefix (beginning) or suffix (end) of the string, then it is removed and the truncated version of the string is returned. If there is no match, the output is equal to the initial string. For example,
print(my_name.removeprefix('Lo')) # the prefix 'Lo' is removed
print(my_name.removesuffix('la')) # the suffix 'la' is removed
la Lo
The above mentioned methods do not change the string inplace, so if you want to save the updated string, store it to a new variable, e.g.
new_name = my_name.replace('la', 'ic')
print(new_name)
Loic
To check if a string contains a paricular a substring, use the in
keyword as in the following example:
'ic' in new_name
True
Side note: to get the list of keywords type import keyword
and in the next line print(keyword.kwlist)
. Remember that keywords cannot be used as variable names.
To repeat the same string n
number of times use the multiplication operator *
:
n = 10
print(my_name * n)
LolaLolaLolaLolaLolaLolaLolaLolaLolaLola
You can concatenate strings by using the +
operator as follows:
print(my_name + ' and ' + new_name + ' are friends') # Note that concatenation happens without spaces!
Lola and Loic are friends
To get a string that would be joined with the same separator (it can be comma, semicolon, dot, underscore, etc.), use the .join()
method:
print(' '.join([my_name, new_name, 'Robert', 'and', 'Sarah', 'are', 'friends']))
print('-' * 10)
print('_'.join([my_name, new_name, 'Robert', 'and', 'Sarah', 'are', 'friends']))
Lola Loic Robert and Sarah are friends ---------- Lola_Loic_Robert_and_Sarah_are_friends
Another useful method for strings is .split()
which allows splitting by a defined pattern:
long_string = '_'.join([my_name, new_name, 'Robert', 'and', 'Sarah', 'are', 'friends'])
print(long_string) # this string contains underscore as a separator
Lola_Loic_Robert_and_Sarah_are_friends
Let's use .split()
to extract separate words from the string:
print(long_string.split('_'))
['Lola', 'Loic', 'Robert', 'and', 'Sarah', 'are', 'friends']
Strings in Python are represented as arrays of Unicode characters and therefore, single elements of a string can be accessed through the square brackets in the following way:
my_name[0], my_name[1], my_name[2], my_name[3]
('L', 'o', 'l', 'a')
To acces several elements of the string, use colon and specify the index range in the [start_idx:end_idx]
format as shown below. Note that it is not necessary to specify start or end of the slice if start/end match the sequence start/end coordinate.
print('The first half of the name is:', my_name[:2])
print('The statement my_name[:2] == my_name[0:2] is', my_name[:2] == my_name[0:2])
print('-' * 10)
print('The second half of the name is:', my_name[2:])
print('The statement my_name[2:4] == my_name[2:] is', my_name[2:4] == my_name[2:])
The first half of the name is: Lo The statement my_name[:2] == my_name[0:2] is True ---------- The second half of the name is: la The statement my_name[2:4] == my_name[2:] is True
! Important: Enumeration in Python starts from 0 ! That is why the first index of the "L" letter in the variable my_name
is accessed with [0]
. When slicing a string keep in mind that the last coordinate is not included. One can access elements from the end of the string/list by using negative indexers starting from -1. In this case, the last element of my_name
will be accessed as my_name[-1]
. To acces a slice from the end, use the following syntax:
print('The second half of the name is:', my_name[-2:])
The second half of the name is: la
To know the length of the string one can use the len()
function:
print('The string \"', my_name, '\" contains', len(my_name), 'characters.')
The string " Lola " contains 4 characters.
You may have noticed in the cell above the new structure represented with square brackets and comma-separated variables (strings in this example). This stucture is called list
and it is one of the data types allowing to store data in Python. To know more about lists, sets and dictionaries, please see the following subsections.
Lists in Python are created with square brackets and may contain mixed data types, multiple occurrences of the same element. For example:
my_list = ['flowers', 20., 'cat', 'dog', 2, True, 'flowers', ['a', 'b', 5]]
print(type(my_list), ', length of the list is', len(my_list))
<class 'list'> , length of the list is 8
Elements in the list are indexed, so to access a single element of the list or a several elements, use the following options:
print('The first element of my_list is', my_list[0])
print('The second element of my_list is', my_list[1])
print('The last two elements of my_list are', my_list[-2:])
The first element of my_list is flowers The second element of my_list is 20.0 The last two elements of my_list are ['flowers', ['a', 'b', 5]]
Single elements in lists can be changed by using indeces. For example, let's take the word "cat" (the second element in Python counting system) and replace it with the word "owl".
my_list[2] = 'owl'
print(my_list)
['flowers', 20.0, 'owl', 'dog', 2, True, 'flowers', ['a', 'b', 5]]
Great, the replacement worked! Let's now try changing several sequential words "owl" and "dog" to words "pigeon" and "parrot".
my_list[2:4] = ['pigeon', 'parrot']
print(my_list)
['flowers', 20.0, 'pigeon', 'parrot', 2, True, 'flowers', ['a', 'b', 5]]
Lists and strings can be reversed with [::-1]
:
print('Initial list is:', my_list)
print('Reversed list is:', my_list[::-1])
Initial list is: ['flowers', 20.0, 'pigeon', 'parrot', 2, True, 'flowers', ['a', 'b', 5]] Reversed list is: [['a', 'b', 5], 'flowers', True, 2, 'parrot', 'pigeon', 20.0, 'flowers']
Lists in Python can be modified, namely, you can append, remove, replace, sort objects inside a list. The full list of methods is described here.
Let's try out some methods:
print('Before:', my_list)
print('Length is', len(my_list))
my_list.append(my_name)
# Check out the .extend() method which allows
# adding several elements from another list to the list of interest
print('-' * 10)
print('After:', my_list)
print('Length is', len(my_list))
Before: ['flowers', 20.0, 'pigeon', 'parrot', 2, True, 'flowers', ['a', 'b', 5]] Length is 8 ---------- After: ['flowers', 20.0, 'pigeon', 'parrot', 2, True, 'flowers', ['a', 'b', 5], 'Lola'] Length is 9
my_list.remove(True)
print('my_list after removing an element:', my_list)
print('Length is', len(my_list))
my_list after removing an element: ['flowers', 20.0, 'pigeon', 'parrot', 2, 'flowers', ['a', 'b', 5], 'Lola'] Length is 8
print('The word \"flowers\" appears', my_list.count('flowers'), 'times in my_list')
The word "flowers" appears 2 times in my_list
Side note 1: Note that there are two methods for sorting list: my_list.sort()
orders elements inplace (changes the initial list), and sorted(my_list)
returns a sorted copy of the list.
Side note 2: By using the list()
constructor, one can create a list from another data type, for example, np.array()
, which we will discuss later. Then, the constructor will be used in the following way: list(np.array(['a', 'b', 'c']))
.
To check if a list contains a paricular element, use the in
keyword as in the following example:
'parrot' in my_list
True
Note that my_list
contains a sublist. It's elements can be accessed by first extracting the list based on its index in my_list
, and then extracting an element inside the sublist by its index starting from 0
and to the length of the sublist:
print(my_list[7]) # get the sublist
print(my_list[7][0]) # extract the first element of the sublist
print(my_list[7][2]) # extract the last element of the sublist
print(my_list[7][:2]) # extract the fisrt two elements of the sublist
Lola L l Lo
Sets in Python represent a non-repetitive collection of elements, so it is the set in a mathematical sense. Therefore, sets allow various set-like operations including built-in methods, such as .intersection()
, .union()
, .difference()
. Similarly to lists, you can add/remove elements to/from a set, but sets cannot be sorted, set elements cannot be changed because sets are not indexed.
Side note: To create an unchangeable set, use the frozenset()
method. To read more about it, check out the documentation.
You can create a set with curly braces by listing the elements inside:
my_set = {'flowers', 20.0, 'pigeon', 'parrot', 2, True, 'flowers'}
print(my_set, ', the data type is', type(my_set))
{True, 2, 'flowers', 20.0, 'pigeon', 'parrot'} , the data type is <class 'set'>
Even though the element 'flowers' is repeated twice, the set definition with {}
will automatically remove this repetition.
Alternatively, sets can be created from lists, for example, by using the set()
constructor:
my_list = ['flowers', 20., 'cat', 'dog', 2, True, 'flowers']
my_set = set(my_list)
print(my_set, ', set length is', len(my_set))
# Sets can be converted to lists with the list() constructor: list(my_set)
{True, 2, 'dog', 'cat', 'flowers', 20.0} , set length is 6
To add an element to the set, use the .add()
method:
my_set.add('genetics')
print(my_set)
{True, 2, 'dog', 'genetics', 'cat', 'flowers', 20.0}
Existing sets can be extended with the elements from another set (or list) with the .update()
method:
print('my_set before:', my_set)
new_set = {'a', 'b', 'c', 20, 'flowers'}
my_set.update(new_set)
print('\nmy_set after the update:', my_set)
my_set before: {True, 2, 'dog', 'genetics', 'cat', 'flowers', 20.0} my_set after the update: {True, 2, 'dog', 'a', 'genetics', 'c', 'cat', 'flowers', 20.0, 'b'}
To check if a set contains a paricular element, use the in
keyword as in the following example:
'parrot' in my_set
False
Below you can find several examples of set operations, such as intersection, union, difference:
my_set = set(my_list)
new_set = {'a', 'b', 'c', 20, 'flowers'}
print('Intersection of sets:', my_set.intersection(new_set))
print('Union of sets:', my_set.union(new_set))
print('Difference of sets, option 1:', my_set.difference(new_set))
# Note that the output of new_set.difference(my_set) will be different!
# Equivalently, the set difference can be obtained as follows:
print('Difference of sets, option 2:', my_set - new_set)
print('Symmetric difference of sets:', my_set.symmetric_difference(new_set))
# Symmetric difference of sets can be obtained as (my_set - new_set).union(new_set - my_set)
Intersection of sets: {'flowers', 20} Union of sets: {True, 2, 'dog', 'a', 'c', 'cat', 'flowers', 20.0, 'b'} Difference of sets, option 1: {'cat', True, 2, 'dog'} Difference of sets, option 2: {'cat', True, 2, 'dog'} Symmetric difference of sets: {True, 2, 'c', 'a', 'dog', 'cat', 'b'}
To know more about set methods in Python, check out this link.
The last, but not less useful data type is dictionary. Dictionaries are powerful since they allow to store different data types in the {key: value}
format, which allows efficient hashing of elements. Dictionaries represent ordered (since Python3.6) structures with no repetitive keys, but editable elements. Note that keys can be represented only by immutable data types, check out this link to know more about mutable and immutable data types.
Dictionaries are represented with curly brackets and the following syntax:
my_dict = {
'name': my_name,
'age': 20,
'favourite_animal': 'dog',
'sibling_names': ['John', 'Sarah']
}
print(my_dict)
print('Type is', type(my_dict))
{'name': 'Lola', 'age': 20, 'favourite_animal': 'dog', 'sibling_names': ['John', 'Sarah']} Type is <class 'dict'>
As strings, lists and sets, dictionaries have a length.
Exercise 3.
my_dict
?Dictionary elements (or items, can be obtained with .items()
) are keys and values, which can be retrieved from the dictionary with .keys()
and .values()
methods.
Exercise 4.
print(my_dict.items())
print(my_dict.keys())
print(my_dict.values())
dict_items([('name', 'Lola'), ('age', 20), ('favourite_animal', 'dog'), ('sibling_names', ['John', 'Sarah'])]) dict_keys(['name', 'age', 'favourite_animal', 'sibling_names']) dict_values(['Lola', 20, 'dog', ['John', 'Sarah']])
To get values for a particular key of the dictionary, use the square brackets as follows:
my_dict['age']
20
Alternatively, one can use the built-in method .get()
which will return the value for a key if it is present and None otherwise (unless the alternative is specified):
print(my_dict.get('age'))
print(my_dict.get('eye_color'))
print(my_dict.get('eye_color', 'no_value')) # check parameters of the method to see how it works
20 None no_value
To add a new item, or several items to the dictionary, one can use either square brackets, or the .update()
method in the following way:
my_dict['eye_color'] = 'green'
# Or alternatively:
my_dict.update({'eye_color': 'green'})
Exercise 5.
my_dict
using the .update()
function. Print the final dictionary.# To add more than one item:
my_dict.update({'eye_color': 'green', 'height': 165})
my_dict
{'name': 'Lola', 'age': 20, 'favourite_animal': 'dog', 'sibling_names': ['John', 'Sarah'], 'eye_color': 'green', 'height': 165}
To get more information on dictionary methods, check out this link.
Side note: Dictionaries can be converted to lists and vise versa:
dict_to_list = list(my_dict.items())
dict_to_list
[('name', 'Lola'), ('age', 20), ('favourite_animal', 'dog'), ('sibling_names', ['John', 'Sarah']), ('eye_color', 'green'), ('height', 165)]
Note that in the example above, elements of the list are tuples, which are defined with round brackets (see next section 2.5. to know more about tuples):
print(dict_to_list[0], type(dict_to_list[0]))
('name', 'Lola') <class 'tuple'>
Lists can be converted to dictionaries as well:
new_list = [
['name', 'Lola'], ['age', 20], ['eye_color', 'green'],
['height', 165], ['favourite_animal', 'dog'],
['sibling_names', ['John', 'Sarah']],
]
list_to_dict = dict(new_list)
list_to_dict
{'name': 'Lola', 'age': 20, 'eye_color': 'green', 'height': 165, 'favourite_animal': 'dog', 'sibling_names': ['John', 'Sarah']}
Tuples represent another data type that is ordered, immutable and allows duplicates. As in other data types, tuples can contain any data type, tuples have length and tuple elements can be accessed with indexing. Tuples in Python are defined with round brackets ()
, and the .tuple()
constructor allows to create and/or convert other data types to tuples:
my_tuple = ('Antoni', 'Bart', 'Jacques', 'Olga', 'Valeria', 'Vincent')
my_tuple = tuple(['Antoni', 'Bart', 'Jacques', 'Olga', 'Valeria', 'Vincent'])
type(my_tuple)
tuple
my_tuple[0], my_tuple[3:5]
('Antoni', ('Olga', 'Valeria'))
None is a data type whith is defined with a keyword None
and indicates null value, or absence of a value. Therefore, None
cannot be interpreted as zero value, False, or an empty object (e.g. string, list, dict).
x = None
print(type(x))
<class 'NoneType'>
# Let's check if x is indeed the None data type
x is None, x is not None
(True, False)
In the subsection 2.2. we introduced boolean variables and discussed logical operators and
, or
and not
in the subsection 2.2.1. Conditional statements in Python allow to test statements and define the code based on that.
x, y, z = 1, 3, 4
if (x + y) == z:
# execute some code here
print('The sum of x and y is equal to z')
else:
# execute sth else here
print(';(')
The sum of x and y is equal to z
# Let's change the value of z
x, y, z = 1, 3, 5
if (x + y) == z:
# execute some code here
print('The sum of x and y is equal to z')
else:
# execute sth else here
print(';(')
;(
! Important: When using Python, one needs to be careful with indents and spacings! One extra space or absence of an indent may cause an error.
In conditional statements, the else
statement is not required. In this case, if the if
statement is not satisfied, noting will happen:
x, y, z = 1, 3, 5
if (x + y) == z:
# execute some code here
print('The sum of x and y is equal to z')
To test several statements, you can use the elif
statement, which will tell the interpreter that when the if
statement is not satisfied, try another contition, and if it works -- great! Otherwise, proceed either to the else
statement, or execute the following lines of code (if any). Note that conditional statements in Python can be nested.
x, y, z = 1, 3, 5
if (x + y) == z:
# execute some code here
print('The sum of x and y is equal to z')
elif (x + y) < z:
# execute some code here
print('The sum of x and y is less than z')
else:
# execute some code here
print('None of the conditions is satisfied')
The sum of x and y is less than z
Python allows for having several consecutive if
and/or elif
statements. Python will test each if
statement but will stop testing at the elif
statement that was satisfied.
Side note: Sometimes you might want to have an empty conditional statement. In this case, use the pass
statement right after a contition. To read more about it, check out this link.
While
and for
loops¶Let's go back to our example with my_list
and suppose we don't know its content and we want to store only numerical values to another list. How would you approach this problem? Well, you can, of course, check the length of the list and print each element by accessing it via indexing with square brackets, test whether an element has a numerical type and then add those elements to a new list. However, such approach is not efficient. This is the moment where loops come in hand!
while
¶While
is a conditional looping statement that allows you to perform an operation (or many operations) until the while
statement is satisfied. Let's try solving the problem of finding all numerical values in my_list
and storing them to a new list.
counter = 0 # Since enumeration in Python starts from 0, we set counter to 0 and change it in the loop
numerical_list = [] # Create an empty list
while counter < len(my_list):
list_element = my_list[counter] # get the element of my_list with the counter as index
if type(list_element) == int or type(list_element) == float: # Check data type of the element
numerical_list.append(list_element) # Append a numerical value to the new list
# Increase the counter by one to access next element of the my_list
counter += 1 # This is equivalent to: counter = counter + 1
print(numerical_list)
[20.0, 2]
If you want to stop the while loop if a custom condition is satisfied, use the break
statement as in the example below:
counter = 0 # Since enumeration in Python starts from 0,
# we set counter to 0 and iteratively increase it in the loop
numerical_list = [] # Create an empty list
while counter < len(my_list): # While condition
list_element = my_list[counter] # get the element of my_list with the counter as index
if type(list_element) == int or type(list_element) == float: # Check data type of the element
numerical_list.append(list_element) # Append a numerical value to the new list
# Increase the counter by one to access next element of the my_list
counter += 1 # This is equivalent to: counter = counter + 1
if counter == 1:
print('There is at least one numerical element in the list! Breaking...')
break
There is at least one numerical element in the list! Breaking...
for
¶The for
loop is useful when you need to iterate over a sequence of elements, which can be represented as a string, set, list, tuple or dictionary. Loops can be combined with conditional statements and various python functionalities. Please see the subsections below for more examples.
As in the subsection above, we will use my_list
to find numerical data types.
print(my_list)
['flowers', 20.0, 'cat', 'dog', 2, True, 'flowers']
numerical_list = [] # create an empty list
for list_element in my_list: # iterate over list elements
if type(list_element) == int or type(list_element) == float: # check element type
numerical_list.append(list_element) # append numerical value to list
numerical_list = [] # create an empty list
for i in range(len(my_list)): # iterate over list indices in range [0, 1, 2,... len(my_list))
list_element = my_list[i] # get element from the list based on the index
if type(list_element) == int or type(list_element) == float: # check element type
numerical_list.append(list_element) # append numerical value to list
numerical_list = [] # create an empty list
for i, list_element in enumerate(my_list): # iterate over list indices and elements with enumerate fucntion
if type(list_element) == int or type(list_element) == float: # check element type
numerical_list.append(list_element) # append numerical value to list
All three examples above will generate the exact same output, which is:
print(numerical_list)
[20.0, 2]
In the example above we saw how to interupt looping with the break
statement. continue
is another useful statement that allows to jump over one of the elements if a conditional statement is true.
Let's try it out by skipping the numerical values and printing all other elements while looping:
my_list = ['flowers', 20.0, 'cat', 'dog', 2, True, 'flowers', [1, 'fish', True]]
for i, list_element in enumerate(my_list): # iterate over list indices and elements with enumerate fucntion
if type(list_element) == int or type(list_element) == float:
continue # skip the element and do nothing if the condition is satisfied
else: # otherwise print the list element
print(list_element)
flowers cat dog True flowers [1, 'fish', True]
for
loops can be nested, for example, you may have noticed that we have a sublist inside of my_list
which contains one numerical value. Let's get is out and save to the numerical list with other values:
numerical_list = [] # create an empty list
for i, list_element in enumerate(my_list): # iterate over list indices and elements with enumerate fucntion
if type(list_element) == list: # first, check if the element type is list
for sublist_element in list_element: # if it is, iterate over sublist elements
if type(sublist_element) == int or type(sublist_element) == float:
# if the sublist element type is numerical, add it to the numerical_list:
numerical_list.append(sublist_element)
else: # go here is the element type is not list
if type(list_element) == int or type(list_element) == float:
# if the element type is numerical, add it to the numerical_list:
numerical_list.append(list_element)
print(numerical_list)
# It worked!
# We have added a numerical element from a sublist to all other numerical values!
[20.0, 2, 1]
List comprehensions are a compact way of writing for
loops. For example, the code from the subsection 4.2.1. can be rewritten as a one-liner:
numerical_list = [list_element for list_element in my_list if type(list_element) == int or type(list_element) == float]
print(numerical_list)
[20.0, 2]
However, this representation is not esthetically nice and does not follow the PEP8 Python code styling guidelines. To know more about styling your code with PEP8, check out the enclosed link.
If we follow the guidelines, the one-liner will turn into the following structure, which is better structured and allows much easier to navigation through the code:
numerical_list = [
list_element
for list_element in my_list
if type(list_element) == int or type(list_element) == float
]
Iteration over strings and sets is similar to iteration over lists. Let's use the variables we have defined above and implement the
print(my_name)
print(my_set)
Lola {True, 2, 'dog', 'cat', 'flowers', 20.0}
list_of_letters = []
for letter in my_name:
print(letter)
list_of_letters.append(letter)
L o l a
Or as a list comprehension:
list_of_letters = [letter for letter in my_name]
set_elements_list = []
for set_element in my_set:
print(set_element)
set_elements_list.append(set_element)
True 2 dog cat flowers 20.0
set_elements_list = [set_element for set_element in my_set]
for key in my_dict.keys(): # iterate over keys
print(key, my_dict[key]) # print dictionary key and the respective value
name Lola age 20 favourite_animal dog sibling_names ['John', 'Sarah'] eye_color green height 165
for value in my_dict.values(): # iterate over values
print(value) # print dictionary value
Lola 20 dog ['John', 'Sarah'] green 165
for key, value in my_dict.items(): # iterate over both keys and values
print(key, value) # print dictionary key and value
name Lola age 20 favourite_animal dog sibling_names ['John', 'Sarah'] eye_color green height 165
Let's create a dictionary from my_dict
that would contain only string values:
str_my_dict = {} # initialize empty dictionary
for key, value in my_dict.items(): # iterate over both keys and values
if type(value) == str: # check the value type
str_my_dict[key] = value # assign the value to its key in the *new* dictionary
str_my_dict.values()
dict_values(['Lola', 'dog', 'green'])
Let's now do the same thing but with dictionary comprehension:
str_my_dict = {
key: value
for key, value in my_dict.items()
if type(value) == str
}
Another useful function is zip()
which takes two or more iterable objects (e.g., lists) and joins them into tuple. Let's see how we can create a dictionary from two lists with the zip()
function:
list_with_keys = ['name', 'eye_color', 'favourite_animal']
list_with_values = ['Lola', 'green', 'dog']
new_dict = {}
for key, value in zip(list_with_keys, list_with_values):
new_dict[key] = value
print(zip(list_with_keys, list_with_values))
# by just printing the zip object, you won't see its content
<zip object at 0x146dad44c4c0>
# To view the content, first convert the zip object into list
print(list(zip(list_with_keys, list_with_values)))
[('name', 'Lola'), ('eye_color', 'green'), ('favourite_animal', 'dog')]
Sometimes you will need to execute the same piece of code several times. Let's imagine that you have 10 different lists and you want to know if the largest list element is larger than the sum of all other elements in the list. An efficient way of approaching this task is to first, create a function with a keyword def
that would take a list as input and return a boolean for the tested condition. Here is how to do it:
def is_larger(input_list): # define function name and its arguments
# function body with the code
max_element = max(input_list) # get maximum value in the list
sum_elements = sum([el for el in input_list if el != max_element]) # get the elements other than max
return max_element > sum_elements # the output to return
def get_max_and_sum(input_list): # define function name and its arguments
# function body with the code
max_element = max(input_list) # get maximum value in the list
sum_elements = sum([el for el in input_list if el != max_element]) # get the elements other than max
return max_element, sum_elements # you can output several values that are separated with a comma
Let's try out these functions! But first, we need to create some input data:
lst_1 = [i for i in range(5)] + [20]
lst_2 = [m / 10 for m in range(10)]
lst_3 = [j for j in range(150, 800, 500)] + [k for k in range(200, 300, 50)]
dict_with_lists = {
'lst_1': lst_1,
'lst_2': lst_2,
'lst_3': lst_3,
}
for lst_name, lst_i in dict_with_lists.items():
if is_larger(lst_i):
max_v, sum_v = get_max_and_sum(lst_i)
print('For', lst_name, ', maximum value', max_v, 'is larger than the sum of other values.')
For lst_1 , maximum value 20 is larger than the sum of other values. For lst_3 , maximum value 650 is larger than the sum of other values.
Of those intereseted, here is the list of useful resourses: