1: Introduction to Python¶
Throughout this Machine Learning series we will be exploring the possibilities of ML using python. We will be using various libraries like tensorflow, numpy, pandas, scikit and other graphing libraries like pyplot and seaborn.
This session will mainly be focused on the fundamentals of python required for machine learning.
Conditionals¶
By default, statements in Python script are executed sequentially from top to bottom. If the processing logic require so, the sequential flow of execution can be altered in two way:
- Conditional execution : a block of one or more statements will be executed if a certain expression is true.
- Repetitive execution : a block of one or more statements will be repetitively executed as long as a certain expression is true. In this section, we will cover if, else, elif statements. The comparison and logical operators we learned in previous sections will be useful here.
If Condition¶
An "if statement" is written by using the if
keyword. Remember the indentation after the colon.
'''syntax'''
if condition:
this part of code runs for truthy conditions
Example: 1
a = 3
if a > 0:
print('A is a positive number')
"""A is a positive number"""
A is a positive number
As you can see in the example above, 3 is greater than 0. The condition was true and the block code was executed.
If Else¶
If condition is true the first block will be executed, if not the else condition will run.
'''syntax'''
if condition:
this part of code runs for truthy conditions
else:
this part of code runs for false conditions
Example:
a = 3
if a < 0:
print('A is a negative number')
else:
print('A is a positive number')
A is a positive number
The condition above proves false, therefore the else block was executed. However, the else keyword catches anything which isn't caught by the preceding conditions.
If we have more than 2 conditions to check, We could use elif.
If Elif Else¶
In our daily life, we make decisions on daily basis. We make decisions not by checking one or two conditions but multiple conditions. As similar to life, programming is also full of conditions. We use elif when we have multiple conditions.
'''syntax'''
if condition:
code
elif condition:
code
else:
code
Example:
a = 0
if a > 0:
print('A is a positive number')
elif a < 0:
print('A is a negative number')
else:
print('A is zero')
A is zero
Nested Conditions¶
Conditions can be nested.
'''syntax'''
if condition:
code
if condition:
code
Example:
a = 0
if a > 0:
if a % 2 == 0:
print('A is a positive and even integer')
else:
print('A is a positive number')
elif a == 0:
print('A is zero')
else:
print('A is a negative number')
A is zero
Lists¶
List: is a collection which is ordered and changeable(modifiable). Allows duplicate members. A list is collection of different data types which is ordered and modifiable(mutable). A list can be empty or it may have different data type items.
empty_list = list() # this is an empty list, no item in the list
print(len(empty_list)) # 0
0
- Using square brackets (
[]
)
empty_list = [] # this is an empty list, no item in the list
print(len(empty_list)) # 0
0
Accessing List Items Using Indexing¶
We can access list items using positive and negative indexing.
You'll learn more about this in the slicing section ahead.
Unpacking List Items¶
lst = ['item','item2','item3', 'item4', 'item5']
first_item, second_item, third_item, *rest = lst
print(first_item) # item1
print(second_item) # item2
print(third_item) # item3
print(rest) # ['item4', 'item5']
item item2 item3 ['item4', 'item5']
Slicing Items from a List¶
- Positive Indexing : We can specify a range of positive indexes by specifying the start, end and step, the return value will be a new list. (default values for start = 0, end = len(lst) - 1 (last item), step = 1)
fruits = ['banana', 'orange', 'mango', 'lemon']
all_fruits = fruits[0:4] # it returns all the fruits
# this will also give the same result as the one above
all_fruits = fruits[0:] # if we don't set where to stop it takes all the rest
orange_and_mango = fruits[1:3] # it does not include the first index
orange_mango_lemon = fruits[1:]
orange_and_lemon = fruits[::2] # here we used a 3rd argument, step. It will take every 2cnd item - ['banana', 'mango']
- Negative Indexing : We can specify a range of negative indexes by specifying the start, end and step, the return value will be a new list.
fruits = ['banana', 'orange', 'mango', 'lemon']
all_fruits = fruits[-4:] # it returns all the fruits
orange_and_mango = fruits[-3:-1] # it does not include the last index,['orange', 'mango']
orange_mango_lemon = fruits[-3:] # this will give starting from -3 to the end,['orange', 'mango', 'lemon']
reverse_fruits = fruits[::-1] # a negative step will take the list in reverse order,['lemon', 'mango', 'orange', 'banana']
Modifying Lists¶
List is a mutable or modifiable ordered collection of items. Lets modify the fruit list.
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits[0] = 'avocado'
print(fruits) # ['avocado', 'orange', 'mango', 'lemon']
fruits[1] = 'apple'
print(fruits) # ['avocado', 'apple', 'mango', 'lemon']
last_index = len(fruits) - 1
fruits[last_index] = 'lime'
print(fruits) # ['avocado', 'apple', 'mango', 'lime']
['avocado', 'orange', 'mango', 'lemon'] ['avocado', 'apple', 'mango', 'lemon'] ['avocado', 'apple', 'mango', 'lime']
Checking Items in a List¶
Checking an item if it is a member of a list using in operator. See the example below.
fruits = ['banana', 'orange', 'mango', 'lemon']
does_exist = 'banana' in fruits
print(does_exist) # True
does_exist = 'lime' in fruits
print(does_exist) # False
True False
Adding Items to a List¶
To add item to the end of an existing list we use the method append()
.
'''syntax'''
lst = list()
lst.append(item)
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.append('apple')
print(fruits) # ['banana', 'orange', 'mango', 'lemon', 'apple']
fruits.append('lime') # ['banana', 'orange', 'mango', 'lemon', 'apple', 'lime']
print(fruits)
['banana', 'orange', 'mango', 'lemon', 'apple'] ['banana', 'orange', 'mango', 'lemon', 'apple', 'lime']
Inserting Items into a List¶
We can use insert() method to insert a single item at a specified index in a list. Note that other items are shifted to the right. The insert()
methods takes two arguments:index and an item to insert.
'''syntax'''
lst = ['item1', 'item2']
lst.insert(index, item)
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.insert(2, 'apple') # insert apple between orange and mango
print(fruits) # ['banana', 'orange', 'apple', 'mango', 'lemon']
fruits.insert(3, 'lime') # ['banana', 'orange', 'apple', 'lime', 'mango', 'lemon']
print(fruits)
['banana', 'orange', 'apple', 'mango', 'lemon'] ['banana', 'orange', 'apple', 'lime', 'mango', 'lemon']
Removing Items from a List¶
The remove()
method removes a specified item from a list
'''syntax'''
lst = ['item1', 'item2']
lst.remove(item)
fruits = ['banana', 'orange', 'mango', 'lemon', 'banana']
fruits.remove('banana')
print(fruits) # ['orange', 'mango', 'lemon', 'banana'] - this method removes the first occurrence of the item in the list
fruits.remove('lemon')
print(fruits) # ['orange', 'mango', 'banana']
['orange', 'mango', 'lemon', 'banana'] ['orange', 'mango', 'banana']
Removing Items Using Pop¶
The pop()
method removes the specified index, (or the last item if index is not specified):
'''syntax'''
lst = ['item1', 'item2']
lst.pop() # last item
lst.pop(index)
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.pop()
print(fruits) # ['banana', 'orange', 'mango']
fruits.pop(0)
print(fruits) # ['orange', 'mango']
['banana', 'orange', 'mango'] ['orange', 'mango']
Removing Items Using Del¶
The del
keyword removes the specified index and it can also be used to delete items within index range. It can also delete the list completely
'''syntax'''
lst = ['item1', 'item2']
del lst[index] # only a single item
del lst # to delete the list completely
fruits = ['banana', 'orange', 'mango', 'lemon', 'kiwi', 'lime']
del fruits[0]
print(fruits) # ['orange', 'mango', 'lemon', 'kiwi', 'lime']
del fruits[1]
print(fruits) # ['orange', 'lemon', 'kiwi', 'lime']
del fruits[1:3] # this deletes items between given indexes, so it does not delete the item with index 3!
print(fruits) # ['orange', 'lime']
del fruits
print(fruits) # This should give: NameError: name 'fruits' is not defined
['orange', 'mango', 'lemon', 'kiwi', 'lime'] ['orange', 'lemon', 'kiwi', 'lime'] ['orange', 'lime']
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-39-8f67a3380e85> in <module> 7 print(fruits) # ['orange', 'lime'] 8 del fruits ----> 9 print(fruits) # This should give: NameError: name 'fruits' is not defined NameError: name 'fruits' is not defined
Clearing List Items¶
The clear()
method empties the list:
'''syntax'''
lst = ['item1', 'item2']
lst.clear()
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.clear()
print(fruits) # []
[]
Copying a List¶
It is possible to copy a list by reassigning it to a new variable in the following way: list2 = list1. Now, list2 is a reference of list1, any changes we make in list2 will also modify the original, list2. But there are lots of case in which we do not like to modify the original instead we like to have a different copy. One of way of avoiding the problem above is using copy()
.
'''syntax'''
lst = ['item1', 'item2']
lst_copy = lst.copy()
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits_copy = fruits.copy()
print(fruits_copy) # ['banana', 'orange', 'mango', 'lemon']
['banana', 'orange', 'mango', 'lemon']
Counting Items in a List¶
The count()
method returns the number of times an item appears in a list:
'''syntax'''
lst = ['item1', 'item2']
lst.count(item)
fruits = ['banana', 'orange', 'mango', 'lemon']
print(fruits.count('orange')) # 1
ages = [22, 19, 24, 25, 26, 24, 25, 24]
print(ages.count(24)) # 3
1 3
Finding Index of an Item¶
The index()
method returns the index of an item in the list:
'''syntax'''
lst = ['item1', 'item2']
lst.index(item)
fruits = ['banana', 'orange', 'mango', 'lemon']
print(fruits.index('orange')) # 1
ages = [22, 19, 24, 25, 26, 24, 25, 24]
print(ages.index(24)) # 2, the first occurrence
1 2
Reversing a List¶
The reverse()
method reverses the order of a list.
'''syntax'''
lst = ['item1', 'item2']
lst.reverse()
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.reverse()
print(fruits) # ['lemon', 'mango', 'orange', 'banana']
ages = [22, 19, 24, 25, 26, 24, 25, 24]
ages.reverse()
print(ages) # [24, 25, 24, 26, 25, 24, 19, 22]
['lemon', 'mango', 'orange', 'banana'] [24, 25, 24, 26, 25, 24, 19, 22]
Sorting List Items¶
To sort lists we can use sort()
method or sorted()
built-in functions. The sort() method reorders the list items in ascending order and modifies the original list. If an argument of sort()
method reverse is equal to true, it will arrange the list in descending order.
sort()
: this method modifies the original list
'''syntax'''
lst = ['item1', 'item2']
lst.sort() # ascending
lst.sort(reverse=True) # descending
Example:
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits.sort()
print(fruits) # sorted in alphabetical order, ['banana', 'lemon', 'mango', 'orange']
fruits.sort(reverse=True)
print(fruits) # ['orange', 'mango', 'lemon', 'banana']
ages = [22, 19, 24, 25, 26, 24, 25, 24]
ages.sort()
print(ages) # [19, 22, 24, 24, 24, 25, 25, 26]
ages.sort(reverse=True)
print(ages) # [26, 25, 25, 24, 24, 24, 22, 19]
['banana', 'lemon', 'mango', 'orange'] ['orange', 'mango', 'lemon', 'banana'] [19, 22, 24, 24, 24, 25, 25, 26] [26, 25, 25, 24, 24, 24, 22, 19]
sorted()
: returns the ordered list without modifying the original list
Example:
fruits = ['banana', 'orange', 'mango', 'lemon']
print(sorted(fruits)) # ['banana', 'lemon', 'mango', 'orange']
fruits = ['banana', 'orange', 'mango', 'lemon']
fruits = sorted(fruits,reverse=True) # Reverse order
print(fruits)
['banana', 'lemon', 'mango', 'orange'] ['orange', 'mango', 'lemon', 'banana']
Tuples¶
A tuple is a collection of different data types which is ordered and unchangeable (immutable). Tuples are written with round brackets, ()
. Once a tuple is created, we cannot change its values.
We cannot use add, insert, remove methods in a tuple because it is not modifiable (mutable). Unlike list, tuple has few methods. Methods related to tuples:
tuple()
: to create an empty tuplecount()
: to count the number of a specified item in a tupleindex()
: to find the index of a specified item in a tuple- operator: to join two or more tuples and to create a new tuple
Creating a Tuple¶
- Empty tuple: Creating an empty tuple
'''syntax'''
empty_tuple = ()
empty_tuple = tuple() # or using the tuple constructor
Tuple length¶
We use the len()
method to get the length of a tuple.
'''syntax'''
tpl = ('item1', 'item2', 'item3')
print(len(tpl))
Accessing Tuple Items¶
- Positive Indexing: Similar to the list data type we use positive or negative indexing to access tuple items.
'''Syntax'''
tpl = ('item1', 'item2', 'item3')
first_item = tpl[0]
second_item = tpl[1]
- Negative indexing: Negative indexing means beginning from the end, -1 refers to the last item, -2 refers to the second last and the negative of the list/tuple length refers to the first item.
'''Syntax'''
tpl = ('item1', 'item2', 'item3','item4')
first_item = tpl[-4]
second_item = tpl[-3]
Changing Tuples to Lists¶
We can change tuples to lists and lists to tuples. Tuple is immutable if we want to modify a tuple we should change it to a list.
'''Syntax'''
tpl = ('item1', 'item2', 'item3','item4')
lst = list(tpl)
fruits = ('banana', 'orange', 'mango', 'lemon')
fruits = list(fruits)
fruits[0] = 'apple'
print(fruits) # ['apple', 'orange', 'mango', 'lemon']
fruits = tuple(fruits)
print(fruits) # ('apple', 'orange', 'mango', 'lemon')
['apple', 'orange', 'mango', 'lemon'] ('apple', 'orange', 'mango', 'lemon')
Dictionaries¶
Dictionaries are used to store data values in key:value pairs. A dictionary is a collection which is ordered*, changeable and does not allow duplicates. Here's how a dictionary is declared in python:
Declaring a dictionary in python¶
thisdict = {
"branch": "CS",
"students": 100,
"year": 2021,
"Marks" : [1,3,2,4,2,3,4]
}
print(thisdict) #{'branch': 'CS', 'students': 100, 'year': 2021, 'Marks': [1, 3, 2, 4, 2, 3, 4]}
{'branch': 'CS', 'students': 100, 'year': 2021, 'Marks': [1, 3, 2, 4, 2, 3, 4]}
Here's how we retrieve values from a dictionary¶
thisdict = {
"branch": "CS",
"students": 100,
"year": 2021,
}
print(thisdict["branch"]) #CS
CS
Access Dictionary Items¶
We can store the values of dictionary items as shown below.
x = thisdict["year"]
Alternatively we can use the get to get the same result:
x = thisdict.get("students")
Get Keys¶
The keys()
method will return a list of all the keys in the dictionary.
x = thisdict.keys()
We can add new items(keys and values) to a dictionary by assigning them in the following way:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
x = car.keys()
print(x) #before the change
#dict_keys(['brand', 'model', 'year'])
car["color"] = "white"
print(x) #after the change
#dict_keys(['brand', 'model', 'year', 'color'])
dict_keys(['brand', 'model', 'year']) dict_keys(['brand', 'model', 'year', 'color'])
Get Values¶
The values() method will return a list of all the values in the dictionary.
x = thisdict.values()
Here's how we modify the values for any of the keys in a dictionary.
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
x = car.values()
print(x) #before the change
#dict_values(['Ford', 'Mustang', 1964])
car["year"] = 2020
print(x) #after the change
#dict_values(['Ford', 'Mustang', 2020])
dict_values(['Ford', 'Mustang', 1964]) dict_values(['Ford', 'Mustang', 2020])
Functions¶
A function is a block of code which only runs when it is called. You can pass data, known as parameters, into a function. A function can return data as a result.
Creating a Function¶
def my_function():
print("Hello from a function")
The above code would not work until it is called. To call a function, use the function name followed by parenthesis:
def my_function():
print("Hello from a function")
my_function()
Hello from a function
Functions with Arguments¶
Information can be passed into functions as arguments.
Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just separate them with a comma.
Parameter and arguments can be used as the same thing.
def my_function(fname):
print(fname + " Refsnes")
my_function("Emil")
my_function("Tobias")
my_function("Linus")
Emil Refsnes Tobias Refsnes Linus Refsnes
By default, a function must be called with the correct number of arguments. Meaning that if your function expects 2 arguments, you have to call the function with 2 arguments, not more, and not less.
Arbitrary Arguments (*args)
¶
If the number of arguments are not known, then we use *
before the argument. This way the function will receive a tuple of arguments, and can access the items accordingly:
def my_function(*kids):
for item in kids:
print(item)
my_function("Emil", "Tobias", "Linus")
Emil Tobias Linus
Keyword Arguments¶
You can also send arguments with the key = value syntax.
This way the order of the arguments does not matter.
This reduces the number of errors as we do not need to consider the position of the parameters as discussed earlier.
def my_function(child3, child2, child1):
print("The youngest child is " + child3)
my_function(child1 = "Emil", child2 = "Tobias", child3 = "Linus")
The youngest child is Linus
Arbitrary Keyword Arguments (**kwargs)
¶
If you do not know how many keyword arguments that will be passed into your function, add two asterisk: ** before the parameter name in the function definition.
def my_function(**kid):
print("His last name is " + kid["lname"])
my_function(fname = "Tobias", lname = "Refsnes")
His last name is Refsnes
Default Parameter Value¶
The following example shows how to use a default parameter value.
If we call the function without argument, it uses the default value:
def my_function(country = "Norway"):
print("I am from " + country)
my_function("Sweden") # Sweden
my_function("India") # India
my_function() # Norway
my_function("Brazil") # Brazil
I am from Sweden I am from India I am from Norway I am from Brazil
You can send any data types of argument to a function (string, number, list, dictionary etc.), and it will be treated as the same data type inside the function.
E.g. if you send a List as an argument, it will still be a List when it reaches the function:
def my_function(food):
for x in food:
print(x)
fruits = ["apple", "banana", "cherry"]
my_function(fruits)
apple banana cherry
Return Values¶
To let a function return
a value, use the return statement:
def my_function(x):
return 5 * x
print(my_function(3)) #15
print(my_function(5)) #25
print(my_function(9)) #45
15 25 45
Data Types in Python¶
Variables can store data of different types, and different types can do different things. The important built-in Python data types include:
- Numerics :
int
,float
,complex
- Text :
str
- Booleans :
bool
- Sequences :
list
,tuple
,range
- Mappings :
dict
- Classes
- Functions
Getting the Data type¶
You can get the data type of any object by using the type()
function:
x = 5
print(type(x))
<class 'int'>
Setting a Specific Data Type¶
x = str("Hello World")
print(type(x))
<class 'str'>
Loops¶
For Loops¶
A for keyword is used to make a for loop, similar with other programming languages, but with some syntax differences. Loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a string).
- For loop with list
'''syntax'''
for iterator in lst:
'''code goes here'''
Example:
numbers = [0, 1, 2, 3, 4, 5]
for number in numbers: # number is temporary name to refer to the list's items, valid only inside this loop
print(number) # the numbers will be printed line by line, from 0 to 5
0 1 2 3 4 5
- For loop with string
'''syntax''' for iterator in string: code goes here
Example:
language = 'Python'
for letter in language:
print(letter)
for i in range(len(language)):
print(language[i])
P y t h o n P y t h o n
- For loop with tuple
'''syntax''' for iterator in tpl: code goes here
Example:
numbers = (0, 1, 2, 3, 4, 5)
for number in numbers:
print(number)
0 1 2 3 4 5
While Loops¶
We use the reserved word while to make a while loop. It is used to execute a block of statements repeatedly until a given condition is satisfied. When the condition becomes false, the lines of code after the loop will be continued to be executed.
'''syntax'''
while condition:
code goes here
Example:
count = 0
while count < 5:
print(count)
count = count + 1
# prints from 0 to 4
0 1 2 3 4
In the above while loop, the condition becomes false when count is 5. That is when the loop stops. If we are interested to run block of code once the condition is no longer true, we can use else.
'''syntax'''
while condition:
code goes here
else:
code goes here
count = 0
while count < 5:
print(count)
count = count + 1
else:
print(count)
0 1 2 3 4 5
Slicing Strings¶
In Python, we can slice strings into substrings.
language = 'Python'
first_three = language[0:3] # starts at zero index and up to 3 but not include 3
print(first_three) # Pyt
Pyt
Skipping Characters While Slicing¶
It is possible to skip characters while slicing by passing step argument to slice method.
language = 'Python'
pto = language[0:6:2] # Iterates from 0 to 6, in steps of 2
print(pto) # Pto
Pto
- Positive Indexing : We can specify a range of positive indexes by specifying the start, end and step, the return value will be a new list. (default values for start = 0, end = len(lst) - 1 (last item), step = 1)
fruits = ['banana', 'orange', 'mango', 'lemon']
all_fruits = fruits[0:4] # it returns all the fruits
# this will also give the same result as the one above
all_fruits = fruits[0:] # if we don't set where to stop it takes all the rest
orange_and_mango = fruits[1:3] # it does not include the first index
orange_mango_lemon = fruits[1:]
orange_and_lemon = fruits[::2] # here we used a 3rd argument, step. It will take every 2cnd item - ['banana', 'mango']
- Negative Indexing : We can specify a range of negative indexes by specifying the start, end and step, the return value will be a new list.
fruits = ['banana', 'orange', 'mango', 'lemon']
all_fruits = fruits[-4:] # it returns all the fruits
orange_and_mango = fruits[-3:-1] # it does not include the last index,['orange', 'mango']
orange_mango_lemon = fruits[-3:] # this will give starting from -3 to the end,['orange', 'mango', 'lemon']
reverse_fruits = fruits[::-1] # a negative step will take the list in reverse order,['lemon', 'mango', 'orange', 'banana']
Lambda Functions¶
A lambda function is a small anonymous function.
A lambda function can take any number of arguments, but can only have one expression.
Examples :
x = lambda a : a + 10
print(x(5))
15
x = lambda a, b, c : a + b + c
print(x(5, 6, 2))
13
Error Handling¶
Python offers an efficint way to handle errors. This can be done using the try
, except
blocks.
try:
print(x)
except:
print("An exception occurred")
try:
print("Hello")
except:
print("Something went wrong")
Hello Nothing went wrong