Python fundamentals - Part 2#

  • In this lesson we continue where we left off last time (Python fundamentals - Part 1)

Functions#

  • Functions help us to break our code into smaller code blocks which are then easier to manage
  • Function is run only when it is called
  • Function can take data as input, which is called parameters
  • Python functions can be divided into two categories:
    • Functions defined by user
    • Python built-in functions (for example sum(), len(), abs() etc.)
  • Below is an example of a function that calculates the average of numbers contained within the input list
# Function definition
def calculate_avg(lst): 
    return sum(lst)/len(lst)

print(calculate_avg([1,2,3,4,5,6,7,8,9]))
5.0

  • It is important to notice the scope of variables which are defined inside or outside the function
  • Below is an example where the variable x set inside the add_to_num() function does not affect the value of the variable with the same name outside the function
x = 10

def add_to_num(num):
    x = 5
    return num + x

print(add_to_num(3))
print("The value of x outside the function is " + str(x))
8
The value of x outside the function is 10

Conditions#

  • Making decisions and only running code when given conditions are met is crucial part for making programs work effectively
  • Conditions can be built with if, elif and else statements
  • Conditions will be read one by one starting from the top
  • Code block defined after the condition will only be run if the expression in condition is True
  • Below is an example where function input list will be tested for the following conditions:
    1. List is empty (length is 0)
    2. List length is 5 or less
    3. List length is 6 or more
# Function to test if input list of numbers matches the given conditions
def test_list(lst):
    if len(lst) == 0:
        print("List is empty!")
    elif len(lst) <= 5:
        print("This is a small list.")
    else:
        print("This is a big list.")

# Test
test_list([1,2,3,4,5])
test_list([10,20,30,40,50,60,70])
test_list([])
This is a small list.
This is a big list.
List is empty!

For loops#

  • For loops are used to iterate through a sequence, for example a list or individial characters in a string
  • Python built-in function range() can also be used with for loop to define how many rounds should the loop be run
  • When loop is run with range function, it starts from number 0
  • Below is an example where numbers from 0 to 4 are printed
# Print numbers from 0 to 4
for i in range(5):
    print(i)
0
1
2
3
4

  • Below is another example where given list is iterated and only numbers that are divisable with 3 are stored in a new list
def check_the_list(lst):
    new_lst = []
    for i in lst:
        if i % 3 == 0:
            new_lst.append(i)
    return new_lst

# Test
check_the_list([10,12,30,33,35,40,42,45,50])
[12, 30, 33, 42, 45]
  • Another example of for loops is presented below where two dimensional list containing numbers is iterated and all elements that are in range 10-30 (inclusive are printed)
def print_numbers_in_range(matrix):
    for i in matrix:
        for j in i:
            if 10 <= j <= 30:
                print(j)

# Test
m = [[30,12,14,9,31],[2,4,13,39,10],[1,32,22,24,5]]
print_numbers_in_range(m)
30
12
14
13
10
22
24

While loops#

  • Whereas with for loop we know how many loop iterations we are going to do, while loop is a great tool when the amount of iterations is unknown
  • Loop is run until the exit condition is met
  • Below is an example where number is processed inside the loop until it reaches zero
# Run the loop until number will reach zero
num = 100
while(num > 0):
    print(num)
    num = num // 2

100
50
25
12
6
3
1

Loop control statements#

  • Control statements can be used inside loop if exceptional operation from loops normal sequence is required
  • Next we are going through the following control statements:
    • Break
    • Continue
  • Below is a set of flow diagrams describing the logic behind these two control statements

Control statement logic

  • As can be seen from the diagrams:
    • break statement will stop the execution of current loop and continue the execution of code normally that is below the loop structure
    • continue statement will skip the rest of the code in current loop iteration cycle
  • Below are some examples on how these two statements work
# Break statement test
for i in range(10):
    if i == 5:
        break
    print(i)
0
1
2
3
4

# Continue statement test
for i in range(10):
    if i == 5:
        continue
    print(i)
0
1
2
3
4
6
7
8
9

Exception handling#

  • Exception can be described as something that interferes the normal program execution
  • Exception handling can be done with try-except pair where the actual code to be run will be placed in the try block and possible error handling that occurs when the code is run will be placed in the except block
  • Below is an example where list of number pairs is taken to the function as an input and the division result of these numbers is returned
  • With this example we would receive two errors:
    • First error comes from the fifth iteration round in the loop where the calculation of numbers 9 and 0 is performed (ZeroDivisionError: division by zero)
    • Second error will not be listed since the iteration will not reach the sixth round because of the first error occurrance, but it would be (IndexError: list index out of range)
# Function to test number pairs
def test_pairs(lst):
    for i in lst:
        print(i[0] / i[1])

# Test
test_pairs([[1,2],[3,4],[5,6],[7,8],[9,0],[10]])
0.5
0.75
0.8333333333333334
0.875

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-53-cfafe696062f> in <module>
      5 
      6 # Test
----> 7 test_pairs([[1,2],[3,4],[5,6],[7,8],[10]])

<ipython-input-53-cfafe696062f> in test_pairs(lst)
      2 def test_pairs(lst):
      3     for i in lst:
----> 4         print(i[0] / i[1])
      5 
      6 # Test

IndexError: list index out of range
  • We could now try to modify our code so we could catch those errors
  • Below is a refreshed version of the code where exception handling is implemented
  • The code execution will now stop to the first error
# Function to test number pairs
def test_pairs(lst):
    try:
        for i in lst:
            print(i[0] / i[1])
    except ZeroDivisionError:
        print("Number cannot be divided with zero!")
    except IndexError:
        print("List does not have that many numbers!")

# Test
test_pairs([[1,2],[3,4],[5,6],[7,8],[9,0],[10]])
0.5
0.75
0.8333333333333334
0.875
Number cannot be divided with zero!

Classes and objects#

  • Like many other programming languages, also Python has OOP (Object Oriented Programming)
  • Objects are created through classes
  • Classes can have
    • Attributes: Save the information of the object
    • Methods: Modify or get object information
  • Below is an example where Player class is defined and an example player is created through that class
# Define person class
class Player:
    def __init__(self, firstname, lastname, age, status):
        self.firstname = firstname
        self.lastname = lastname
        self.age = age
        self.status = status

    def check_age(self):
        print(self.firstname + " " + self.lastname + " is " + str(self.age) + " old.")

    def change_status(self,new_status):
        self.status = new_status

# Test
Player1 = Player("Harry","Johnson",42,"Available")
Player1.check_age()
Player1.change_status("Busy")
Player1.status
Harry Johnson is 42 old.

'Busy'