In this notebook, we will explore some fundamental concepts in Python that are essential for writing clean, efficient, and maintainable code. These concepts include:
- Classes and Objects
- Formatted Strings
- Handling Errors
- Variable Scopes
Don't Miss Any Updates!
Before we continue, we have a humble request, to be among the first to hear about future updates of the course materials, simply enter your email below, follow us on (formally Twitter), or subscribe to our YouTube channel.
Classes and Objects
In Python, everything is an object. A class helps us create objects.
Creating a Class
Use the class
keyword to create a class
Here is the syntax:
class className:
statement(s)
Below is an example:
class Person:
first_name = "Betty"
last_name = "Kawala"
age = 30
Instantiating a class
Now we can ceate an object from the class by instantiating it.
To instantiate a class, add round brackets to the class name.
person_obj1 = Person()
type(person_obj1)
__main__.Person
After instantiating a class, we can now access the object's properties.
# print attributes
print(person_obj1.first_name)
print(person_obj1.last_name)
print(person_obj1.age)
Betty
Kawala
30
Class Attributes
A class can have attributes. Forexample the Person Class can have attributes like the name
, height
and feet
class Person:
def __init__(self, name, height, feet):
self.name = name
self.height = height
self.feet = feet
Note!
For now, focus on the syntax. Later we will explain the init()
function and the self
parameter.
Now that our class is ready, we can now instantiate it and provide values to it's attributes.
This process can also be called "creating an instance of a class".
An instance is simply the object created from a class
In this example, person_obj1
is a unique instance of the person class.
# create a class instance
person_obj = Person(
name='Betty Kawala',
height=1.57,
feet=4
)
After that, we can now access the properties of the instance (object)
# accessing the properties
print('Name:', person_obj.name)
print('Height:', person_obj.height)
print('Feet:', person_obj.feet)
Name: Betty Kawala
Height: 1.57
Feet: 4
The self
parameter allows us to access the attributes and methods of a class
The __init__()
function allows us to provide values for the attributes of a class
Instances are unique
Let's say you have 500 people and you need to manage their data.
It is inefficient to create a variable for each of them, instead, you can create unique instances of a class.
In this example, the student1 and student2 instances are different from each other
class Student:
def __init__(self, id_number, name, age):
self.id_number = id_number
self.name = name
self.age = age
student1 = Student(5243, "Mary Doe", 18)
student2 = Student(3221, "John Doe", 18)
print("Student 1 ID:", student1.id_number)
print("Student 1 Name:", student1.name)
print("Student 1 Age:", student1.age)
print("---------------------")
print("Student 2 ID:", student2.id_number)
print("Student 2 Name:", student2.name)
print("Student 2 Age:", student2.age)
Student 1 ID: 5243
Student 1 Name: Mary Doe
Student 1 Age: 18
---------------------
Student 2 ID: 3221
Student 2 Name: John Doe
Student 2 Age: 18
Methods
Methods are functions that can access the class attributes.
These methods should be defined (created) inside the class
class Person:
def __init__(self, name, height, feet):
self.name = name
self.height = height
self.feet = feet
def jump(self):
return "I'm jumping " + str(self.feet) + " Feet"
person_obj1 = Person(name='Juma', height=1.59, feet=5)
print(person_obj1.jump())
I'm jumping 5 Feet
As you may notice, we used the self
parameter to access the feet
attribute
You can also pass an argument to a method.
class Student:
def __init__(self, id_number, name, age):
self.id_number = id_number
self.name = name
self.age = age
def greet_student(self, greetings):
print("Hello" + self.name + ", " + greetings)
student1 = Student(43221, "Agaba Calvin", 18)
# the string below will be passed as
# the value of the greetings parameter
student1.greet_student("Welcome to this Python Tutorial!")
HelloAgaba Calvin, Welcome to this Python Tutorial!
Python Inheritance
Inheritance is a feature that allows us to create a class that inherits the attributes or properties and methods of another class
Example
The Animal
class below can be used to tell that an animal can eat
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name} is eating.")
Let's say we need to create another class called Dog.
Since a dog is also an animal, it's more efficient to have access to all the properties and methods of the Animal
class than to create another
This example creates a class named Dog
and inherits from the Animal
class
class Dog(Animal):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def sound(self):
print(self.name, "barks")
Note!
As you may notice, to inherit from a parent, we simply pass the name of that class as a parameter of the child class.
Now we can use the properties and methods of both the Animal
and the Dog
classes using just one instance
dog1 = Dog(name='Brian', age=8, color='White')
dog1.eat()
dog1.sound()
Brian is eating.
Brian barks
The super()
and __init__
functions found in the Dog
class allow us to inherit the properties and methods of the Animal
class.
Parent and Child Class
The parent class is the class from whick the other class inherits from.
The child class is the the class that inherits from another class
In our example above, the Animal
is the parent class while the Dog
class is the child class
Formatted Strings
In Python, we can format a string by adding substring/s within it.
The format()
function allows us to format strings.
Placeholders {}
Placeholders help us control which part of the string should be formated.
They are defined using curly braces {}
.
In this example, we will concatenate (add) a substring to where the curly braces are placed
text = "I love {} very much!"
formatted_text = text.format("Python")
print(formatted_text)
I love Python very much!
Multiple placeholders
If you want to format multiple parts of a string, use multiple placeholders.
text = '{} loves to code in {}'
formatted_text = text.format('Juma', 'JavaScript')
print(formatted_text)
Juma loves to code in JavaScript
Using Indexes
We can use index numbers to specify exactly where the values should be placed.
The index numbers should be inside the curly braces: {index_numbers}
text = 'I love {2}, {1} and {0} very much!'
formatted_text = text.format('Python', 'JavaScript', 'HTML')
print(formatted_text)
I love HTML, JavaScript and Python very much!
Note!
0 represents the first value, 1 represents the second value and so on.
Using Named Indexes
We can also use named indexes to specify exactly where the values should be placed.
The arguments of the format()
function should be in key/value
pairs ie key=value
.
The key/value
pairs should be separated by commas.
text = 'The color of the {fruit} is {color}.'
formatted_text = text.format(fruit='banana', color='yellow')
print(formatted_text)
The color of the banana is yellow.
Literal String Interpolation
Literal string interpolation allows you to use expression inside your strings.
Simply add f
before you opening quote, then surround your expressions with curly braces {}
.
name = 'Juma';
language = 'JavaScript'
statement = f'{name} loves to code in {language}'
print(statement)
Juma loves to code in JavaScript
Here's another example
number1 = 5
number2 = 7
answer = f'The summation of 5 and 7 is {number1 + number2}'
print(answer)
The summation of 5 and 7 is 12
Errors in Python
When coding in Python, you will encounter errors.
When errors occur, the program crashes or stops executing.
Fortunately, errors can be handled in Python
The try...except
statment
The try...except
statement is used to handle exceptions(errors)
The try
statement takes a block of code to test for errors
The except
statement handles the exceptions.
try:
# age = input('Enter your age: ')
age = '32'
if age >= 18:
print('Your vote has been cast')
else:
print('You are not eligible to vote')
except:
print('A problem occured while picking your age \n'
'You did not enter a number')
text = "\nHello world!"
print(text)
A problem occured while picking your age
You did not enter a number
Hello world!
Note!
Even when the exception was thrown, the codes after the try...except were still executed
The else
statement
The else statement is executed if there are no exceptions thrown.
try:
text = "Hello World!"
print(text)
except:
print("An error occurred.")
else:
print("No exception was thrown!")
Hello World!
No exception was thrown!
The finally
statement
The finally
statement is executed whether or not an exception is thrown.
try:
text = "hello world"
print(text)
except:
print("An error occured.")
finally:
print("Hello, I am still printed.")
print("----------------------")
# an exception will be thrown here
try:
print(undefined_variable)
except:
print("An error occured.")
finally:
print("Hello, I am still printed.")
hello world
Hello, I am still printed.
----------------------
An error occured.
Hello, I am still printed.
Throw Exceptions
We can intentionally throw and exception to stop the execution of a program.
The raise
keyword throws an excrption.
# Creating your own errors
try:
age = 14
if age < 18:
raise Exception('Not an adult')
except Exception as error:
print('A problem occurred \n'
f'Error: {error}')
A problem occurred
Error: Not an adult
Kinds of Exceptions
In Python, there are different kinds of exceptions and we can handle them individually with the try...except
statement.
try:
# statements
except ExceptionKind:
#statments
One of the most common kind of exceptions is the NameError
. This is thrown when you use a variable that is not defined
try:
print(rand_var)
except NameError:
print('You used a variable that is not defined!')
You used a variable that is not defined!
Variable Scope
Python Variable Scopes
The accessibility of variable depends on its scope. In Python, there are two variable scopes:
- Global Scope
- Local Scope
Global Scope
A variable that is defined (created) outside a function has a global scope
A global variable can be accessed anywhere in a program
name = 'Viola'
# name can be accessed here
print(name)
def greet():
# name can be accessed here
print('Hello ' + name)
greet()
Viola
Hello Viola
Local Scope
A variable that is defined (created) inside a function has a local scope. A local scope variable can only be accessed and used inside the function.
def greet():
local_name = 'Viola'
print('Hello ' + local_name)
greet()
try:
# local_name cannot be accessed here
print(local_name)
except Exception as e:
print(e)
Hello Viola
name 'local_name' is not defined
The global
Keyword
We can force a local variable to be a global variable by using the global
keyword.
# Global Keyword
def add():
global summ
number1 = 5
number2 = 7
summ = number1 + number2
return summ
add()
# summ is accessible even outside the function
print(summ)
12
What's on your mind? Put it in the comments!