HomeOperationsAutomated OperationsMoving up the stack - time to learn Python - part 5

Moving up the stack – time to learn Python – part 5

In our last article on my journey into Python, we talked at depth about the various operators that Python can use.  If you managed to plough your way through that post, my hat off to you.

To refresh your memory on the first three articles, you can read them at the links shown below:

Today we will continue meandering around the building site looking at the brick work and foundations.  This article will discuss, Python Loops and introduce functions and Dictionaries.

It is time to take a trip on the hyper-LOOP

The concept of a loop in essential in the vast majority of programming languages, and Python is no exception to that statement, without the ability to iterate through a list of numbers or strings, the language would need to write every step of the process manually for each and every input.  I think you will agree that would be both tedious and very error prone.  Python loops are a powerful way to iterate over data, perform repeated tasks, or create complex patterns. In this article, we will explore the different types of loops in Python, how to use them, and some examples of their applications.

The first type and most common type of loop in Python is the for loop, this executes a block of code for each element in an given object, such as a list, a tuple, a string, or a range. Below is a simple example, where we use a for loop to print the numbers from 1 to 10:

for i in range(1, 11):
    print(i)

Funny story the first time I wrote this out I forgot to indent the print statement, it did not like it when I run it the first time 😊, Python is very fussy about proper indentation.

python - Houston we have an error
Houston we have an error, Python is very fussy about proper indentation.

Once this was corrected the output is of this simply a output of 1 to 10:

Python - 1 to 10

As we have already stated the loop can also iterate though a string,  This simple script will effectively spell Python.

word = "Python"
for char in word:
    print(char)

running this particular script results in the following output, as you can see Python is spelt correctly 😉:

Python can spell

Now instead of running though the characters in a word lets iterate though a list of words.

fruits = ["apple",  "orange", "Peach"]
for fruit in fruits:
    print(fruit)

Running this script will result in the following output.

python fruit

So far we have only looked a simple for loop,  Python also as a construct called the while loop, which is very useful for iterating through a list of objects and executing the block of code as long as a condition is true. For example, so looking at our original example we can use a while loop to print the numbers from 1 to 10:

i = 1
while i <= 10:
    print(i)
    i = i + 1

although the output is the same as the for loop shown above the process is completely different.  In the first loop we simply printed out the numbers 1 to 10 which equates to the stated range (1-11), in the above script we are printing out a list of numbers while the number is less or equal to 10.

Python counting while 1

Although the while loops is powerful, we need to be careful when using them, as they can create infinite loops if the condition never becomes false.   Run the following script to see an example.

while True:
for i in range(1, 11):
    print(i)

If you are stuck in the infinity loop remember to use “Ctrl-C” to escape it.  It is relatively easy to avoid this, by using the “break” statement to exit the loop, or the “continue” statement to skip the current iteration and move on to the next one. For example, we can use a break statement to stop the loop when i reaches 5:

i = 1
while i <= 10:
    print(i)
    if i == 5:
        break
    i = i + 1

The output is:

python - take a break a 5

This is an example where we use a “continue” statement to skip the even numbers and only print the odd ones:

i = 1
while i <= 10:
    if i % 2 == 0:
        i = i + 1
        continue
    print(i)
    i = i + 1

Running this code will result in the following output:

python - let's gather the odd ones

Loops are useful for many tasks in Python, such as processing data, generating patterns, or creating games. Here are some more examples of how the power of loops in Python:

This example used a nested loop to create a multiplication table:

for i in range(1, 11):
    for j in range(1, 11):
        print(i * j, end=" ")
    print()

Running this script results in the following output:

python - multiplication table

Loops can be used to filter here I show how to create a new list that contains only the positive numbers from the imputed list:

numbers = [9, 7, 5, 3, -5, -2, -7, -9]
positive_numbers = [n for n in numbers if n >0]
print(positive_numbers)

Running this script will result in the following output.

python gather all the odd ones

Here we are creating a spiralled pentagram by importing turtle module (a graphical library for drawing shapes):

import turtle
t = turtle.Turtle()
t.speed(0)
for i in range(100):
    t.forward(i *10)
    t.right(144)
turtle.done()

when we run this script nothing appears to happen in the terminal

However, look we’ve made some magic, we have created a pretty graphical pentagram

python - pretty pentagram

Now that we understand the concept of loops it is time to move on the concept of functions.

What are Functions and why we need them

The function is core component of many programming languages and once again Python is no exception to that rule, paring back the definition of a function to is base minimum it is a block of code that performs a specific task. It takes input, processes it, and produces output. A Function is designed to be reusable, meaning that they can be called multiple times with different inputs to produce different outputs. We define a function In Python, “def” keyword which is followed by the function name, the input parameters, and the code block that performs the task.

Functions are effectively the core building blocks of a programming language as they help to break down complex tasks into smaller, more manageable pieces. This makes the code easier to read, write, and debug. Functions also reusable which saves time and will help to reduce errors.

For example, suppose you need to calculate the area of a rectangle in your program. You can write a function that takes the length and width of the rectangle as input parameters and returns the area as output. This function can be called multiple times with different inputs to calculate the area of different rectangles. Below is an example of a function that calculates the area of a rectangle:

def rectangle_area(length, width):
    area = length * width
    return area

Now you cannot just run this to utilise this or any function it needs to be called, to do this you call it with the length and width of the rectangle as input parameters:

area1 = rectangle_area(5, 10)
area2 = rectangle_area(3, 7)

In this example, the function “rectangle_area” takes two input parameters (length and width) and returns the area of the rectangle. The function is called twice with different inputs to calculate the area of two different rectangles.  Here is a script that prints out the area of a rectangle in Python using the function and calls you provided:

def rectangle_area(length, width):
    area = length * width
    return area
area1 = rectangle_area(5, 10)
area2 = rectangle_area(3, 7)
print(f"The area of the first rectangle is {area1}")
print(f"The area of the second rectangle is {area2}")

This script defines the rectangle_area() function that takes two arguments, length and width, and returns their product. It then calls this function twice with different arguments and stores the results in area1 and area2. Finally, it prints out the areas of both rectangles using formatted strings. When you run this script you should receive the following output:

python - area calculation

Types of Functions in Python

There are two types of Functions in Python, you have already seen examples of the first type the built-in function in a couple of the examples in this and earlier articles, turtle(), Print(),int(),float() etc. The second type of function is termed a user-defined function and our “rectangle_area” function is a good example of one of that type.

User-defined functions are functions that we the programmer create to perform specific tasks, just like built-in functions they can be called multiple times with different inputs to produce different outputs. To create a User-defined functions you must define it using the “def” keyword followed by the function name, input parameters, and the code block that performs the task, this is not needed when you are using a built-in function.

It is time for another example, here we have created a user-defined function that calculates the factorial of a number:

def factorial(num):
   if num == 0:
      return 1
   else:
      return num * factorial(num - 1)

below is a python script that wraps the function into a Python script that uses our factorial() function:

def factorial(num):
   if num == 0:
      return 1
   else:
      return num * factorial(num - 1)
num = int(input("Enter a number: "))
print(f"The factorial of {num} is {factorial(num)}")

This script defines the factorial() function that takes an integer argument and returns its factorial. It then prompts the user to enter a number, reads the input as an integer, and calls the factorial() function with the input as its argument. Finally we print out the result using a built-in function (print()).  Running this script results in the following output.

python - factorial function

Wait what about Lambda functions?

There is another type of function in Python, these are called Lambda Functions.  A Lambda function is an anonymous function in Python that is defined without a name. They are also known as “inline functions” or “anonymous functions”. Lambda functions are used when we need a small function and restricted functions, it can only have a single line and is utilised for a short period of time.

Its syntax is “lambda arguments: expression”, this lambda being the effective “function name”, the arguments are the input arguments for the function, and the expression is the output of the function.  As we have already alluded to Lambda functions are used as a shortcut for defining simple functions that are only used once. Here is an example of a lambda function that squares its input:

square = lambda x: x**2

This defines a lambda function called square that takes one argument x and returns its square. Lambda functions can be used anywhere that a regular function can be used, such as in higher-order functions like map() and filter().  Lets have a look at an example that uses the lambda function shown above.

square = lambda x: x**2
num = int(input("Enter a number: "))
print(f"The square of {num} is {square(num)}")

This script defines the square lambda function that takes one argument and returns its square. It then prompts the user to enter a number, reads the input as an integer, and calls the square function with the input as its argument.  Finally, we print out the result using a formatted string.  Let’s see the result where the inputted number is 49:

Python - lambda Squared

Next we will look at Classes and Objects,  If you remember when we started this series on learning python we briefly discussed that python is an interpreted language, it is however, also language based on the principles of Object-oriented programming like C++ and Go, this means that Python supports and requires the use of Classes and Objects

What are Python Classes and Objects?

Its definition time again, a class is a blueprint or template for creating objects. It defines a set of attributes and methods that the objects of that class will have. An object, on the other hand, is an instance of a class. It is a data structure that contains data and the methods that operate on that data.  This is quite a complex concept, so an example may be in order 😊. To create a class in Python we use the ”class” keyword followed by the name of the class. Here is an example that defines the class car.:

class Car:
   def __init__(self, make, model, year):
      self.make = make
      self.model = model
      self.year = year
   def start(self):
      print("The car has started.")
   def stop(self):
      print("The car has stopped.")

In this example, we have defined the “Car” class with three attributes (`make`, `model`, and `year`) and two methods (“start” and “stop”). The “__init__” method is a special method that is called when an object of the class is created, we were first introduced to the “__init__” method in our forth article. It initializes the attributes of the object with the values passed as arguments.  Now that we have an understanding of a class, let’s create our first object using this class to do this we can use an example like below:

my_car = Car("Morris", "Minor", 1965)

This creates an object with the make “Morris”, model “Minor”, and year 1965.  To prove that this is working here is an example script that uses our Car class:

class Car:
   def __init__(self, make, model, year):
      self.make = make
      self.model = model
      self.year = year
def start(self):
   print("The car has started.")
def stop(self):
   print("The car has stopped.")
my_car = Car("Morris", "Minor", 1965)
print(f"Make: {my_car.make}, Model: {my_car.model}, Year: {my_car.year}")
my_car.start()
my_car.stop()

This script defines the Car class that takes three arguments and initializes them as instance variables. It then creates an instance of the Car class called my_car with the specified arguments. Finally, it prints out the values of the instance variables using a formatted string and calls both the start() and stop() methods.  Running this script results in the following output:

Python - Classes

What are the purposes of Python Classes and Objects?

Classes and objects are essential concepts in OOP. They allow us to organize our code into reusable and modular components. By defining a class, we can create multiple objects with the same set of attributes and methods. This makes our code more efficient, easier to maintain, and less prone to errors.

For example, let’s say we want to create a program that manages a fleet of cars. Without classes and objects, we would have to define separate variables for each car’s make, model, year, and other attributes. This would quickly become unwieldy as the number of cars increases. With classes and objects, we can define a `Car` class once and create as many objects as we need.

Another advantage of classes and objects is that they support inheritance. Inheritance allows us to create a new class based on an existing class. The new class inherits all the attributes and methods of the existing class and can add its own attributes and methods or modify existing ones. This makes our code more flexible and adaptable to changing requirements. Let’s have a look as something a little more useful, below we created a class called BankAccount, that has two attributes:  Account_number and Balance

class BankAccount:
   def __init__(self, account_number, balance):
      self.account_number = account_number
      self.balance = balance
   def deposit(self, amount):
      self.balance += amount
   def withdraw(self, amount):
      if amount <= self.balance:
         self.balance -= amount
      else:
         print("Insufficient balance.")
my_account = BankAccount("1234567890", 1000)
my_account.deposit(500)
my_account.withdraw(200)
print(my_account.balance)

In this example, we have defined a “BankAccount” class with two attributes (`account_number` and `balance`) and two methods (`deposit` and `withdraw`). We have also created an object “my_account” with an initial balance of 1000. We then deposit 500 into the account and withdraw 200. Finally, we print the remaining balance.  Running this script will result in the following output.

python - bank class

The next thing we will investigate is the concept of Python Dictionaries

What are Python Dictionaries?

At its core, a dictionary is a collection of key-value pairs. Each key is associated with a value, and you can use the key to retrieve the value later on. In Python, dictionaries are created using curly braces ({}) and colons (:).  In concept, a Dictionary is very similar to that of a map in Terraform or GoLang.  Below is a simple dictionary

my_dict = {"apple": 1, "orange": 2, "peach": 3}

In this dictionary, the keys are “apple”, “orange”, and “peach”. The values associated with those keys are 1, 2, and 3, respectively. You can access the values in the dictionary by using the keys:

print(my_dict["apple"]) # Output: 1
print(my_dict["peach"]) # Output: 3

Create the following script:

my_dict = {"apple":1, "Orange":2,"Peach":3}
print(my_dict["apple"])
print(my_dict["Peach"])

When you run the script, it will output the following result:

python - dictionary fruit

Why Do We Need Python Dictionaries?

Dictionaries are incredibly useful because they allow you to store data in a way that’s easy to access and manipulate. For example, let’s say you’re building a program that needs to keep track of the number of times each word appears in a text file. You could use a list to store the words and their counts, but that would be inefficient and difficult to work with. Instead, you could use a dictionary:

word_counts = {}
with open("text_file.txt", "r") as file:
   for line in file:
      words = line.strip().split()
      for word in words:
         if word not in word_counts:
            word_counts[word] = 1
         else:
            word_counts[word] += 1

In this example, we’re using a dictionary to store the number of times each word appears in the text file. The keys are the words themselves, and the values are the counts. We’re iterating through each line in the file, splitting it into individual words, and adding them to the dictionary. If a word isn’t already in the dictionary, we create a new key-value pair with a count of 1. If it is already in the dictionary, we increment the count.  Let’s wrap this up in a working script

word_counts = {}
with open("lorumipsum.txt", "r") as file:
   for line in file:
      words = line.strip().split()
      for word in words:
         if word not in word_counts:
            word_counts[word] = 1
         else:
            word_counts[word] += 1
sorted_word_counts = sorted(word_counts.items(), key=lambda x: x[1], reverse=True)
for word, count in sorted_word_counts:
   print(f"{word}: {count}")

this script is actually quite complicated, but it should be easily understandable with what we have covered so far.  We have already discussed the dictionary creation, so we will concentrate on the logic.  We have another example of a lambda function In the line “sorted_word_counts” where we loop through the dictionary and organise the inputted words with the largest number of occurances first and then decreasing thereafter.  Next we iterate though that output and prints the output to standard output. (we have concatenated this output).

python - dictionary word count

Working with Python Dictionaries

Now that we know what dictionaries are and why we need them, let’s take a look at some common operations you can perform on them.  To show these functions we are going back to our simple fruit dictionary.

Adding and Updating Key-Value Pairs

To add a new key-value pair to a dictionary, simply assign a value to a new key:

my_dict = {"apple": 1, "orange": 2, “peach”:3}
my_dict["grape"] = 4
print(my_dict)

running this outputs:

python - fruit manipulation

To update an existing key-value pair, simply assign a new value to the existing key:

print(my_dict) 
my_dict["apple"] = 5
print(my_dict)

this update results in the following output, note that the value of the apple key has changed from 1 to 5

Accessing Values

To access the value associated with a key in a dictionary, use square brackets:

my_dict = {"apple": 1, "orange": 2}
print(my_dict["apple"])

If the key isn’t in the dictionary, this will raise a KeyError.

my_dict = {"apple": 1, "orange": 2, "peach":3}
my_dict["grape"] = 4
print(my_dict("orange", 0))

This results in the following response.

python error

To avoid this error, you can use the get() method:

my_dict = {"apple": 1, "orange": 2, "peach":3, "grape":4}
print(my_dict.get("orange", 4))

In this example, we’re trying to access the value associated with the key “orange”. Since this key isn’t in the dictionary, the get() method returns the correct key instead of raising an error.

python - dict.get method

Iterating Over Keys and Values

To iterate over the keys in a dictionary, use the keys() method:

my_dict = {"apple": 1, "orange": 2,”peach”:3}
my_dict = [“grape”] = 4
for key in my_dict.keys():
   print(key)

This will output:

python dict.key

To iterate over the values in a dictionary, use the values() method:

my_dict = {"apple": 1, "orange": 2}
for value in my_dict.values():
   print(value)

This will output:

Python Dict.values

Finally to iterate over both keys and values at the same time, use the items() method:

my_dict = {"apple": 1, "orange": 2}
for key, value in my_dict.items():
   print(key, value)

This will output:

python dict.items

I think we can agree that Python dictionaries are an incredibly powerful tool for storing and retrieving data. They allow you to easily work with key-value pairs and perform operations like adding and updating pairs, accessing values, and iterating over keys and values. Whether you’re building a complex application or just working on a simple script, dictionaries can help make your code more efficient and intuitive.

Summary

We have covered a lot of ground in this article, diving into loops, functions and dictionaries.  These are core functions of Python, but as we have shown they are very powerful.  In our next article we will discuss and investigate module and packages.

NEWSLETTER

Receive our top stories directly in your inbox!

Sign up for our Newsletters

LET'S CONNECT