Complete Python Tutorial
Learn Python from the fundamentals to practical programming through clear explanations, examples, exercises and projects.
Introduction
Python is a powerful and beginner-friendly programming language used to build software, automate tasks, analyze data, develop websites, create artificial intelligence systems and much more.
This course is designed to take you from the fundamentals of Python to writing useful programs of your own. You do not need previous programming experience to begin.
You can learn at your own pace, practice each concept and return to any section whenever you need a refresher.
Why Was Python Named Python?
Before learning how to write Python code, it is interesting to know where the name came from.
Python was created by Guido van Rossum and first released in 1991. The name was not chosen because the programming language was related to snakes.
Guido was a fan of a British comedy television series called Monty Python's Flying Circus. While developing the language, he wanted a name that was short, distinctive and slightly playful.
He therefore chose the name Python, inspired by Monty Python.
The snake became strongly associated with Python later, which is why you often see snake imagery and names such as Python represented by a snake.
↑ Back to Python ContentsLearn Python Your Way
People learn differently. Some people understand programming concepts more easily by watching someone explain them, while others prefer reading explanations and working through examples at their own pace.
That is why this course gives you both options. You can watch the embedded video or work through the written lessons below, section by section.
Python Video Lesson
Prefer learning through video? Start here. You can also continue with the written lessons below.
Python Course Contents
Select any topic to open its lessons.
Ready to Take Your Projects Online?
As you progress through Python, you may eventually want to publish a website, portfolio or web application online. A reliable hosting service can help you take your projects from your computer to the web.
Recommended: Hostinger
Explore Hostinger → Disclosure: This section contains an affiliate link. Gabbywall may earn a commission if you make a qualifying purchase through the link.Getting Started With Python
Before writing larger Python programs, you need to understand how Python gets onto your computer, where you write your code, how Python runs that code and some of the basic rules that determine whether your program works.
This section takes you from having Python installed to writing and running your first simple Python program.
What You Will Learn
- How to install Python.
- How to check whether Python is installed.
- How Python code is executed.
- What the Python interpreter does.
- Different ways to write and run Python code.
- What an IDE and code editor are.
- How to create your first Python program.
- Basic Python syntax.
- How indentation works in Python.
- How to write comments.
- How to avoid some common beginner mistakes.
Installing Python
Python is a programming language, but before you can normally write and execute Python programs on your computer, you need a Python interpreter.
The interpreter is the program that reads your Python source code and executes it. Python's official documentation describes the interpreter as the program through which Python commands and scripts are executed. :contentReference[oaicite:1]{index=1}
Where Do You Get Python?
Python is available for major operating systems including Windows, macOS and Linux. The official Python website provides installers and documentation for supported platforms.
When installing Python, make sure you are installing a current supported version of Python 3.
How Do You Know If Python Is Installed?
After installation, you can check from a terminal or command prompt.
On many systems, you can try:
python --version
Depending on your operating system and installation, you may instead use:
python3 --version
On Windows systems with the Python launcher, you may also see
commands using py. The exact command available can
depend on how Python was installed. :contentReference[oaicite:2]{index=2}
If Python is installed correctly, the terminal should display a Python version number.
Python 3.x.x
What If the Command Does Not Work?
If your computer says that the command cannot be found, Python may not be installed, or the command may not be available through your system's PATH configuration.
Do not panic. This does not mean that Python itself is broken. It usually means your computer cannot locate the Python installation using the command you entered.
This is one reason beginners should learn the difference between installing a program and making the program accessible from the terminal.
↑ Back to Python ContentsRunning Python
Once Python is installed, there are several ways you can run Python code.
Two important approaches are:
- Using Python interactively.
- Running a Python script saved in a file.
1. Using Python Interactively
Interactive mode allows you to type Python instructions directly into the interpreter and immediately see the result.
When the interpreter is running interactively, you will commonly see the prompt:
>>>
For example, you can type:
2 + 3
Python immediately evaluates the expression.
5
This makes interactive mode useful when you want to quickly test an idea, experiment with a function or check what a particular Python expression does.
The official Python documentation describes interactive mode as a mode in which the interpreter reads commands and executes them as you enter them. :contentReference[oaicite:3]{index=3}
2. Running a Python Script
For larger programs, you normally write your code in a file and
save it with the .py extension.
For example:
hello.py
Inside that file you could write:
print("Hello, Python!")
You can then run the file through your Python installation.
A common command is:
python hello.py
Depending on your operating system and Python setup, the command may instead be:
python3 hello.py
The important idea is simple:
Interactive mode is excellent for quick experiments. Python files are better for programs that you want to save, reuse, edit and share.
Interactive Python vs Python Files
| Interactive Mode | Python File |
|---|---|
| Good for quick experiments | Good for complete programs |
| Results appear immediately | Code can be saved |
| Useful for learning | Useful for projects |
| Usually temporary | Can be reused and shared |
Python IDEs and Code Editors
You do not have to write Python programs directly inside a terminal. Most programmers use a code editor or an Integrated Development Environment, commonly called an IDE.
What Is a Code Editor?
A code editor is a program designed for writing and editing source code.
A good code editor can make programming easier by providing features such as:
- Syntax highlighting.
- Code completion.
- File management.
- Search and replace.
- Error highlighting.
- Extensions and plugins.
What Is an IDE?
An IDE combines several programming tools into one development environment.
Depending on the IDE, this may include a code editor, debugger, project management tools, terminal integration and other development features.
Examples of Python Development Tools
- Python IDLE
- Visual Studio Code
- PyCharm
- JupyterLab
- Other Python-compatible editors and IDEs
You do not need the most complicated development environment to learn Python.
In fact, beginners should focus more on understanding Python than spending too much time changing editors.
Pick one development environment, learn how to create and run a Python file, and start writing programs. You can explore more advanced tools as your projects become more demanding.
Your First Python Program
You are now ready to write your first Python program.
One of the simplest things a Python program can do is display information on the screen.
Python provides the print() function for this.
Your First Line of Python
print("Hello, Python!")
What Does This Code Mean?
Let's break it down.
-
printis the name of the function. -
( )tells Python that we are calling the function. -
"Hello, Python!"is a string of text.
Hello, Python!
Try Changing the Message
Programming becomes easier when you experiment. Change the text inside the quotation marks.
print("I am learning Python.")
I am learning Python.
Try another one:
print("Welcome to Gabbywall Learn!")
This may look extremely simple, and it is. But the important thing is that you have just written a real Python instruction.
Printing More Than One Thing
You can use multiple values inside print().
print("My name is Olivia")
print("I am learning Python")
print("Python is interesting")
My name is Olivia I am learning Python Python is interesting
A beginner might look at print() and think,
"This is too easy." But programming is built from simple
instructions combined together. Understanding these small
building blocks is what eventually allows you to create
large applications.
Python Syntax
Syntax refers to the rules that determine how Python code should be written.
Just as human languages have grammar rules, programming languages have syntax rules.
If you write Python in a way that does not follow its syntax, Python may produce an error instead of executing the program.
Python Is Sensitive to Structure
Python uses indentation as an important part of its syntax. This becomes especially important when you begin learning conditions, loops and functions.
For example:
if 10 > 5:
print("10 is greater than 5")
The indented line belongs to the if statement.
The colon after the condition indicates that a block of code follows, and the indentation identifies the statements belonging to that block.
Indentation Matters
Python uses indentation to organize blocks of code. This is one of the characteristics that makes Python code visually clean, but it also means indentation mistakes can cause errors or change how your program behaves.
A common convention is to use four spaces for each indentation level.
if age >= 18:
print("You are an adult")
Python Is Case-Sensitive
Python distinguishes between uppercase and lowercase letters.
For example:
name = "John"
Name = "Mary"
name and Name are different names in
Python.
Python is case-sensitive. Pay attention to uppercase and lowercase letters when writing variables, functions, keywords and other identifiers.
Python Uses Colons in Certain Structures
You will frequently see a colon at the end of statements that introduce a block of code.
For example:
if score >= 50:
print("Pass")
Later, you will see this pattern with conditions, loops, functions, classes and other Python structures.
Python Uses Parentheses for Function Calls
When calling a function, parentheses are normally used.
print("Hello")
The parentheses contain the information being passed to the function.
Strings Need Quotation Marks
When you want Python to treat something as text, you normally place the text inside quotation marks.
print("Hello")
Single and double quotation marks can both be used for ordinary strings.
print("Hello")
print('Hello')
Both represent text strings.
Whitespace
Python generally allows spaces around operators, and readable spacing is encouraged.
total = 10 + 20
Writing readable code is an important programming habit. Your code should not only work; another person should be able to understand it.
↑ Back to Python ContentsPython Comments
Comments are notes written inside your source code for humans. Python does not execute ordinary comments as program instructions.
Comments are useful for explaining what a section of code does, leaving reminders and making programs easier to understand.
Creating a Comment
A Python comment begins with the hash symbol:
# This is a comment
Python ignores the comment when executing the program.
The official Python documentation also describes comments as
beginning with the # character and extending to the
end of the line. :contentReference[oaicite:4]{index=4}
Commenting Above Your Code
You can place a comment above a line to explain what the code does.
# Display a welcome message
print("Welcome to Python")
Commenting Beside Your Code
You can also place a comment after a line of code.
age = 27 # Store the user's age
Why Are Comments Useful?
Imagine you write a program today and return to it six months later.
You might understand what you were doing today, but after months of working on other projects, some parts of the program may no longer be obvious.
Good comments can help you understand your own decisions later.
Comments can also help other developers understand unfamiliar code.
Comments Should Add Meaning
You do not need to comment every single line of code.
For example, this comment does not add much value:
age = 27 # Set age to 27
The code is already obvious.
A useful comment explains something that may not be immediately obvious.
# Use the user's birth year to estimate their current age
age = current_year - birth_year
Commenting Out Code
During development, programmers sometimes temporarily disable a line of code by turning it into a comment.
# print("This line is temporarily disabled")
print("This line will run")
This can be useful while testing a program.
Comments are primarily for humans. They should help explain the code rather than become a substitute for writing clear code.
Common Beginner Mistakes
Making mistakes is a normal part of learning programming. The goal is not to avoid every error. The goal is to learn how to understand and fix errors.
1. Forgetting Quotation Marks
If you want to print text, make sure the text is represented as a string.
print("Hello")
A beginner might accidentally write:
print(Hello)
Python does not interpret Hello as ordinary text in
this situation.
2. Mixing Up Uppercase and Lowercase
Remember that Python is case-sensitive.
name = "Olivia"
print(name)
This is different from:
name = "Olivia"
print(Name)
3. Incorrect Indentation
When working with blocks of code, make sure the indentation is consistent.
if age >= 18:
print("Adult")
4. Thinking Errors Mean You Are Bad at Programming
This is perhaps the most damaging beginner mistake.
Programming involves problem solving. Even experienced developers encounter errors, unexpected behavior and bugs.
When Python gives you an error, treat it as information: something about your program needs attention.
Learning to read error messages will become one of your most valuable programming skills.
↑ Back to Python ContentsPractice: Getting Started With Python
Don't just read this section. Open your Python environment and try these exercises yourself.
- Write a program that prints your name.
- Write a program that prints three things about yourself.
- Print the sentence: I am learning Python.
- Create a comment explaining what your program does.
- Write a program that prints a simple welcome message for someone visiting Gabbywall.
- Experiment with both single and double quotation marks.
-
Open Python's interactive interpreter and calculate
25 + 17.
Create a Python program that prints your name, your favourite subject and one reason you are learning Python.
Quick Quiz: Getting Started
1. What is the Python interpreter used for?
2. Which symbol starts a Python comment?
3. Which function can be used to display information?
4. Is Python case-sensitive?
5. What is the usual file extension for Python programs?
Getting Started: Summary
You have now learned the basic setup and concepts needed to begin working with Python.
| Concept | What It Means |
|---|---|
| Python Interpreter | The program that executes Python code. |
| Interactive Mode | A way to enter Python commands and see results immediately. |
| Python Script | A Python program saved in a file, normally with a .py extension. |
| IDE | A development environment containing tools that help you write and work with code. |
| Syntax | The rules governing how Python code is written. |
| Indentation | Whitespace used to organize blocks of Python code. |
| Comment | A note in source code that Python does not execute as ordinary program instructions. |
| print() | A built-in function commonly used to display information. |
At this point, you know how Python is installed, how Python code can be executed, how to create a basic Python program, and some of the fundamental syntax rules.
Next, we begin one of the most important concepts in programming: variables.
Next: Python Variables
Learn how Python stores and works with information using variables.
Continue to Python Variables →Python Variables
Variables are one of the most important ideas you will learn in Python. Almost every useful Python program will need them.
If you have never programmed before, the word variable may sound complicated. It is actually a very simple idea.
In this lesson, we are going to take our time and understand variables from the ground up. By the end, you should be able to create variables, store information in them, change their values, use them in calculations, accept information from a user, and choose good variable names.
What You Will Learn
- What a variable is
- Why programmers use variables
- How to create a variable
- How assignment works in Python
- How to change a variable's value
- How to print variables
- How to use variables in calculations
- How to store different kinds of values
- How to name variables correctly
- How to use multiple variables
- How variables work with user input
- The difference between local and global variables
- Common mistakes beginners make with variables
What Is a Variable?
A variable is a name that Python uses to refer to a value.
That definition may sound technical, so let's forget the technical language for a moment.
Imagine that you have several boxes in your room. You put a label on each box so that you know what is inside.
Think About It Like This
You could have a box labelled:
- Name
- Age
- Country
Inside those boxes you could have:
- Name → Olivia
- Age → 27
- Country → Nigeria
Programming variables work in a similar way. The variable name gives us a convenient way to refer to information stored by our program.
In Python, we could write:
name = "Olivia"
age = 27
country = "Nigeria"
Here we have created three variables:
nameagecountry
Each variable refers to a different value.
Why Do We Use Variables?
You might be wondering:
Sometimes you can. But real programs usually need to work with information that changes.
Imagine you are creating a program that calculates the total cost of fuel for a trip.
You might have:
fuel_price = 950
litres = 48.93
You can then calculate the total:
total_cost = fuel_price * litres
print(total_cost)
Instead of repeatedly writing 950 and
48.93, we give those values meaningful names.
This makes the program easier to understand and easier to change later.
Without Variables
print(950 * 48.93)
This works, but another programmer looking at it has to
figure out what 950 and 48.93
represent.
With Variables
fuel_price = 950
litres = 48.93
total_cost = fuel_price * litres
print(total_cost)
Now the code explains itself much better.
Creating Variables
Creating a variable in Python is very simple.
You give the variable a name, type the equals sign
=, and then provide the value.
name = "Olivia"
You can read this informally as:
You can create a number variable:
age = 27
You can create a decimal number:
price = 1500.50
And you can store a Boolean value:
is_student = True
We will study these different types of values in much more detail in the next major section, Python Data Types.
Assigning Values to Variables
One of the most important things to understand about Python
variables is the meaning of the equals sign =.
In mathematics, you might see:
x = 10
In programming, we normally describe this as assignment.
The value on the right is assigned to the name on the left.
Python evaluates the right side:
10.
Python associates that value with
x.
You can now use x elsewhere in
your program.
x = 10
print(x)
10
Python's documentation describes assignment as binding a name to a value. :contentReference[oaicite:1]{index=1}
Important: = Does Not Mean "Is Equal To"
At this stage, think of = as
"assign this value".
Python uses == when we want to compare
whether two things are equal. We will learn that later
in the Operators and Conditions sections.
Printing Variables
Once you create a variable, you can display its value using
the print() function.
name = "Olivia"
print(name)
Olivia
You can also print several variables:
name = "Olivia"
age = 27
country = "Nigeria"
print(name)
print(age)
print(country)
Olivia 27 Nigeria
Notice something important here:
print(name) does not print the word
name. It prints the value stored under
that variable.
Changing the Value of a Variable
Variables are called variables because the value associated with a name can change during a program.
For example:
age = 27
print(age)
age = 28
print(age)
27 28
The first time we assign a value:
age = 27
age refers to 27.
Later, we assign another value:
age = 28
Now age refers to 28.
Think of It Like Updating a Label
Imagine a box labelled age. At first, the information inside says 27.
Later, you update the information to 28.
You are not creating a completely different concept. You are updating what your program associates with that name.
Variables Can Store Different Kinds of Values
Python variables can refer to many different kinds of values.
For example:
name = "Olivia"
age = 27
height = 1.68
is_student = True
Here:
| Variable | Value | Example Type |
|---|---|---|
name |
"Olivia" |
String |
age |
27 |
Integer |
height |
1.68 |
Float |
is_student |
True |
Boolean |
We will explore all of these properly in the Data Types section.
Using Variables in Calculations
One of the biggest reasons variables are useful is that they allow us to perform calculations using meaningful names.
For example, imagine a simple shopping calculation.
price = 5000
quantity = 3
total = price * quantity
print(total)
15000
Python calculates:
5000 * 3
and stores the answer in:
total
This becomes especially powerful when the values come from users, files, databases, sensors, or other parts of a program.
Python Variable Names
Choosing a variable name may seem like a small thing, but it is extremely important.
Compare these two programs:
x = 950
y = 48.93
z = x * y
with:
fuel_price = 950
litres = 48.93
total_cost = fuel_price * litres
Both can perform the calculation, but the second version tells us what each value represents.
Rules for Naming Variables
Python has rules that variable names must follow.
Rule 1: A variable name can contain letters
name = "Olivia"
country = "Nigeria"
Rule 2: A variable name can contain numbers
student1 = "Ada"
student2 = "David"
However, a variable name cannot begin with a number.
1student = "Ada"
The example above is invalid.
Rule 3: Underscores are allowed
first_name = "Olivia"
last_name = "Ezeani"
fuel_price = 950
Rule 4: Spaces are not allowed
This is invalid:
first name = "Olivia"
Use an underscore instead:
first_name = "Olivia"
Rule 5: Variable names are case-sensitive
This means that Python treats these as different names:
name = "Olivia"
Name = "David"
NAME = "Sarah"
They are three different variable names.
Be Careful With Capital Letters
A common beginner mistake is creating:
name = "Olivia"
print(Name)
Python will not assume that Name means
name.
Good and Bad Variable Names
Python allows many names that technically work, but "working" does not always mean "good programming".
| Variable | Good? | Why? |
|---|---|---|
name |
Good | Simple and clear |
student_name |
Good | Clearly describes the value |
fuel_price |
Good | Describes exactly what it stores |
x |
Sometimes | Okay for short mathematical examples |
a_really_long_name_that_is_hard_to_read |
Not ideal | Too long |
thing |
Not ideal | Does not explain what it contains |
Use Descriptive Names
Instead of:
x = 350000
you could write:
salary = 350000
Now anyone reading the code immediately has an idea what
350000 represents.
Python Naming Style: snake_case
Python programmers commonly use a style called snake_case for variable names.
Instead of writing:
studentname = "Olivia"
you can write:
student_name = "Olivia"
For multiple words:
first_name = "Olivia"
last_name = "Ezeani"
phone_number = "08000000000"
total_trip_cost = 45000
The underscore makes the words easier to read.
Assigning Values
We have already seen simple assignment:
name = "Olivia"
But the right side of the equals sign can also contain an expression.
price = 5000
quantity = 4
total = price * quantity
Python first works out:
5000 * 4
and then assigns the result to total.
print(total)
20000
Reassigning Variables
You can assign a new value to an existing variable.
score = 50
print(score)
score = 80
print(score)
50 80
The variable did not become a completely new variable. We simply assigned a new value to the existing name.
Python's documentation describes this as rebinding a name to a value. :contentReference[oaicite:2]{index=2}
Updating a Variable's Value
Suppose you have:
score = 10
score = score + 5
print(score)
15
Python also provides a shorter way to write this:
score = 10
score += 5
print(score)
15
You will see operators such as +=,
-=, and *= frequently in real
Python programs. Python's reference documentation defines
these as augmented assignment operations. :contentReference[oaicite:3]{index=3}
For now, simply remember:
x += 5means increasexby 5.x -= 5means decreasexby 5.x *= 5means multiplyxby 5.
Multiple Variables
You can create several variables one after another:
name = "Olivia"
age = 27
country = "Nigeria"
Python also allows multiple assignment in a single line.
x, y, z = 10, 20, 30
print(x)
print(y)
print(z)
10 20 30
The values are matched from left to right:
x = 10
y = 20
z = 30
The shorter version is:
x, y, z = 10, 20, 30
Python supports this type of multiple assignment directly. :contentReference[oaicite:4]{index=4}
Giving Multiple Variables the Same Value
You can also give several variables the same value.
x = y = z = 0
Now:
print(x)
print(y)
print(z)
0 0 0
This can be useful when several values need the same starting value.
Variables and User Input
Variables become even more useful when your program receives information from a user.
Remember the input() function from earlier?
We can store the user's response in a variable.
name = input("What is your name? ")
print(name)
When the program runs, the user might type:
Olivia
The response is stored in the variable:
name
You can then use that variable later:
name = input("What is your name? ")
print("Hello", name)
If the user enters Olivia, the program displays:
Hello Olivia
A Very Important Point
By default, input() gives your program
the user's response as text.
We will learn how to convert that text into numbers
using int() and float() in
the Data Types section.
Checking the Type of a Variable
Sometimes you may want to know what kind of value a variable contains.
Python provides the type() function for this.
name = "Olivia"
print(type(name))
You might see:
<class 'str'>
For a number:
age = 27
print(type(age))
<class 'int'>
Do not worry if str and int look
unfamiliar right now. We will study data types properly
in the next section.
Local and Global Variables
Now we are going to introduce an idea that may feel a little more advanced.
It is called variable scope.
Scope basically means:
There are two terms you will hear often:
- Local variable
- Global variable
Global Variable
A variable created outside a function can be accessible from code within that module, including from functions under normal name-resolution rules.
name = "Olivia"
def say_hello():
print(name)
say_hello()
Olivia
Here, name was created outside the function.
Local Variable
A variable created inside a function is normally local to that function.
def greet():
message = "Hello"
print(message)
greet()
The variable message belongs to the function's
local scope.
Beginner Rule
Do not worry about using the global
keyword yet.
For beginner programs, it is usually better to pass information into functions and return results rather than relying heavily on global variables.
The global Keyword
Python also provides the global keyword.
It allows a function to indicate that an assignment should
refer to a global name rather than creating a new local
binding.
For example:
score = 10
def increase_score():
global score
score = score + 5
increase_score()
print(score)
15
This is useful to understand, but you do not need to start writing programs this way immediately.
As your programs become larger, relying on many global variables can make your code harder to understand.
What About Constants?
Sometimes a program contains a value that we do not intend to change.
For example:
PI = 3.14159
Python does not have a special constant variable mechanism that prevents reassignment in ordinary Python code. Instead, programmers commonly use uppercase names to signal that a value is intended to remain unchanged.
MAX_SCORE = 100
TAX_RATE = 0.075
Think of uppercase names here as a programmer convention.
Common Beginner Mistakes With Variables
Mistake 1: Forgetting quotation marks around text
This is wrong:
name = Olivia
Python will interpret Olivia as another name
rather than text.
Write:
name = "Olivia"
Mistake 2: Starting a variable name with a number
2name = "Olivia"
This is invalid.
Instead:
name2 = "Olivia"
Mistake 3: Using spaces
first name = "Olivia"
Use:
first_name = "Olivia"
Mistake 4: Mixing uppercase and lowercase accidentally
name = "Olivia"
print(Name)
Remember:
name and Name are different.
Mistake 5: Using a variable before creating it
print(age)
If age has not been defined before this point,
Python will raise a NameError.
The official Python tutorial demonstrates this behavior
when an undefined variable is referenced. :contentReference[oaicite:5]{index=5}
Create the variable first:
age = 27
print(age)
Mistake 6: Confusing = and ==
Assignment:
age = 27
Comparison:
age == 27
We will study comparison operators later.
Real-World Examples of Variables
Let's make variables feel less abstract by connecting them to programs you might actually build.
Example 1: Student Information
student_name = "Olivia"
age = 27
course = "Python"
print(student_name)
print(age)
print(course)
Example 2: Currency Converter
dollars = 100
exchange_rate = 1500
naira = dollars * exchange_rate
print(naira)
Example 3: Trip Cost
distance = 500
fuel_efficiency = 12
fuel_price = 950
litres_needed = distance / fuel_efficiency
fuel_cost = litres_needed * fuel_price
print(fuel_cost)
Notice how much easier this is to understand because the variables describe what the numbers represent.
Example 4: Agricultural Sensor Project
Imagine that one day you build an agricultural monitoring system that receives information from sensors.
temperature = 31.5
soil_moisture = 42
crop_name = "Maize"
print(temperature)
print(soil_moisture)
print(crop_name)
This is one reason variables are so important in programming: programs need names for the information they are working with.
Practice: Create Your First Variables
Do not just read this section. Open your Python editor and type the examples yourself.
Create variables for:
- Your name
- Your age
- Your country
- Your favorite programming language
- Your favorite number
Then print all of them.
name = "Your Name"
age = 27
country = "Nigeria"
favorite_language = "Python"
favorite_number = 7
print(name)
print(age)
print(country)
print(favorite_language)
print(favorite_number)
Practice: Build a Simple Calculation
Imagine you bought three items.
- Item price: ₦2,500
- Quantity: 4
Create variables for the price and quantity. Then calculate the total.
Your program should produce:
10000
Try solving it yourself before looking at the example below.
Show Example Solution
price = 2500
quantity = 4
total = price * quantity
print(total)
Practice: Change a Variable
Create a variable called score.
Give it the value 50.
Print it.
Then change it to 75 and print it again.
Your output should be:
50 75
Mini Project: Personal Introduction
Let's combine what you have learned.
Create variables for:
- Name
- Age
- Country
- Favorite programming language
Then use print() to display an introduction.
For example, your program could produce something similar to:
My name is Olivia. I am 27 years old. I am from Nigeria. I am learning Python.
Try to build it yourself before looking at a possible solution.
Show Example Solution
name = "Olivia"
age = 27
country = "Nigeria"
language = "Python"
print("My name is", name)
print("I am", age, "years old.")
print("I am from", country)
print("I am learning", language)
Quick Quiz: Python Variables
Test yourself before moving to the next section.
1. What is a variable?
2. What does the = sign normally do in an assignment?
3. Which is a valid variable name?
4. Are Python variable names case-sensitive?
5. What will this print?
age = 27
age = 28
print(age)
6. What does input() allow a program to do?
Python Variables: Summary
You have now learned one of the foundations of Python programming.
| Concept | Example | Meaning |
|---|---|---|
| Creating a variable | name = "Olivia" |
Assign a value to a name |
| Number variable | age = 27 |
Store a number |
| Changing a value | age = 28 |
Reassign the variable |
| Printing | print(age) |
Display the value |
| Calculation | total = price * quantity |
Use variables in expressions |
| User input | name = input() |
Store user input |
| Check type | type(age) |
Find the value's type |
| Multiple assignment | x, y = 10, 20 |
Assign multiple values |
If You Remember Only Five Things
- A variable is a name used to refer to a value.
-
Use
=to assign a value. - Variable names should be clear and descriptive.
- Python variable names are case-sensitive.
- Variables allow programs to store, reuse, and change information.
Python Data Types
Now that you understand variables, it is time to learn something very important: the kind of information a variable contains.
This is called a data type.
If the word "type" sounds confusing, don't worry. We are going to explain it using simple, everyday examples before looking at the technical definition.
By the end of this lesson, you should understand the
difference between text, whole numbers, decimal numbers,
Boolean values, complex numbers, and the special
None value.
What You Will Learn
- What a data type is
- Why data types matter
- How to identify a value's type
- Strings
- Integers
- Floats
- Complex numbers
- Booleans
- The special
Nonevalue - How Python treats different types
- Type conversion
- How to convert strings to numbers
- Common beginner mistakes with data types
What Is a Data Type?
A data type tells Python what kind of value it is dealing with.
Think about information in the real world.
You can have:
- A person's name
- A person's age
- A temperature
- Whether someone is logged in
- A location
- A phone number
Although all of these are pieces of information, they are not necessarily the same kind of information.
Think About a School
Imagine a teacher has a record containing:
- Name → Olivia
- Age → 27
- Average score → 82.5
- Passed → True
The information is different in nature.
Olivia is text.
27 is a whole number.
82.5 is a decimal number.
True represents a yes/no or true/false condition.
Python uses different data types to represent these different kinds of values.
Why Do Data Types Matter?
This is an important question.
Why doesn't Python simply treat everything as "information"?
Because Python needs to know what operations make sense for a particular value.
For example, adding two numbers makes sense:
10 + 5
The result is:
15
But text behaves differently.
"Hello" + "World"
Python joins the two strings:
HelloWorld
So the same + symbol can behave differently
depending on the types of values involved.
Common Python Data Types
Python has many built-in types. For beginners, the most important ones to understand first are:
| Type | Example | Used For |
|---|---|---|
str |
"Hello" |
Text |
int |
27 |
Whole numbers |
float |
27.5 |
Decimal numbers |
complex |
3 + 4j |
Complex numbers |
bool |
True |
True/false values |
NoneType |
None |
Absence of a value |
Python's official documentation lists these among its built-in types. :contentReference[oaicite:1]{index=1}
How to Find the Type of a Value
Python provides a built-in function called
type().
You can give type() a value, and Python will
tell you what type it is.
print(type("Hello"))
The result is:
<class 'str'>
This tells us that "Hello" is a string.
Try a whole number:
print(type(27))
<class 'int'>
Try a decimal:
print(type(27.5))
<class 'float'>
The type() built-in is the normal way to inspect
the type of an object in Python. :contentReference[oaicite:2]{index=2}
Strings
A string is text.
If you are storing words, sentences, names, addresses, messages, or other textual information, you will usually use a string.
Python's type name for strings is:
str
Examples:
name = "Olivia"
country = "Nigeria"
message = "Welcome to Python"
Strings are usually written inside quotation marks.
You can use single quotes:
name = 'Olivia'
Or double quotes:
name = "Olivia"
Both create strings.
Why Do We Need Quotation Marks?
Compare:
name = "Olivia"
with:
name = Olivia
In the first example, Python understands
Olivia as text.
In the second example, Python assumes
Olivia is the name of another variable.
Python strings are sequences of Unicode characters and are immutable, meaning the existing string itself cannot be changed in place. :contentReference[oaicite:3]{index=3}
String Examples
Strings can contain single words:
name = "Olivia"
Multiple words:
full_name = "Olivia Ezeani"
Sentences:
message = "Welcome to Gabbywall."
Numbers can also appear inside a string.
phone = "08012345678"
Notice that the number above is inside quotation marks. Therefore Python treats it as text, not as a number.
"27" and 27 are not the same
type.
The first is a string. The second is an integer.
Integers
An integer is a whole number.
Python's type name for integers is:
int
Examples:
age = 27
students = 50
temperature = 30
Integers can also be negative:
temperature = -5
And zero is also an integer:
score = 0
Python integers can represent whole numbers with arbitrary precision, subject to available memory. :contentReference[oaicite:4]{index=4}
Working With Integers
You can perform mathematical operations with integers.
a = 10
b = 5
print(a + b)
print(a - b)
print(a * b)
print(a / b)
15 5 50 2.0
Notice something interesting:
Even though both a and b are
integers, regular division with / produces
a floating-point result.
Floats
A float is a floating-point number.
For a beginner, the easiest way to think about a float is:
Examples:
price = 1500.50
temperature = 31.5
distance = 48.93
You can check:
print(type(31.5))
<class 'float'>
Working With Floats
Floats are especially useful when working with measurements, prices, percentages, distances, temperatures, and other values that may contain decimals.
distance = 48.93
fuel_price = 950
cost = distance * fuel_price
print(cost)
46483.5
The result is also a floating-point number because it contains a decimal part.
Integer vs Float
This distinction is important.
| Value | Type |
|---|---|
10 |
int |
10.0 |
float |
-5 |
int |
-5.5 |
float |
0 |
int |
0.0 |
float |
Notice that 10 and 10.0 represent
numerically equivalent values, but they have different
Python types.
Complex Numbers
Python also supports complex numbers.
If you have not studied complex numbers in mathematics yet, do not panic.
You do not need to master them to continue learning basic Python.
A Python complex number can look like:
z = 3 + 4j
Here:
3is the real part.4jrepresents the imaginary part.
You can check its type:
print(type(z))
<class 'complex'>
Python's numeric type system includes integers, floating-point numbers, and complex numbers. :contentReference[oaicite:5]{index=5}
Complex numbers are important in areas such as engineering, physics, signal processing, and mathematics, but you can continue with this course without going deeply into them right now.
Booleans
A Boolean represents one of two truth values:
TrueFalse
Python's type name for Boolean values is:
bool
Examples:
is_logged_in = True
is_raining = False
has_permission = True
Think of Boolean values as answers to questions that can be answered with yes or no.
Real-World Example
Imagine an application asking:
- Is the user logged in?
- Is the payment complete?
- Is the vehicle available?
- Is the soil dry?
Each question could have a Boolean answer:
True or False.
Python's bool type has exactly two Boolean
values: True and False. :contentReference[oaicite:6]{index=6}
True and False Must Be Capitalized
Python uses:
True
False
The first letter is capitalized.
These are not the same:
True
true
Python recognizes True as the Boolean value.
Lowercase true is not the Python Boolean
constant.
Always write:
True and False.
None
Now we come to a special Python value:
None.
This can be confusing at first.
The easiest way to think about None is:
For example:
result = None
print(result)
None
You might use None when a value does not exist
yet or when a program needs to represent the absence of a
meaningful value.
Example
middle_name = None
This could mean that the person currently has no middle name recorded in the program.
Python has a single null object called None,
whose type is NoneType. :contentReference[oaicite:7]{index=7}
Is None the Same as False?
No.
They are different values and different concepts.
answer = None
completed = False
The first says:
The second says:
Python does consider None false in a Boolean
context, but that does not make None and
False the same value. :contentReference[oaicite:8]{index=8}
Type Conversion
Sometimes you have one type of value but need another type.
This is called type conversion.
For example, imagine a user enters their age:
age = input("Enter your age: ")
The value returned by input() is text.
If the user enters:
27
Python receives that input as a string.
We can convert it into an integer using
int().
age = int(input("Enter your age: "))
print(age)
Now age is an integer, assuming the user entered
something that can be interpreted as an integer.
Python provides constructors such as int(),
float(), and complex() for creating
numeric values of those types. :contentReference[oaicite:9]{index=9}
Converting to an Integer
Use int() when you need an integer.
number = int("25")
print(number)
print(type(number))
25 <class 'int'>
Before conversion:
"25"
is a string.
After:
int("25")
the result is an integer.
Converting to a Float
Use float() when you need a floating-point number.
price = float("1500.50")
print(price)
print(type(price))
1500.5 <class 'float'>
This is particularly useful when receiving decimal values from a user.
distance = float(input("Enter distance: "))
Converting to a String
You can use str() to convert a value into text.
age = 27
age_text = str(age)
print(age_text)
print(type(age_text))
27 <class 'str'>
This becomes useful when you need to combine a value with text in situations where explicit conversion is required.
Converting Values to Boolean
Python also has:
bool()
It converts a value into a Boolean truth value.
For example:
print(bool(1))
print(bool(0))
True False
Python has rules for determining whether different objects
are considered true or false. For example, zero and
None are considered false. :contentReference[oaicite:10]{index=10}
Don't Memorize Everything Yet
Boolean truth testing becomes much more important when we reach if statements and while loops.
For now, understand the basic idea:
bool() asks Python to interpret a value
as true or false.
Very Important: "10" Is Not the Same as 10
This is one of the most common things that confuses beginners.
Look at these two values:
"10"
10
They look almost identical.
But they are different types.
print(type("10"))
print(type(10))
<class 'str'> <class 'int'>
This difference becomes very important with calculations.
For example:
number = "10"
print(number + "5")
105
Why?
Because Python is joining two strings.
But:
number = 10
print(number + 5)
15
Here Python is adding two numbers.
Why Input Conversion Is Important
Imagine you want a program to ask someone for two numbers.
A beginner might write:
first = input("Enter first number: ")
second = input("Enter second number: ")
print(first + second)
If the user enters:
10 5
the result may be:
105
That is because the values received from
input() are strings.
If you want mathematical addition, convert them:
first = int(input("Enter first number: "))
second = int(input("Enter second number: "))
print(first + second)
Now:
15
User input is text by default, so convert it when your program needs a number.
Important Conversion Functions
| Function | Purpose | Example |
|---|---|---|
int() |
Convert to integer | int("25") |
float() |
Convert to float | float("25.5") |
str() |
Convert to string | str(25) |
bool() |
Convert to Boolean | bool(1) |
Common Beginner Mistakes With Data Types
Mistake 1: Treating a string like a number
age = "27"
print(age + 5)
This causes a type error because Python cannot directly add a string and an integer this way.
Convert it first:
age = "27"
age = int(age)
print(age + 5)
Mistake 2: Forgetting quotation marks
name = Olivia
If Olivia is meant to be text, use quotes:
name = "Olivia"
Mistake 3: Assuming 10 and "10" are the same
number1 = 10
number2 = "10"
print(type(number1))
print(type(number2))
They have different types.
Mistake 4: Writing true instead of True
is_active = true
Use:
is_active = True
Mistake 5: Trying to convert invalid text to a number
age = int("hello")
Python cannot interpret "hello" as an integer,
so this will raise an error.
Type conversion only works when the original value can be converted appropriately.
Real-World Examples
Let's bring everything together using situations you may actually encounter when building applications.
Example 1: Student Record
student_name = "Olivia"
age = 27
average_score = 82.5
passed = True
Here we have:
student_name→ stringage→ integeraverage_score→ floatpassed→ Boolean
Example 2: Trip Planner
destination = "Abuja"
distance = 760.5
fuel_price = 950
trip_confirmed = True
Example 3: Agricultural Monitoring
crop = "Maize"
temperature = 31.7
soil_moisture = 42
sensor_active = True
As you move into more advanced programming, your programs will constantly be working with different types of data.
Practice: Identify the Data Types
Look at each value and identify its type before checking the answers.
"Python"
25
25.5
True
None
3 + 4j
Show Answers
"Python"→str25→int25.5→floatTrue→boolNone→NoneType3 + 4j→complex
Practice: Convert the Values
Convert the following values into the requested types.
-
Convert
"50"into an integer. -
Convert
"25.5"into a float. -
Convert
100into a string.
Try them yourself first.
Show Example Solution
number = int("50")
price = float("25.5")
text = str(100)
Practice: Build a Number Calculator
Write a program that asks the user for two numbers and adds them together.
Remember:
input() gives you text, so you need to convert
the input before performing mathematical addition.
Try to write the program yourself.
Show Example Solution
first = int(input("Enter first number: "))
second = int(input("Enter second number: "))
total = first + second
print(total)
Mini Project: Student Score Calculator
Let's use variables and data types together.
Ask the user for three scores:
- Biology
- Chemistry
- Physics
Convert the input into integers and calculate the total.
Your program should contain variables similar to:
biology = int(input("Biology score: "))
chemistry = int(input("Chemistry score: "))
physics = int(input("Physics score: "))
total = biology + chemistry + physics
print("Total:", total)
Don't simply copy this.
First try to build it yourself.
Quick Quiz: Python Data Types
Test your understanding before continuing.
1. What is a data type?
2. What type is "Hello"?
3. What type is 25?
4. What type is 25.5?
5. Which two values are Boolean values?
6. What does None generally represent?
7. What is the type of "27"?
8. Which function converts text into an integer?
Python Data Types: Summary
You have now learned that Python values can belong to different types, and that the type affects how Python handles the value.
| Type | Example | Simple Meaning |
|---|---|---|
str |
"Olivia" |
Text |
int |
27 |
Whole number |
float |
27.5 |
Decimal number |
complex |
3 + 4j |
Complex number |
bool |
True |
True/false value |
NoneType |
None |
Absence of a value |
If You Remember Only Seven Things
- A data type describes what kind of value you have.
-
stris used for text. -
intis used for whole numbers. -
floatis used for floating-point numbers. -
boolrepresentsTrueorFalse. -
Nonerepresents the absence of a value. -
Functions such as
int(),float(),str(), andbool()can be used for type conversion.
Python Operators
You have learned about variables and data types. Now it is time to make those values useful.
This is where operators come in.
Operators are symbols or keywords that tell Python to perform an operation.
If that sounds complicated, think about mathematics.
You already know symbols such as:
+
-
*
/
You use them to add, subtract, multiply and divide.
Python uses these same ideas, but it has many more operators that allow your programs to calculate, compare, test and make decisions.
What You Will Learn
- What operators are
- Arithmetic operators
- Assignment operators
- Comparison operators
- Logical operators
- Identity operators
- Membership operators
- The difference between
=and== - How operators work with variables
- How to combine operators
- Operator precedence
- Common beginner mistakes
What Are Operators?
An operator is something that tells Python to perform an operation on one or more values.
For example:
10 + 5
Here:
10is a value.5is a value.+is the operator.
Python uses the + operator to add the two
values together.
15
The values are what Python works with. The operator tells Python what to do with them.
Types of Operators in Python
Python has several categories of operators.
| Category | Main Purpose |
|---|---|
| Arithmetic | Perform mathematical calculations |
| Assignment | Assign or update values |
| Comparison | Compare values |
| Logical | Combine or reverse conditions |
| Identity | Check whether two references are the same object |
| Membership | Check whether something exists inside a collection |
We will take each category slowly.
Arithmetic Operators
Arithmetic operators are used for mathematical calculations.
These are probably the easiest operators to understand because you have already encountered most of them in mathematics.
| Operator | Name | Example | Result |
|---|---|---|---|
+ |
Addition | 10 + 3 |
13 |
- |
Subtraction | 10 - 3 |
7 |
* |
Multiplication | 10 * 3 |
30 |
/ |
Division | 10 / 3 |
3.333... |
// |
Floor division | 10 // 3 |
3 |
% |
Modulus | 10 % 3 |
1 |
** |
Exponentiation | 10 ** 2 |
100 |
Python's numeric types support operations such as addition, subtraction, multiplication, division, floor division, remainder and exponentiation. :contentReference[oaicite:1]{index=1}
The Addition Operator: +
The + operator adds values together.
first = 10
second = 5
result = first + second
print(result)
15
You can also add more than two values:
total = 10 + 20 + 30
print(total)
60
Adding Strings
The + operator can also join strings.
first_name = "Olivia"
last_name = "Ezeani"
full_name = first_name + " " + last_name
print(full_name)
Olivia Ezeani
The Subtraction Operator: -
The - operator subtracts one value from another.
money = 5000
spent = 1500
remaining = money - spent
print(remaining)
3500
This is useful in many real-world programs.
For example:
- Calculating remaining money
- Calculating remaining inventory
- Calculating remaining fuel
- Calculating age differences
- Calculating available seats
The Multiplication Operator: *
The * operator multiplies values.
price = 1500
quantity = 4
total = price * quantity
print(total)
6000
This is useful for calculating things such as:
- Total product cost
- Distance
- Area
- Salary calculations
- Fuel cost
The Division Operator: /
The / operator performs division.
total = 20
people = 4
result = total / people
print(result)
5.0
Notice that the result is 5.0, not
5.
Regular division with / produces a
floating-point result.
Floor Division: //
Floor division uses two forward slashes:
//
It performs division and returns the floor of the result.
result = 10 // 3
print(result)
3
Compare:
print(10 / 3)
print(10 // 3)
3.3333333333333335 3
Simple Way to Remember
/ asks:
"What is the exact division result?"
// asks:
"What is the floor of the division result?"
The Modulus Operator: %
The % operator gives you the remainder after
division.
For example:
result = 10 % 3
print(result)
1
Why?
Because:
10 ÷ 3 = 3 remainder 1
Therefore:
10 % 3 = 1
Why Is This Useful?
The modulus operator is extremely useful when checking whether a number is even or odd.
number = 10
print(number % 2)
0
If a number divided by 2 leaves a remainder of zero, it is even.
For example:
10 % 2
12 % 2
7 % 2
0 0 1
This idea becomes very useful when we learn conditions and loops.
Exponentiation: **
The ** operator is used for powers.
For example:
result = 2 ** 3
print(result)
8
This means:
2 × 2 × 2 = 8
Another example:
print(5 ** 2)
25
Assignment Operators
Assignment operators are used to assign values to variables.
You have already seen:
age = 27
The = symbol means:
It does not mean "is equal to" in the mathematical sense.
Understanding the = Sign
Consider:
age = 27
Read it as:
Python evaluates the right-hand side and then assigns the result to the name on the left.
For example:
price = 100
quantity = 3
total = price * quantity
Python calculates:
100 * 3
and assigns the result to total.
Therefore:
print(total)
300
Compound Assignment Operators
Python also allows you to combine an arithmetic operation with assignment.
For example:
score = 10
score += 5
print(score)
15
This:
score += 5
is a shorter way of writing:
score = score + 5
Other examples include:
score -= 2
score *= 3
score /= 2
score //= 2
score %= 2
score **= 2
| Operator | Meaning |
|---|---|
+= |
Add and assign |
-= |
Subtract and assign |
*= |
Multiply and assign |
/= |
Divide and assign |
//= |
Floor divide and assign |
%= |
Modulus and assign |
**= |
Power and assign |
Comparison Operators
Comparison operators are used when you want Python to compare two values.
They produce a Boolean result:
TrueFalse
Python provides comparison operators such as
<, >, ==,
!=, <= and
>=. :contentReference[oaicite:2]{index=2}
| Operator | Meaning |
|---|---|
== |
Equal to |
!= |
Not equal to |
> |
Greater than |
< |
Less than |
>= |
Greater than or equal to |
<= |
Less than or equal to |
The Equal-To Operator: ==
The == operator checks whether two values
are equal.
age = 27
print(age == 27)
True
But:
age = 27
print(age == 30)
False
= means assignment.
== means comparison.
The Not-Equal Operator: !=
The != operator asks:
age = 27
print(age != 30)
True
Because 27 is not 30.
Greater Than and Less Than
You can ask whether one number is larger or smaller than another.
age = 27
print(age > 18)
print(age < 18)
True False
You can also use:
>=
<=
These include equality.
age = 18
print(age >= 18)
print(age <= 18)
True True
Logical Operators
Logical operators allow you to combine or reverse conditions.
Python has three main Boolean logical operators:
andornot
These become extremely important when we start writing conditions.
The and Operator
and means that multiple conditions must
be true for the combined expression to be true.
Imagine:
You can enter an exam if:
- You registered
- and you paid the fee
In Python:
registered = True
paid = True
print(registered and paid)
True
If either condition is false:
registered = True
paid = False
print(registered and paid)
False
Python evaluates and expressions from left
to right and can stop once the final result is already
determined. :contentReference[oaicite:3]{index=3}
The or Operator
or means that at least one of the conditions
needs to be true for the combined expression to be true.
Imagine a website accepts payment by:
- Card
- or bank transfer
card = False
bank_transfer = True
print(card or bank_transfer)
True
Because at least one condition is true.
The not Operator
not reverses a Boolean truth value.
is_raining = True
print(not is_raining)
False
Because:
not True = False
And:
not False = True
Identity Operators
Identity operators are:
isis not
They check whether two references point to the same object.
This is different from simply asking whether two values are equal.
Python's documentation defines is and
is not as identity comparisons. :contentReference[oaicite:4]{index=4}
The is Operator
The is operator checks object identity.
One of the clearest beginner examples is checking
whether a value is None.
result = None
print(result is None)
True
This is a common and appropriate use of
is.
The is not Operator
is not checks that two references do not
refer to the same object.
result = None
print(result is not None)
False
Use == when you want to compare values.
Use is when you specifically want to
test object identity, commonly with None.
Membership Operators
Membership operators are used to check whether something exists inside another object.
The two membership operators are:
innot in
Python uses these operators for membership tests. :contentReference[oaicite:5]{index=5}
The in Operator
Let's start with a string.
name = "Olivia"
print("O" in name)
True
Python checks whether the character
"O" occurs inside the string.
You can also search for a word:
message = "Welcome to Python"
print("Python" in message)
True
The not in Operator
not in checks whether something does
not exist inside another object.
message = "Welcome to Python"
print("Java" not in message)
True
Because the word "Java" is not present
in the string.
Membership With a List
Membership testing becomes even more useful when we start working with collections such as lists.
You will learn lists properly in a later section, but here is a small preview:
fruits = ["apple", "orange", "banana"]
print("apple" in fruits)
print("mango" in fruits)
True False
Python checks whether each item exists in the collection.
Operator Precedence
Sometimes an expression contains several operators.
For example:
result = 10 + 5 * 2
What should Python calculate first?
Multiplication has higher precedence than addition.
Therefore Python calculates:
5 * 2
first, giving:
10 + 10
and the final result is:
20
Python's operator precedence determines which operations are evaluated first. :contentReference[oaicite:6]{index=6}
Use Parentheses When You Want to Be Clear
You can use parentheses to tell Python exactly which calculation should happen first.
result = (10 + 5) * 2
print(result)
30
Without the parentheses:
result = 10 + 5 * 2
print(result)
20
Real-World Example: Trip Fuel Cost
Let's use several concepts together.
Imagine a trip planner needs to calculate fuel cost.
distance = 500
fuel_efficiency = 10
fuel_price = 950
fuel_needed = distance / fuel_efficiency
fuel_cost = fuel_needed * fuel_price
print("Fuel needed:", fuel_needed)
print("Fuel cost:", fuel_cost)
Fuel needed: 50.0 Fuel cost: 47500.0
Notice what happened.
- We stored the distance in a variable.
- We stored fuel efficiency in another variable.
- We divided distance by fuel efficiency.
- We multiplied the fuel needed by the fuel price.
- We displayed the result.
This is what programming starts to look like: taking simple pieces of information and combining them to solve real problems.
Common Beginner Mistakes
Mistake 1: Confusing = and ==
Remember:
age = 27
assigns a value.
While:
age == 27
compares a value.
Mistake 2: Forgetting that input is text
first = input("First number: ")
second = input("Second number: ")
print(first + second)
This joins strings rather than performing numeric addition.
Mistake 3: Using / when you need //
Regular division:
10 / 3
gives a floating-point result.
Floor division:
10 // 3
gives the floor of the division result.
Mistake 4: Confusing % with percentage
In Python, % is the modulus operator.
It calculates the remainder after division.
Mistake 5: Using is when you mean ==
If you want to compare values, normally use:
==
Use is for identity checks, commonly:
value is None
Practice 1: Basic Arithmetic
Without running the code, try to predict the results:
print(20 + 5)
print(20 - 5)
print(20 * 5)
print(20 / 5)
print(20 // 6)
print(20 % 6)
print(2 ** 4)
Show Answers
25 15 100 4.0 3 2 16
Practice 2: Comparisons
What will each expression produce?
age = 27
print(age == 27)
print(age == 30)
print(age != 30)
print(age > 18)
print(age < 18)
print(age >= 27)
print(age <= 20)
Show Answers
True False True True False True False
Practice 3: Logical Operators
Predict the results:
print(True and True)
print(True and False)
print(True or False)
print(False or False)
print(not True)
print(not False)
Show Answers
True False True False False True
Practice 4: Membership
Predict the result:
word = "Python"
print("P" in word)
print("p" in word)
print("Java" in word)
print("Java" not in word)
Show Answers
True False False True
"P" and "p" are different
characters.
Mini Project: Simple Shopping Calculator
Build a small program that calculates the total cost of a product.
Your program should:
- Store the product price.
- Store the quantity.
- Multiply them.
- Display the total.
For example:
price = 2500
quantity = 4
total = price * quantity
print("Total:", total)
Then improve it by allowing the user to enter the price and quantity.
Add a discount variable and calculate the final amount after the discount.
Quick Quiz: Python Operators
Test yourself before moving to the next section.
1. Which operator is used for addition?
2. What does == do?
3. What does % return?
4. What is the result of 10 // 3?
5. Which operator means "not equal to"?
6. Which operator checks whether something exists inside a collection?
7. Which logical operator requires both conditions to be true?
8. What is the difference between = and ==?
Python Operators: Summary
Operators allow your Python programs to perform calculations, comparisons and logical operations.
| Category | Important Operators | Purpose |
|---|---|---|
| Arithmetic |
+ - * / // % **
|
Mathematical operations |
| Assignment |
= += -= *= /=
|
Assign or update values |
| Comparison |
== != > < >= <=
|
Compare values |
| Logical |
and or not
|
Combine or reverse conditions |
| Identity |
is is not
|
Check object identity |
| Membership |
in not in
|
Check membership |
The Most Important Things to Remember
-
=assigns a value. -
==compares values. -
+adds numbers and can join strings. -
%gives the remainder after division. -
andcombines conditions where both need to be true. -
orallows at least one condition to be true. -
notreverses a truth value. -
inchecks membership. -
ischecks object identity.
Python Conditions
In programming, your computer often needs to make decisions. It may need to decide whether a person is old enough to register, whether a student passed an examination, whether there is enough money in an account, or whether a machine should perform a task.
Python allows us to make these decisions using conditions.
What Are Conditions?
A condition is a statement that allows Python to check whether something is true or false.
Think about everyday decisions.
- If it is raining, take an umbrella.
- If you are hungry, eat.
- If your score is 50 or above, you passed.
- If your battery is low, charge your phone.
Programming works in a similar way. We give the computer a condition and tell it what to do depending on the result.
if condition:
do something
The important word here is if.
Conditions in Everyday Life
Imagine you are going to travel.
Before leaving, you check the weather.
Your decision might be:
IF it is raining:
take an umbrella
If it is not raining, you may decide not to take one.
Python allows you to write this type of decision directly into your program.
if raining:
print("Take an umbrella")
This is the basic idea behind conditions.
Conditions and Boolean Values
Remember that Python has two important Boolean values:
- True
- False
Conditions usually produce one of these two values.
print(10 > 5)
Output:
True
Another example:
print(10 < 5)
Output:
False
Python can use these True and False results to decide what your program should do.
Comparison Operators in Conditions
Conditions often use comparison operators.
| Operator | Meaning | Example |
|---|---|---|
| == | Equal to | 5 == 5 |
| != | Not equal to | 5 != 3 |
| > | Greater than | 10 > 5 |
| < | Less than | 3 < 8 |
| >= | Greater than or equal to | 10 >= 10 |
| <= | Less than or equal to | 5 <= 5 |
These operators allow Python to compare values.
if Statements
The if statement is one of the most important tools for making decisions in Python.
It tells Python:
Basic Syntax
if condition:
statement
For example:
age = 20
if age >= 18:
print("You are an adult")
Python checks whether age >= 18 is True.
Because 20 is greater than 18, the condition is True, so Python prints:
You are an adult
Breaking Down an if Statement
age = 20
if age >= 18:
print("You are an adult")
Let's break it down.
-
age = 20creates a variable. -
iftells Python that a decision is coming. -
age >= 18is the condition. -
The colon
:tells Python that the block of code begins here. -
The indented
print()statement is executed if the condition is True.
Indentation in Conditions
Indentation is extremely important in Python.
Python uses indentation to determine which statements belong
inside an if block.
age = 25
if age >= 18:
print("You are an adult")
Notice that print() is moved to the right.
This tells Python that the print statement belongs to
the if statement.
if age >= 18:
print("You are an adult")
Using Variables in Conditions
Conditions become much more useful when you combine them with variables.
score = 75
if score >= 50:
print("You passed")
Python checks the value stored in score.
Since 75 is greater than or equal to 50, the message is displayed.
You can also use strings.
country = "Nigeria"
if country == "Nigeria":
print("Welcome to Nigeria")
elif Statements
Sometimes you need to check more than one condition.
This is where elif comes in.
elif means:
score = 75
if score >= 80:
print("Excellent")
elif score >= 50:
print("Passed")
Python first checks whether the score is 80 or higher.
That is False.
Python then checks whether the score is 50 or higher.
That is True, so Python prints:
Passed
else Statements
The else statement tells Python what to do when the condition is False.
age = 15
if age >= 18:
print("You are an adult")
else:
print("You are under 18")
Because the age is 15, the first condition is False.
Therefore Python executes the else block.
Output:
You are under 18
An else statement does not have a condition
of its own.
It simply handles everything that did not satisfy the previous conditions.
if + elif + else
You can combine all three structures to create a complete decision-making system.
score = 82
if score >= 80:
print("Excellent")
elif score >= 50:
print("Passed")
else:
print("Failed")
Python checks the conditions from top to bottom.
- If the first condition is True, Python runs it and stops checking the remaining conditions.
-
If it is False, Python checks the next
elif. -
If none of the conditions are True, Python runs
else.
The Order of Conditions Matters
Python checks conditions from top to bottom.
This means the order in which you write them matters.
For example:
score = 85
if score >= 50:
print("Passed")
elif score >= 80:
print("Excellent")
This will print:
Passed
Why?
Because 85 is already greater than or equal to 50.
Python executes the first matching condition and does not
continue to the next elif.
A better arrangement is:
score = 85
if score >= 80:
print("Excellent")
elif score >= 50:
print("Passed")
else:
print("Failed")
This prints:
Excellent
Using Multiple elif Statements
You can have several elif statements.
score = 72
if score >= 80:
print("A")
elif score >= 70:
print("B")
elif score >= 60:
print("C")
elif score >= 50:
print("D")
else:
print("F")
This is useful when you have several possible outcomes.
Python stops at the first condition that is True.
Combining Conditions
Sometimes one condition is not enough. You may need to check several things at the same time.
Python provides three important logical operators:
andornot
The and Operator
and means that all the required conditions
must be True.
age = 25
has_ticket = True
if age >= 18 and has_ticket:
print("You can enter")
Both conditions must be True before the message is displayed.
Think of and as:
The or Operator
or means that at least one of the conditions
needs to be True.
day = "Saturday"
if day == "Saturday" or day == "Sunday":
print("It is the weekend")
Only one of the two comparisons needs to be True.
The not Operator
not reverses a Boolean result.
logged_in = False
if not logged_in:
print("Please log in")
Because logged_in is False,
not logged_in becomes True.
Using Conditions with Strings
Conditions can also compare text.
username = "Olivia"
if username == "Olivia":
print("Welcome, Olivia")
Remember that Python is case-sensitive.
name = "Olivia"
if name == "olivia":
print("Welcome")
This condition is False because "Olivia"
and "olivia" are different strings.
Using in in Conditions
The in operator can check whether something
exists inside another value.
fruits = ["apple", "banana", "orange"]
if "banana" in fruits:
print("Banana is available")
You can also use it with strings.
message = "Welcome to Python"
if "Python" in message:
print("Python was mentioned")
Checking for None
Sometimes a variable does not currently contain a value.
Python represents this with None.
result = None
if result is None:
print("There is no result yet")
When checking specifically for None,
using is None is the recommended form.
Using Conditions with User Input
Conditions become much more interesting when users can enter information.
age = int(input("Enter your age: "))
if age >= 18:
print("You are an adult")
else:
print("You are under 18")
Notice the use of int().
The input() function returns text, so we convert
the answer into an integer before comparing it with 18.
Truthy and Falsy Values
Python can also use certain values directly in conditions.
For example, an empty string is considered False in a condition.
name = ""
if name:
print("Name was entered")
else:
print("No name was entered")
Because the string is empty, Python treats it as False.
Similarly, an empty list is considered False:
items = []
if items:
print("There are items")
else:
print("The list is empty")
You do not need to master truthiness immediately. The important thing at this stage is to understand that Python can evaluate certain values as True or False.
Nested Conditions
A nested condition is an if statement placed
inside another if statement.
For example:
age = 25
has_id = True
if age >= 18:
if has_id:
print("Entry allowed")
Python first checks the person's age.
If the person is at least 18, Python then checks whether they have an ID.
Nested conditions are useful, but do not use them when a simpler condition would be easier to understand.
The same example can sometimes be written more simply:
if age >= 18 and has_id:
print("Entry allowed")
Real-World Example: Age Checker
age = int(input("Enter your age: "))
if age >= 18:
print("You can register.")
else:
print("You are too young to register.")
This simple program demonstrates how variables, user input, conversion, and conditions can work together.
Real-World Example: Grade Calculator
score = int(input("Enter your score: "))
if score >= 80:
print("Grade: A")
elif score >= 70:
print("Grade: B")
elif score >= 60:
print("Grade: C")
elif score >= 50:
print("Grade: D")
else:
print("Grade: F")
This is an excellent example of using multiple conditions to classify information.
Real-World Example: Simple Login Check
Here is a basic learning example of how conditions can compare two pieces of information.
username = input("Username: ")
password = input("Password: ")
if username == "admin" and password == "python123":
print("Login successful")
else:
print("Invalid username or password")
Real-World Example: Agriculture
Conditions become especially useful when programming systems that need to react to sensor information.
Imagine a smart agricultural system measuring soil moisture.
soil_moisture = 25
if soil_moisture < 30:
print("Soil is dry")
print("Water the crop")
else:
print("Soil moisture is sufficient")
This is the beginning of the type of decision-making logic that can later be used in automation and agricultural robotics.
Common Beginner Mistakes
1. Using = instead of ==
Remember:
=assigns a value.==compares two values.
age = 18
if age == 18:
print("Exactly 18")
2. Forgetting the colon
Incorrect:
if age >= 18
print("Adult")
Correct:
if age >= 18:
print("Adult")
3. Incorrect indentation
The code inside an if statement must be
indented.
if age >= 18:
print("Adult")
4. Forgetting that input() returns text
This can cause problems:
age = input("Enter age: ")
if age >= 18:
print("Adult")
A safer beginner approach is:
age = int(input("Enter age: "))
if age >= 18:
print("Adult")
5. Putting conditions in the wrong order
Remember that Python checks conditions from top to bottom. Always think carefully about which condition should be checked first.
6. Making conditions unnecessarily complicated
If a simple condition can solve the problem, prefer the simple version.
if age >= 18 and has_id:
print("Allowed")
This may be easier to understand than several deeply nested
if statements.
Practice Exercises
Try these exercises yourself before looking for a solution.
Exercise 1 — Positive or Negative
Ask the user for a number and print whether the number is positive, negative, or zero.
Exercise 2 — Age Checker
Ask the user for their age.
- If the age is below 13, print "Child".
- If the age is between 13 and 17, print "Teenager".
- If the age is 18 or above, print "Adult".
Exercise 3 — Student Result
Ask the user for a student's score.
- 80–100 → Excellent
- 70–79 → Very Good
- 60–69 → Good
- 50–59 → Passed
- Below 50 → Failed
Exercise 4 — Even or Odd
Ask the user for a number and determine whether it is even or odd.
Hint: Use the modulus operator %.
Exercise 5 — Simple Temperature Checker
Ask the user for a temperature.
- Above 30 → "Hot"
- Between 20 and 30 → "Warm"
- Below 20 → "Cold"
Mini Project: Student Performance Checker
Let's combine what you have learned into a small program.
The program asks for a student's score and determines their performance.
score = int(input("Enter your score: "))
if score >= 80:
print("Excellent performance!")
elif score >= 70:
print("Very good performance!")
elif score >= 60:
print("Good performance!")
elif score >= 50:
print("You passed.")
else:
print("You failed. Keep practicing.")
Study this program carefully.
Try changing the score and predict the output before running the program.
Then modify the program yourself. Add another category or change the messages.
Python Conditions Quiz
Test yourself before moving to the next section.
1. Which keyword is used to start a condition?
2. Which operator checks whether two values are equal?
3. What does else do?
4. What does and mean in a condition?
5. Which statement checks whether a number is at least 18?
6. Which keyword allows you to check another condition after if?
7. What does the following print?
score = 40
if score >= 50:
print("Pass")
else:
print("Fail")
8. What must normally come after an if condition?
Python Conditions Summary
Conditions allow your Python programs to make decisions.
| Concept | Purpose |
|---|---|
| if | Runs code when a condition is True. |
| elif | Checks another condition if the previous one was False. |
| else | Runs when none of the previous conditions are True. |
| and | Requires multiple conditions to be True. |
| or | Allows at least one condition to be True. |
| not | Reverses a Boolean result. |
| == | Checks whether two values are equal. |
| > | Checks whether one value is greater than another. |
| < | Checks whether one value is less than another. |
| in | Checks whether something exists inside another value. |
| is None | Checks whether a value is None. |
Conditions allow your program to make decisions. The computer checks whether something is True or False and then follows the appropriate path.
Python Loops
Imagine you need to print the numbers from 1 to 100.
You could write 100 separate print() statements,
but that would be slow, repetitive, and difficult to maintain.
Python gives us a better solution: loops.
What Are Loops?
A loop is a programming structure that repeatedly executes a block of code.
Think about everyday activities.
If someone tells you:
"Keep watering the plants until the soil is wet."
You are being given a repeated task with a condition.
Programming loops work in a similar way.
Instead of writing:
print("Hello")
print("Hello")
print("Hello")
print("Hello")
print("Hello")
You can tell Python to repeat the instruction.
for i in range(5):
print("Hello")
The result is still five "Hello" messages, but the program is much shorter and easier to maintain.
Types of Loops in Python
Python mainly provides two types of loops:
- while loop
- for loop
Both are used for repetition, but they are useful in different situations.
| Loop | Common Use |
|---|---|
| while | Repeat while a condition remains True. |
| for | Repeat through a sequence or a known range of values. |
while Loops
A while loop repeats code as long as a condition
is True.
Its basic structure is:
while condition:
code to repeat
For example:
number = 1
while number <= 5:
print(number)
number = number + 1
Output:
1
2
3
4
5
Python keeps checking the condition:
- Is number less than or equal to 5?
- If yes, run the code.
- Increase number by 1.
- Check the condition again.
- Stop when the condition becomes False.
Understanding a while Loop Step by Step
number = 1
while number <= 5:
print(number)
number = number + 1
Let's understand what happens.
Step 1
Python creates the variable:
number = 1
Step 2
Python checks:
number <= 5
Since 1 is less than or equal to 5, the condition is True.
Step 3
Python prints 1.
Step 4
The number is increased:
number = number + 1
Now number is 2.
Python repeats the process until number becomes 6.
At that point:
6 <= 5
is False, so the loop stops.
while Loops and User Input
One common use of a while loop is to keep asking
a user for information until they provide the expected answer.
password = ""
while password != "python":
password = input("Enter the password: ")
print("Access granted")
The loop continues while the password is incorrect.
Once the user enters python, the condition becomes
False and the loop ends.
This is one reason while loops are useful:
you may not know exactly how many times the loop needs to run.
Infinite Loops
An infinite loop is a loop that never becomes False.
For example:
number = 1
while number <= 5:
print(number)
This program never changes number.
Therefore the condition will always remain True.
The corrected version is:
number = 1
while number <= 5:
print(number)
number += 1
for Loops
A for loop is commonly used when you want to
repeat something for each item in a sequence or collection.
For example:
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
Output:
apple
banana
orange
Python takes each item from the list and temporarily stores
it in the variable fruit.
The loop then runs once for each item.
Using a for Loop with a String
Strings are sequences of characters, so you can loop through them one character at a time.
word = "Python"
for letter in word:
print(letter)
Output:
P
y
t
h
o
n
This demonstrates an important idea:
a for loop can move through items one by one.
The range() Function
The range() function is commonly used with
for loops when you want to repeat something
a specific number of times.
for number in range(5):
print(number)
Output:
0
1
2
3
4
Notice something important:
range(5) starts at 0 and stops before 5.
range() with a Start and Stop
You can specify where the range should start.
for number in range(1, 6):
print(number)
Output:
1
2
3
4
5
The first number is the starting point.
The second number is the stopping point, but it is not included.
range() with a Step
You can also tell range() how much to increase
the number each time.
for number in range(0, 11, 2):
print(number)
Output:
0
2
4
6
8
10
The 2 is the step.
It means increase the number by 2 each time.
break
The break statement immediately stops a loop.
for number in range(1, 10):
if number == 5:
break
print(number)
Output:
1
2
3
4
When number becomes 5, Python encounters break
and leaves the loop immediately.
continue
The continue statement skips the current
iteration and moves to the next one.
for number in range(1, 6):
if number == 3:
continue
print(number)
Output:
1
2
4
5
The loop did not stop completely. It simply skipped the number 3.
break vs continue
| Keyword | What it does |
|---|---|
| break | Stops the entire loop. |
| continue | Skips the current iteration and continues the loop. |
A simple way to remember:
- break = leave the loop.
- continue = skip this turn.
Nested Loops
A nested loop is a loop inside another loop.
For example:
for outer in range(3):
for inner in range(2):
print("Outer:", outer, "Inner:", inner)
The inner loop runs completely for every iteration of the outer loop.
Nested loops are useful for working with things such as:
- Tables
- Grids
- Rows and columns
- Matrix-like data
- Repeated combinations
However, nested loops can become difficult to understand, so use them carefully.
Using Loops with Conditions
Loops and conditions are often used together.
For example, suppose you want to print only even numbers.
for number in range(1, 11):
if number % 2 == 0:
print(number)
Output:
2
4
6
8
10
Here, the loop produces the numbers and the condition decides which numbers should be printed.
This combination is extremely important in programming.
Loops with User Input
You can use loops to repeatedly ask users for information.
For example:
for i in range(3):
name = input("Enter your name: ")
print("Hello", name)
The program asks for a name three times.
This is useful when processing repeated information.
Using Loops to Calculate a Total
One of the most common uses of loops is adding values together.
total = 0
for number in range(1, 6):
total = total + number
print(total)
Output:
15
The variable total keeps track of the running
total.
This pattern is called an accumulator.
You will see this pattern frequently when working with data and real-world problems.
Real-World Uses of Loops
Loops are everywhere in programming.
Processing Student Scores
scores = [70, 85, 62, 91, 55]
for score in scores:
print(score)
Checking Multiple Crops
crops = ["maize", "rice", "beans"]
for crop in crops:
print("Checking", crop)
Checking Sensor Readings
soil_moisture_values = [25, 40, 31, 18, 45]
for moisture in soil_moisture_values:
if moisture < 30:
print("Soil is dry")
else:
print("Soil moisture is sufficient")
This is the kind of basic logic that can later become part of an automated agricultural system.
Common Beginner Mistakes
1. Forgetting to update a while loop
This can create an infinite loop.
number = 1
while number <= 5:
print(number)
Always make sure the condition can eventually become False.
2. Forgetting the colon
for number in range(5):
print(number)
The colon is required after the loop statement.
3. Incorrect indentation
for number in range(5):
print(number)
The code that belongs to the loop must be indented.
4. Forgetting that range() stops before the end value
range(1, 6)
produces 1 through 5, not 1 through 6.
5. Confusing break and continue
Remember:
breakstops the loop.continueskips the current iteration.
Practice Exercises
Try solving these yourself before checking a solution.
Exercise 1 — Count from 1 to 10
Write a for loop that prints the numbers
from 1 to 10.
Exercise 2 — Count Backwards
Write a loop that prints:
10
9
8
7
6
5
4
3
2
1
Exercise 3 — Even Numbers
Print all even numbers between 1 and 20.
Hint: use %.
Exercise 4 — Sum of Numbers
Calculate the sum of numbers from 1 to 100 using a loop.
Exercise 5 — Names
Create a list containing five names and use a
for loop to print each name.
Exercise 6 — Password Attempts
Create a program that allows a user to try entering a password up to three times.
Use a loop and a condition.
Exercise 7 — Soil Moisture
Given the following readings:
readings = [20, 35, 28, 45, 18, 50]
Loop through the readings and print:
- "Dry" when the reading is below 30.
- "Moist" when the reading is 30 or above.
Mini Project: Number Analyzer
Let's combine loops, conditions, variables, and operators into one small project.
This program examines numbers from 1 to 10 and tells us whether each number is even or odd.
for number in range(1, 11):
if number % 2 == 0:
print(number, "is even")
else:
print(number, "is odd")
Try changing the range.
Then modify the program so that it also calculates the total of all the numbers.
Python Loops Quiz
Test your understanding before moving forward.
1. What is the main purpose of a loop?
2. Which loop runs while a condition is True?
3. What does range(5) produce?
4. What does break do?
5. What does continue do?
6. Which loop is commonly used to go through items in a list?
7. What happens when a while loop's condition becomes False?
8. What is a nested loop?
Python Loops Summary
Loops allow Python programs to repeat tasks efficiently.
| Concept | Purpose |
|---|---|
| while | Repeats while a condition is True. |
| for | Loops through a sequence or range. |
| range() | Generates a sequence of numbers. |
| break | Stops the loop immediately. |
| continue | Skips the current iteration. |
| Nested loop | A loop placed inside another loop. |
Use a for loop when you are generally
moving through a collection or a known range.
Use a while loop when repetition depends
on a condition remaining True.
Python Strings
Strings are one of the most commonly used data types in Python. Whenever your program needs to work with text, you will probably be working with strings.
Names, usernames, messages, addresses, sentences, email addresses and even pieces of code can all be represented as strings.
What Is a String?
A string is text surrounded by quotation marks.
For example:
"Hello"
This is a string because Hello is surrounded
by quotation marks.
You can also store a string inside a variable:
name = "Olivia"
print(name)
Output:
Olivia
Strings can contain letters, numbers, spaces and special characters.
"Python"
"Hello World"
"12345"
"olivia@example.com"
"Welcome to Gabbywall!"
Even though "12345" contains numbers,
it is still a string because it is surrounded by quotation
marks.
Creating Strings
Python allows you to create strings using either single quotation marks or double quotation marks.
name = "Olivia"
Or:
name = 'Olivia'
Both are valid.
The important thing is to make sure that the quotation marks are properly matched.
message = "Hello"
city = 'Enugu'
Single Quotes vs Double Quotes
Python does not treat single and double quotation marks as different types of strings.
name = "Olivia"
name = 'Olivia'
Both create a string.
You can choose whichever style you prefer, but consistency is important when writing larger programs.
Sometimes one type of quotation mark is useful when the text itself contains another type.
message = "I'm learning Python"
print(message)
Here, double quotes allow the apostrophe in
I'm to appear normally.
You could also write:
message = 'She said "Hello"'
Multiline Strings
Sometimes you want a string to contain multiple lines.
Python allows you to create multiline strings using triple quotation marks.
message = """Welcome to Gabbywall.
This is a Python course.
Keep learning!"""
print(message)
Triple quotes can be written using either single quotes or double quotes.
text = '''This is
a multiline
string.'''
Multiline strings are useful when working with longer pieces of text.
Finding the Length of a String
Python provides the len() function to determine
how many characters are inside a string.
name = "Python"
print(len(name))
Output:
6
Python contains six characters:
P y t h o n
Spaces are also counted as characters.
message = "Hello World"
print(len(message))
The space between "Hello" and "World" is included in the count.
Accessing Characters in a String
Strings are sequences of characters. Each character has a position called an index.
Python starts counting positions from 0, not 1.
word = "Python"
The positions are:
P y t h o n
0 1 2 3 4 5
You can access a character using square brackets.
word = "Python"
print(word[0])
Output:
P
Another example:
print(word[3])
Output:
h
Negative Indexing
Python also allows you to access characters from the end of a string using negative indexes.
word = "Python"
print(word[-1])
Output:
n
The last character is -1.
P y t h o n
-6 -5 -4 -3 -2 -1
This can be useful when you want to access the end of a string without knowing its exact length.
Slicing Strings
Slicing allows you to take a portion of a string.
The basic syntax is:
string[start:stop]
For example:
word = "Python"
print(word[0:3])
Output:
Pyt
The starting position is included, but the stopping position is not included.
So 0:3 means positions 0, 1 and 2.
Slicing from the Beginning
You can leave out the starting position.
word = "Python"
print(word[:3])
Output:
Pyt
Python automatically starts from the beginning.
Slicing to the End
You can also leave out the stopping position.
word = "Python"
print(word[2:])
Output:
thon
Python takes everything from position 2 to the end.
String Methods
Python provides many built-in methods for working with strings.
A method is an action that can be performed on a value.
For example:
name = "olivia"
print(name.upper())
Output:
OLIVIA
Notice the dot:
name.upper()
The upper() method changes the string to uppercase
in the returned result.
The original string itself is not changed.
upper() and lower()
upper() converts letters to uppercase.
text = "hello"
print(text.upper())
Output:
HELLO
lower() converts letters to lowercase.
text = "HELLO"
print(text.lower())
Output:
hello
These methods are especially useful when comparing user input.
answer = input("Continue? ")
if answer.lower() == "yes":
print("Continuing...")
Now inputs such as YES, Yes and
yes can all be handled the same way.
strip()
The strip() method removes unnecessary whitespace
from the beginning and end of a string.
name = " Olivia "
print(name.strip())
Output:
Olivia
This is useful when processing information entered by users.
name = input("Enter your name: ").strip()
print("Hello", name)
replace()
The replace() method replaces one piece of text
with another.
message = "I love Java"
new_message = message.replace("Java", "Python")
print(new_message)
Output:
I love Python
Again, the original string is not changed automatically. The result is returned and can be stored in another variable.
split()
The split() method divides a string into smaller
pieces and returns them as a list.
sentence = "Python is easy"
words = sentence.split()
print(words)
Output:
['Python', 'is', 'easy']
By default, Python separates the text at whitespace.
We will study lists in much more detail later in this course.
join()
The join() method does the opposite of
split() in many common situations.
It can combine multiple strings into one string.
words = ["Python", "is", "powerful"]
sentence = " ".join(words)
print(sentence)
Output:
Python is powerful
The string before .join() determines what
separates the items.
find()
The find() method searches for a piece of text
inside another string.
text = "I am learning Python"
position = text.find("Python")
print(position)
Python returns the position where the word begins.
If the text cannot be found, find() returns
-1.
count()
The count() method tells you how many times a
particular piece of text appears.
text = "banana"
print(text.count("a"))
Output:
3
startswith() and endswith()
These methods allow you to check how a string begins or ends.
filename = "photo.jpg"
print(filename.startswith("photo"))
Output:
True
You can also check how it ends:
print(filename.endswith(".jpg"))
Output:
True
Combining Strings
Combining strings together is called concatenation.
You can use the + operator.
first_name = "Olivia"
last_name = "Ezeani"
full_name = first_name + " " + last_name
print(full_name)
Output:
Olivia Ezeani
Notice that we added a space between the two names.
Strings and Numbers
Be careful when combining strings and numbers.
This will cause an error:
age = 27
print("I am " + age + " years old")
Why?
Because age is an integer while the other values
are strings.
One solution is to convert the number into a string:
age = 27
print("I am " + str(age) + " years old")
However, there is an easier and more modern approach: f-strings.
f-Strings
f-strings provide a convenient way to insert variables directly into a string.
name = "Olivia"
age = 27
print(f"My name is {name} and I am {age} years old.")
Output:
My name is Olivia and I am 27 years old.
The f before the quotation mark tells Python
that the string is an f-string.
Variables can be placed inside curly braces:
{name}
{age}
f-strings are one of the most useful ways to create dynamic text in Python.
Escape Characters
Sometimes you need to place special characters inside a string.
Python uses the backslash \ for many
escape sequences.
New Line
print("Hello\nPython")
Output:
Hello
Python
Tab
print("Name:\tOlivia")
The \t creates a tab space.
Quotation Marks
You can use a backslash when you need quotation marks inside a string that use the same quote style.
message = "She said \"Hello\""
print(message)
Strings Cannot Be Changed Directly
Python strings are immutable.
This means you cannot change an individual character directly after the string has been created.
For example, this does not work:
word = "Python"
word[0] = "J"
Instead, you create a new string.
word = "Python"
word = "J" + word[1:]
print(word)
Output:
Jython
You do not need to memorize the technical meaning of "immutable" yet. Just remember that individual characters in a string cannot be replaced directly.
Checking Strings
Python provides useful methods for checking the contents of strings.
isalpha()
Checks whether all characters are letters.
text = "Python"
print(text.isalpha())
Output:
True
isdigit()
Checks whether all characters are digits.
text = "12345"
print(text.isdigit())
Output:
True
isalnum()
Checks whether the string contains only letters and numbers.
text = "Python123"
print(text.isalnum())
Output:
True
Strings and User Input
The input() function returns a string.
name = input("Enter your name: ")
print("Hello", name)
Even if the user enters a number, input()
initially gives you a string.
age = input("Enter your age: ")
print(type(age))
If the user enters 27, Python still treats the
result as:
<class 'str'>
If you need a number, convert it:
age = int(input("Enter your age: "))
Real-World Example: Cleaning User Input
Imagine a program asking a user to enter their country.
country = input("Enter your country: ")
country = country.strip().lower()
if country == "nigeria":
print("Welcome!")
The program uses two string methods:
strip()removes unnecessary spaces.lower()converts the text to lowercase.
This makes the program more tolerant of how the user enters the information.
Common Beginner Mistakes
1. Forgetting quotation marks
Incorrect:
name = Olivia
Correct:
name = "Olivia"
2. Confusing a number with a numeric string
age = 27
This is an integer.
age = "27"
This is a string.
3. Forgetting that indexes start at 0
word = "Python"
print(word[0])
The result is P, not y.
4. Trying to change a character directly
word = "Python"
word[0] = "J"
Strings are immutable, so this will produce an error.
5. Forgetting that methods use parentheses
Correct:
name.upper()
The parentheses are part of calling the method.
Practice Exercises
Try these exercises yourself before checking a solution.
Exercise 1 — Your Name
Create a variable containing your name and print it.
Exercise 2 — String Length
Create a string and use len() to find its length.
Exercise 3 — First Character
Create a word and print its first character using indexing.
Exercise 4 — Last Character
Print the last character of a string using negative indexing.
Exercise 5 — Uppercase
Ask the user for their name and print it in uppercase.
Exercise 6 — Clean Input
Ask the user to enter their name with possible spaces around it.
Remove those spaces using strip().
Exercise 7 — Replace Text
Create the string:
"I am learning Java"
Replace Java with Python.
Exercise 8 — Word Counter
Ask the user to enter a sentence and use
split() to separate the words.
Exercise 9 — f-String
Create variables for your name, age and country. Use an f-string to print them in one sentence.
Mini Project: Personal Profile
Let's combine several string concepts into one small project.
name = input("Enter your name: ").strip()
country = input("Enter your country: ").strip()
profession = input("Enter your profession: ").strip()
print()
print("----- PROFILE -----")
print(f"Name: {name}")
print(f"Country: {country}")
print(f"Profession: {profession}")
This project uses:
input()strip()- variables
- strings
- f-strings
print()
Try improving the project by adding your age, favorite programming language and a short description.
Python Strings Quiz
Test yourself before moving to the next topic.
1. What is a string?
2. Which is a valid string?
3. What index represents the first character in a Python string?
4. Which function finds the length of a string?
5. What does upper() do?
6. What does strip() commonly remove?
7. Which symbol is commonly used to concatenate strings?
8. What does the following produce?
name = "Python"
print(name[-1])
Python Strings Summary
Strings are used whenever your program needs to work with text.
| Concept | Purpose |
|---|---|
| String | Represents text. |
| len() | Finds the number of characters. |
| Indexing | Accesses individual characters. |
| Slicing | Extracts part of a string. |
| upper() | Converts text to uppercase. |
| lower() | Converts text to lowercase. |
| strip() | Removes surrounding whitespace. |
| replace() | Replaces text with other text. |
| split() | Breaks a string into pieces. |
| join() | Combines strings together. |
| find() | Searches for text inside a string. |
| count() | Counts occurrences of text. |
| f-string | Inserts variables into text easily. |
Strings are sequences of characters. You can access, search, slice, combine and transform them using Python's string operations and methods.
Python Lists
Lists are one of the most important data structures you will learn in Python. They allow you to store multiple values inside a single variable.
Imagine you want to store the names of five students. You could create five different variables, but that would quickly become difficult to manage.
student1 = "Ada"
student2 = "John"
student3 = "Mary"
student4 = "David"
student5 = "Sarah"
A list gives you a much better way to organize those values:
students = ["Ada", "John", "Mary", "David", "Sarah"]
What Is a List?
A list is a collection of items written inside square brackets
[].
fruits = ["apple", "banana", "orange"]
This list contains three items.
Lists can contain different types of data.
items = ["Python", 27, 3.14, True]
Although it is possible to mix data types in a list, it is usually clearer to use lists for related information.
Creating a List
To create a list, place your items between square brackets.
colors = ["red", "green", "blue"]
You can also create an empty list.
students = []
An empty list contains no items yet.
You can add items to it later.
Items in a List
Each value stored inside a list is called an item or element.
fruits = ["apple", "banana", "orange"]
The items are:
- apple
- banana
- orange
Lists can store strings, numbers, Boolean values and even other collections.
scores = [75, 82, 91, 68, 88]
passed = [True, True, True, False, True]
Lists Are Ordered
Items in a Python list have a specific order.
fruits = ["apple", "banana", "orange"]
Python remembers the order in which the items appear.
This means that apple is first,
banana is second and orange is third.
This becomes important when accessing items by their index.
Accessing List Items
Just like strings, lists use indexes.
Python starts counting from 0.
fruits = ["apple", "banana", "orange"]
The positions are:
apple banana orange
0 1 2
To get the first item:
print(fruits[0])
Output:
apple
To get the second item:
print(fruits[1])
Output:
banana
Negative Indexing
You can also access list items from the end using negative indexes.
fruits = ["apple", "banana", "orange"]
print(fruits[-1])
Output:
orange
The positions are:
apple banana orange
-3 -2 -1
Changing List Items
One of the important differences between lists and strings is that lists are mutable.
This means you can change individual items after creating the list.
fruits = ["apple", "banana", "orange"]
fruits[1] = "mango"
print(fruits)
Output:
['apple', 'mango', 'orange']
We replaced banana with mango.
Changing Multiple List Items
You can change several items at once using slicing.
colors = ["red", "green", "blue", "yellow"]
colors[1:3] = ["black", "white"]
print(colors)
Output:
['red', 'black', 'white', 'yellow']
Finding the Length of a List
The len() function tells you how many items
are in a list.
fruits = ["apple", "banana", "orange"]
print(len(fruits))
Output:
3
Notice that len() tells you the number of items,
while indexing tells you the position of an item.
Adding Items with append()
The append() method adds one item to the end
of a list.
fruits = ["apple", "banana"]
fruits.append("orange")
print(fruits)
Output:
['apple', 'banana', 'orange']
This is especially useful when you do not know all the items when the program starts.
Adding Items with insert()
The insert() method allows you to add an item
at a specific position.
fruits = ["apple", "orange"]
fruits.insert(1, "banana")
print(fruits)
Output:
['apple', 'banana', 'orange']
The first argument is the position and the second argument is the item you want to add.
Adding Multiple Items with extend()
The extend() method adds multiple items from
another collection.
fruits = ["apple", "banana"]
more_fruits = ["orange", "mango"]
fruits.extend(more_fruits)
print(fruits)
Output:
['apple', 'banana', 'orange', 'mango']
The difference is simple:
append()adds one item.extend()adds items from another collection.
Removing Items with remove()
The remove() method removes an item by its value.
fruits = ["apple", "banana", "orange"]
fruits.remove("banana")
print(fruits)
Output:
['apple', 'orange']
If the specified value does not exist, Python raises an error.
Removing Items with pop()
The pop() method removes an item using its index.
fruits = ["apple", "banana", "orange"]
fruits.pop(1)
print(fruits)
Output:
['apple', 'orange']
If you use pop() without an index, Python removes
the last item.
fruits = ["apple", "banana", "orange"]
fruits.pop()
print(fruits)
Output:
['apple', 'banana']
Deleting Items with del
You can use the del statement to delete an item
using its index.
fruits = ["apple", "banana", "orange"]
del fruits[1]
print(fruits)
Output:
['apple', 'orange']
You can also delete the entire list.
del fruits
Removing Everything with clear()
The clear() method removes all items from a list
but leaves the list itself available.
fruits = ["apple", "banana", "orange"]
fruits.clear()
print(fruits)
Output:
[]
Slicing Lists
You can extract part of a list using slicing.
numbers = [10, 20, 30, 40, 50]
print(numbers[1:4])
Output:
[20, 30, 40]
Just like strings, the starting index is included and the ending index is not included.
You can also leave out the starting or ending position.
numbers[:3]
numbers[2:]
numbers[:]
Checking Whether an Item Exists
You can use the in operator to check whether
an item exists in a list.
fruits = ["apple", "banana", "orange"]
print("banana" in fruits)
Output:
True
You can also use not in.
print("mango" not in fruits)
Output:
True
Sorting a List
The sort() method sorts items in ascending order
by default.
numbers = [50, 10, 40, 20, 30]
numbers.sort()
print(numbers)
Output:
[10, 20, 30, 40, 50]
You can sort numbers from largest to smallest using
reverse=True.
numbers.sort(reverse=True)
print(numbers)
Output:
[50, 40, 30, 20, 10]
Reversing a List
The reverse() method reverses the current order
of the items.
numbers = [1, 2, 3, 4, 5]
numbers.reverse()
print(numbers)
Output:
[5, 4, 3, 2, 1]
Copying a List
You can make a copy of a list using the copy()
method.
fruits = ["apple", "banana", "orange"]
new_fruits = fruits.copy()
print(new_fruits)
This creates another list containing the same items.
Counting Items
The count() method tells you how many times
a value appears in a list.
numbers = [1, 2, 2, 3, 2, 4]
print(numbers.count(2))
Output:
3
Finding an Item's Position
The index() method returns the position of
an item.
fruits = ["apple", "banana", "orange"]
print(fruits.index("banana"))
Output:
1
Looping Through a List
Lists become especially powerful when combined with loops.
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
Output:
apple
banana
orange
The loop takes each item from the list one at a time.
This is one of the most common patterns you will use in Python.
Lists with Conditions
You can combine lists with if statements.
scores = [45, 72, 81, 39, 90]
for score in scores:
if score >= 50:
print(score, "Pass")
else:
print(score, "Fail")
This allows your program to process many values automatically.
List Comprehension
Python provides a shorter way to create lists from existing sequences called a list comprehension.
For example, suppose you want the squares of numbers 1 through 5.
You could write:
squares = []
for number in range(1, 6):
squares.append(number * number)
print(squares)
A list comprehension can express the same idea more compactly:
squares = [number * number for number in range(1, 6)]
print(squares)
Output:
[1, 4, 9, 16, 25]
Do not worry if this looks unfamiliar. The important thing is to understand normal lists and loops first.
Lists Inside Lists
A list can contain other lists. These are sometimes called nested lists.
students = [
["Ada", 85],
["John", 72],
["Mary", 91]
]
You can access an item from the outer list first:
print(students[0])
Output:
['Ada', 85]
You can then access an item inside that inner list:
print(students[0][0])
Output:
Ada
Nested lists are useful for representing structured data, although dictionaries and other data structures may sometimes be a better choice.
Real-World Example: Student Scores
Imagine you are building a student performance program.
scores = [72, 85, 64, 91, 78]
print("Number of scores:", len(scores))
print("Highest score:", max(scores))
print("Lowest score:", min(scores))
print("Total score:", sum(scores))
Output:
Number of scores: 5
Highest score: 91
Lowest score: 64
Total score: 390
Python provides useful built-in functions such as:
len()— number of itemsmax()— largest valuemin()— smallest valuesum()— total of numeric values
Common Beginner Mistakes
1. Forgetting square brackets
Incorrect:
fruits = "apple", "banana", "orange"
Python can interpret this as a tuple rather than a list.
For a list, use:
fruits = ["apple", "banana", "orange"]
2. Forgetting that indexes start at 0
fruits = ["apple", "banana", "orange"]
print(fruits[0])
The first item is at index 0.
3. Using an index that does not exist
fruits = ["apple", "banana"]
print(fruits[5])
This causes an IndexError because index 5
does not exist.
4. Confusing remove() and pop()
remove() removes by value:
fruits.remove("banana")
pop() removes by index:
fruits.pop(1)
5. Forgetting that methods can modify a list
Methods such as sort(),
reverse(), append() and
remove() change the list itself.
Practice Exercises
Try solving these exercises yourself before looking for help.
Exercise 1 — Create a List
Create a list containing five of your favorite foods.
Exercise 2 — Access Items
Print the first, second and last items in your list.
Exercise 3 — Change an Item
Replace one item in your list with another item.
Exercise 4 — Add an Item
Add a new item using append().
Exercise 5 — Insert an Item
Insert a new item at position 1.
Exercise 6 — Remove an Item
Remove one item using remove().
Exercise 7 — Count Items
Create a list containing repeated values and use
count().
Exercise 8 — Sort Numbers
Create a list of numbers and sort them from smallest to largest.
Exercise 9 — Loop Through a List
Create a list of names and use a for loop to
print each name.
Exercise 10 — Student Scores
Create a list containing five student scores. Calculate the total, average, highest and lowest scores.
Mini Project: Simple Shopping List
Let's build a simple shopping list using the concepts you have learned.
shopping_list = []
shopping_list.append("Rice")
shopping_list.append("Milk")
shopping_list.append("Bread")
shopping_list.append("Eggs")
print("Shopping List:")
for item in shopping_list:
print("-", item)
Output:
Shopping List:
- Rice
- Milk
- Bread
- Eggs
Now improve the program.
Try allowing the user to enter their own items.
shopping_list = []
item = input("Enter an item: ")
shopping_list.append(item)
print(shopping_list)
Later, when you understand loops and conditions better, you can turn this into a complete shopping-list application that allows users to add, remove and view items.
Python Lists Quiz
Test your understanding before continuing.
1. Which brackets are used to create a list?
2. What is the index of the first list item?
3. Which method adds an item to the end of a list?
4. Which method removes an item by its value?
5. What does len() return for a list?
6. Which method sorts a list?
7. What does pop() normally remove when no index is provided?
8. What does "apple" in fruits check?
"apple" in fruits
Python Lists Summary
Lists allow you to store and manage multiple values inside one variable.
| Concept | Purpose |
|---|---|
| List | Stores multiple items in one collection. |
| Index | Identifies the position of an item. |
| len() | Returns the number of items. |
| append() | Adds an item to the end. |
| insert() | Adds an item at a specific position. |
| extend() | Adds items from another collection. |
| remove() | Removes an item by value. |
| pop() | Removes an item by index. |
| clear() | Removes all items. |
| sort() | Sorts the list. |
| reverse() | Reverses the list order. |
| count() | Counts how many times a value appears. |
| index() | Finds the position of an item. |
| in | Checks whether an item exists. |
A list lets you keep many related values together and gives you tools for adding, removing, changing, searching, sorting and processing those values.
Python Tuples
In the previous lesson, you learned about Python lists. Lists are useful when you need a collection of values that you may want to change.
Now we are going to learn about another Python collection: tuples.
Tuples look very similar to lists, but there is one major difference:
This property makes tuples useful when you want to store related information that should remain unchanged.
What Is a Tuple?
A tuple is a collection of items that is ordered and cannot be changed after it has been created.
Tuples are normally written using parentheses:
fruits = ("apple", "banana", "orange")
This tuple contains three items.
Like lists, tuple indexes begin at 0.
Tuple vs List
The easiest way to understand tuples is to compare them with lists.
my_list = ["apple", "banana", "orange"]
my_tuple = ("apple", "banana", "orange")
The list uses square brackets:
["apple", "banana", "orange"]
The tuple uses parentheses:
("apple", "banana", "orange")
| Feature | List | Tuple |
|---|---|---|
| Syntax | [] |
() |
| Ordered | Yes | Yes |
| Changeable | Yes | No |
| Allows duplicates | Yes | Yes |
| Indexing | Yes | Yes |
Creating a Tuple
Creating a tuple is straightforward.
colors = ("red", "green", "blue")
You can also create a tuple containing numbers:
numbers = (10, 20, 30, 40)
You can create a tuple containing different data types:
person = ("Olivia", 27, True, 1.75)
However, it is usually best to group related information together.
Creating an Empty Tuple
You can create an empty tuple using empty parentheses.
my_tuple = ()
The tuple currently contains no items.
Creating a Tuple with One Item
There is an important rule when creating a tuple containing only one item.
You need a comma after the item.
fruits = ("apple",)
Without the comma, Python treats it as an ordinary value inside parentheses.
fruits = ("apple")
The second example is simply a string, not a tuple.
You can confirm this with type().
print(type(("apple",)))
print(type(("apple")))
Accessing Tuple Items
Tuples use indexes just like lists and strings.
fruits = ("apple", "banana", "orange")
print(fruits[0])
Output:
apple
The second item is at index 1:
print(fruits[1])
Output:
banana
Negative Indexing
You can access items from the end of a tuple using negative indexes.
fruits = ("apple", "banana", "orange")
print(fruits[-1])
Output:
orange
The positions are:
apple banana orange
-3 -2 -1
Finding the Length of a Tuple
Use len() to find the number of items in a tuple.
fruits = ("apple", "banana", "orange")
print(len(fruits))
Output:
3
Slicing Tuples
You can extract part of a tuple using slicing.
numbers = (10, 20, 30, 40, 50)
print(numbers[1:4])
Output:
(20, 30, 40)
You can also leave out the starting or ending index.
numbers[:3]
numbers[2:]
numbers[:]
Tuples Cannot Be Changed
This is the most important thing to understand about tuples.
Once a tuple has been created, you cannot change an individual item.
fruits = ("apple", "banana", "orange")
fruits[1] = "mango"
This produces an error because tuples are immutable.
This does not mean that Python can never create another tuple containing different values. It means the existing tuple itself cannot have its items changed.
Why Use Tuples?
If lists can store multiple values, you may wonder: why do we need tuples?
Tuples are useful when the values should remain fixed.
For example, suppose you want to store the coordinates of a fixed location:
coordinates = (6.5244, 3.3792)
Or the dimensions of an object:
dimensions = (1920, 1080)
Or the days of the week:
days = (
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
)
These are examples of information that your program may want to treat as a fixed collection.
Checking Whether an Item Exists
You can use in with tuples.
fruits = ("apple", "banana", "orange")
print("banana" in fruits)
Output:
True
You can also use not in.
print("mango" not in fruits)
Output:
True
Looping Through a Tuple
Tuples can be used with for loops.
fruits = ("apple", "banana", "orange")
for fruit in fruits:
print(fruit)
Output:
apple
banana
orange
Python takes each item from the tuple one at a time.
Counting Items with count()
The count() method tells you how many times
a value appears in a tuple.
numbers = (1, 2, 2, 3, 2, 4)
print(numbers.count(2))
Output:
3
Finding an Item with index()
The index() method returns the position of
a specified item.
fruits = ("apple", "banana", "orange")
print(fruits.index("banana"))
Output:
1
Converting Between Lists and Tuples
You can convert a list into a tuple using tuple().
fruits = ["apple", "banana", "orange"]
fruits_tuple = tuple(fruits)
print(fruits_tuple)
Output:
('apple', 'banana', 'orange')
You can also convert a tuple into a list using
list().
fruits = ("apple", "banana", "orange")
fruits_list = list(fruits)
print(fruits_list)
This can be useful when you need to temporarily work with a collection in a changeable form.
Tuple Unpacking
Tuple unpacking allows you to assign the values in a tuple to separate variables.
person = ("Olivia", 27, "Python")
name, age, language = person
print(name)
print(age)
print(language)
Output:
Olivia
27
Python
Python takes the first tuple item and assigns it to
name, the second to age, and
the third to language.
Using * During Unpacking
Python also allows an asterisk to collect multiple remaining values into a list during unpacking.
numbers = (10, 20, 30, 40, 50)
first, *middle, last = numbers
print(first)
print(middle)
print(last)
Output:
10
[20, 30, 40]
50
The *middle variable collects the values that
remain between the first and last values.
Nested Tuples
A tuple can contain other tuples.
students = (
("Ada", 85),
("John", 72),
("Mary", 91)
)
You can access the first inner tuple:
print(students[0])
Output:
('Ada', 85)
You can then access the student's name:
print(students[0][0])
Output:
Ada
Tuples Can Contain Different Data Types
A tuple can contain different types of values.
data = ("Olivia", 27, 85.5, True)
Here we have:
- A string
- An integer
- A float
- A Boolean value
You can also have a tuple containing another collection.
data = ("Python", [1, 2, 3], True)
Real-World Examples of Tuples
1. Coordinates
location = (6.5244, 3.3792)
A coordinate pair is naturally represented as two related values that belong together.
2. RGB Values
rgb = (255, 128, 0)
The values represent a color using red, green and blue components.
3. Dimensions
screen = (1920, 1080)
This could represent width and height.
4. Fixed Configuration
robot_dimensions = (40, 25, 15)
A robotics program could use a tuple to represent fixed dimensions such as width, height and depth.
5. Agricultural Coordinates
field_position = (12.45, 8.72)
A program could use a tuple to represent a fixed position within a field or coordinate system.
Common Beginner Mistakes
1. Trying to change a tuple
colors = ("red", "green", "blue")
colors[0] = "black"
This does not work because tuples are immutable.
2. Forgetting the comma in a one-item tuple
Correct:
item = ("Python",)
Not a tuple:
item = ("Python")
3. Confusing tuple syntax with list syntax
my_list = [1, 2, 3]
my_tuple = (1, 2, 3)
Remember:
[]→ list()→ tuple
4. Unpacking the wrong number of values
numbers = (10, 20, 30)
a, b = numbers
This produces an error because there are three values but only two variables.
Practice Exercises
Exercise 1 — Create a Tuple
Create a tuple containing five countries.
Exercise 2 — Access Items
Print the first and last items in your tuple.
Exercise 3 — Find Length
Use len() to find the number of items.
Exercise 4 — Membership
Use in to check whether a particular country
exists in your tuple.
Exercise 5 — Count
Create a tuple containing repeated numbers and use
count().
Exercise 6 — Index
Use index() to find the position of an item.
Exercise 7 — Unpacking
Create a tuple containing your name, age and favorite programming language. Unpack the values into three variables.
Exercise 8 — Coordinates
Create a tuple containing two numbers representing an imaginary location.
Mini Project: Student Record
Let's use a tuple to store a simple student record.
student = ("Ada", 85, "Biology")
name, score, subject = student
print("Student:", name)
print("Score:", score)
print("Subject:", subject)
Output:
Student: Ada
Score: 85
Subject: Biology
The tuple keeps the three related values together, while unpacking makes them easy to work with individually.
Try creating your own student record.
Python Tuples Quiz
Test what you have learned.
1. Which brackets are commonly used to create a tuple?
2. What is the most important difference between a list and a tuple?
3. What is the index of the first tuple item?
4. Which function returns the number of items?
5. Which is a correct one-item tuple?
6. Which method counts how many times a value appears?
7. What does tuple unpacking allow you to do?
8. Which operator checks whether an item exists in a tuple?
Python Tuples Summary
A tuple is an ordered collection that cannot be changed after it has been created.
| Concept | Purpose |
|---|---|
| Tuple | Stores an ordered collection of values. |
() |
Common syntax used to create tuples. |
| Indexing | Accesses individual tuple items. |
| Negative indexing | Accesses items from the end. |
| len() | Returns the number of items. |
| Slicing | Extracts part of a tuple. |
| count() | Counts occurrences of a value. |
| index() | Finds the position of a value. |
| in | Checks whether a value exists. |
| Unpacking | Assigns tuple values to variables. |
| Immutable | Tuple items cannot be changed after creation. |
Use a list when you expect the collection to change. Use a tuple when the collection should remain fixed.
Python Sets
You have already learned about lists and tuples. Both allow you to store multiple values in a single variable.
Now we will learn about another Python collection called a set.
A set is useful when you want to store a collection of unique values.
For example, suppose you have:
numbers = [1, 2, 2, 3, 3, 3, 4]
There are duplicate values in this list. A set can automatically keep only the unique values:
numbers = {1, 2, 2, 3, 3, 3, 4}
print(numbers)
The result contains each value only once.
{1, 2, 3, 4}
What Is a Set?
A set is a collection of unique items.
Sets are written using curly braces:
fruits = {"apple", "banana", "orange"}
Unlike lists and tuples, sets do not use numeric indexes to access individual items.
The main reason to use a set is to work with unique values and perform operations such as union, intersection and difference.
Set vs List vs Tuple
It is important to understand how sets differ from the collections you have already learned.
| Feature | List | Tuple | Set |
|---|---|---|---|
| Syntax | [] |
() |
{} |
| Ordered | Yes | Yes | No guaranteed order |
| Changeable | Yes | No | Yes |
| Duplicates | Allowed | Allowed | Not allowed |
| Indexing | Yes | Yes | No |
Creating a Set
You can create a set by placing values inside curly braces.
colors = {"red", "green", "blue"}
You can also create a set containing numbers:
numbers = {10, 20, 30, 40}
Sets can contain values of different data types, provided those values are suitable for use in a set.
data = {"Python", 27, True}
Sets Do Not Allow Duplicates
This is one of the most important characteristics of a set.
numbers = {1, 2, 2, 3, 3, 4}
print(numbers)
Python keeps only one copy of each value.
This makes sets very useful for removing duplicates.
names = ["Ada", "John", "Ada", "Mary", "John"]
unique_names = set(names)
print(unique_names)
The resulting set contains each name only once.
Creating an Empty Set
There is an important detail when creating an empty set.
You cannot use just {} because Python interprets
that as an empty dictionary.
empty = {}
This creates a dictionary, not a set.
To create an empty set, use set():
empty = set()
print(type(empty))
Output:
<class 'set'>
Sets Are Unordered
Sets do not provide a sequence position like lists and tuples.
Therefore, you should not depend on a particular display order when working with a set.
fruits = {"apple", "banana", "orange"}
You should not assume that the items will always be displayed in the order you wrote them.
Accessing Items in a Set
Because sets do not use indexes, you cannot do this:
fruits = {"apple", "banana", "orange"}
print(fruits[0])
That will produce an error.
Instead, you can loop through the set.
for fruit in fruits:
print(fruit)
You can also check whether an item exists using
in.
print("apple" in fruits)
Adding Items with add()
The add() method adds one item to a set.
fruits = {"apple", "banana"}
fruits.add("orange")
print(fruits)
The set now contains the new value.
If you attempt to add a value that is already present, the set remains unchanged.
fruits.add("apple")
There will still be only one "apple".
Adding Multiple Items with update()
Use update() when you want to add multiple
items from another collection.
fruits = {"apple", "banana"}
more_fruits = {"orange", "mango"}
fruits.update(more_fruits)
print(fruits)
You can also update a set using a list:
fruits.update(["pawpaw", "watermelon"])
Any duplicate values are automatically ignored.
Removing Items with remove()
The remove() method removes a specific item.
fruits = {"apple", "banana", "orange"}
fruits.remove("banana")
print(fruits)
If the item does not exist, remove() raises
a KeyError.
Removing Items with discard()
The discard() method also removes an item.
fruits = {"apple", "banana", "orange"}
fruits.discard("banana")
The important difference is what happens if the item does not exist.
discard() does not raise an error when the
value is missing.
fruits.discard("mango")
The program continues normally.
remove() expects the item to exist.
discard() safely does nothing if it does not.
Removing an Item with pop()
Sets also have a pop() method.
However, unlike list pop(), you cannot use an
index with set pop().
fruits = {"apple", "banana", "orange"}
removed = fruits.pop()
print(removed)
print(fruits)
The item removed is not something you should predict from the set's written order.
Removing Everything with clear()
The clear() method removes all items from a set.
fruits = {"apple", "banana", "orange"}
fruits.clear()
print(fruits)
Output:
set()
Deleting a Set with del
The del statement can delete the entire set.
fruits = {"apple", "banana", "orange"}
del fruits
After this, the variable fruits no longer exists.
Checking Membership
The in operator is especially useful with sets.
countries = {"Nigeria", "Ghana", "Kenya"}
print("Nigeria" in countries)
Output:
True
You can also use not in.
print("Canada" not in countries)
Set Union
One of the most useful features of sets is the ability to combine collections while automatically removing duplicates.
This operation is called a union.
set_a = {"apple", "banana", "orange"}
set_b = {"orange", "mango", "pawpaw"}
result = set_a.union(set_b)
print(result)
The result contains values from both sets.
The duplicate "orange" appears only once.
You can also use the | operator:
result = set_a | set_b
Set Intersection
Intersection finds the values that two sets have in common.
set_a = {"apple", "banana", "orange"}
set_b = {"orange", "mango", "banana"}
result = set_a.intersection(set_b)
print(result)
The common values are:
{'banana', 'orange'}
You can also use the & operator:
result = set_a & set_b
Set Difference
Difference finds values that are present in one set but not in another.
set_a = {"apple", "banana", "orange"}
set_b = {"orange", "mango"}
result = set_a.difference(set_b)
print(result)
The result contains values that are in set_a
but not in set_b.
You can also use the - operator:
result = set_a - set_b
Symmetric Difference
Symmetric difference returns values that belong to either set, but not values that belong to both.
set_a = {"apple", "banana", "orange"}
set_b = {"orange", "mango"}
result = set_a.symmetric_difference(set_b)
print(result)
orange is excluded because it appears in both
sets.
The ^ operator can also be used:
result = set_a ^ set_b
Checking for a Subset
A set is a subset of another set when every item in the first set is also contained in the second set.
small_set = {1, 2}
large_set = {1, 2, 3, 4}
print(small_set.issubset(large_set))
Output:
True
You can also use the <= operator.
Checking for a Superset
A set is a superset when it contains every item from another set.
small_set = {1, 2}
large_set = {1, 2, 3, 4}
print(large_set.issuperset(small_set))
Output:
True
Checking for Disjoint Sets
Two sets are disjoint when they have no items in common.
set_a = {1, 2, 3}
set_b = {4, 5, 6}
print(set_a.isdisjoint(set_b))
Output:
True
Looping Through a Set
You can loop through a set using a for loop.
fruits = {"apple", "banana", "orange"}
for fruit in fruits:
print(fruit)
Remember that you should not depend on the order in which the items are printed.
Converting Other Collections into Sets
The set() function can convert another iterable
into a set.
Convert a List
numbers = [1, 2, 2, 3, 3, 4]
unique_numbers = set(numbers)
print(unique_numbers)
Convert a Tuple
numbers = (1, 2, 2, 3, 3, 4)
unique_numbers = set(numbers)
print(unique_numbers)
This is a convenient way to remove duplicate values.
What Is a frozenset?
Python also provides a collection called a
frozenset.
A frozenset behaves like a set but cannot be modified after it has been created.
numbers = frozenset([1, 2, 3, 4])
print(numbers)
You cannot use methods such as add() or
remove() to change a frozenset.
You do not need to master frozensets yet. Just remember that they are an immutable version of a set.
Real-World Examples of Sets
1. Removing Duplicate Names
names = [
"Ada",
"John",
"Ada",
"Mary",
"John"
]
unique_names = set(names)
print(unique_names)
2. Registered Courses
morning_students = {"Ada", "John", "Mary"}
afternoon_students = {"Mary", "David", "Sarah"}
all_students = morning_students | afternoon_students
print(all_students)
The union operation gives us everyone who attended either session without duplicates.
3. Finding Common Interests
python_students = {"Ada", "John", "Mary"}
robotics_students = {"Mary", "David", "John"}
both = python_students & robotics_students
print(both)
The intersection gives students who belong to both groups.
4. Agriculture Example
Imagine collecting crop types from several farms.
farm_a = {"maize", "rice", "cassava"}
farm_b = {"rice", "yam", "cassava"}
common_crops = farm_a & farm_b
print(common_crops)
The intersection shows crops that both farms grow.
Common Beginner Mistakes
1. Trying to access a set using an index
fruits = {"apple", "banana", "orange"}
print(fruits[0])
Sets do not support indexing.
2. Expecting a set to preserve order
Do not build your program around the assumption that a set will display items in the same order you entered them.
3. Using {} when you want an empty set
Remember:
empty = {}
creates a dictionary.
Use:
empty = set()
4. Expecting duplicates
numbers = {1, 1, 2, 2, 3}
print(numbers)
Duplicate values are automatically removed.
5. Confusing remove() and discard()
remove() raises an error if the item does not
exist, while discard() does not.
Practice Exercises
Exercise 1 — Create a Set
Create a set containing five fruits.
Exercise 2 — Duplicates
Create a set containing repeated numbers and observe what happens to the duplicates.
Exercise 3 — Membership
Use in to check whether a particular value
exists in your set.
Exercise 4 — Add
Add two new values using add().
Exercise 5 — Remove
Remove an item using remove().
Exercise 6 — Union
Create two sets of fruits and combine them using union.
Exercise 7 — Intersection
Create two sets of students and find the students who appear in both sets.
Exercise 8 — Difference
Find the values that appear in one set but not the other.
Exercise 9 — Remove Duplicates
Create a list containing duplicate values and convert it into a set.
Mini Project: Unique Student Names
Let's build a small program that removes duplicate student names.
students = [
"Ada",
"John",
"Mary",
"Ada",
"David",
"John",
"Mary"
]
unique_students = set(students)
print("Original names:")
print(students)
print("Unique names:")
print(unique_students)
This demonstrates one of the most practical uses of sets: removing duplicates from a collection.
Try extending the program by allowing the user to enter several names and then displaying only the unique names.
Python Sets Quiz
Test your understanding before moving on.
1. What is one major feature of a set?
2. Which brackets are commonly used for a set?
3. How do you create an empty set?
4. Can you access set items using indexes?
5. Which method adds one item to a set?
6. Which operation finds values common to two sets?
7. What does set() commonly help you do with a list?
8. What is the difference between remove() and discard()?
Python Sets Summary
Sets are collections designed primarily for storing unique values and performing mathematical-style set operations.
| Concept | Purpose |
|---|---|
| Set | Stores unique values. |
{} |
Common syntax for a non-empty set. |
set() |
Creates an empty set or converts an iterable. |
add() |
Adds one item. |
update() |
Adds multiple items. |
remove() |
Removes an item and raises an error if missing. |
discard() |
Removes an item without raising an error if missing. |
clear() |
Removes all items. |
union() |
Combines values from two sets. |
intersection() |
Finds values shared by two sets. |
difference() |
Finds values in one set but not another. |
symmetric_difference() |
Finds values that are in either set but not both. |
issubset() |
Checks whether one set is contained in another. |
issuperset() |
Checks whether one set contains another. |
isdisjoint() |
Checks whether two sets have no values in common. |
Use a set when uniqueness matters or when you need to compare collections using operations such as union, intersection and difference.
Python Dictionaries
So far, you have learned how Python stores collections of data using lists, tuples and sets.
Now we are going to learn one of the most useful and important Python data structures: the dictionary.
Dictionaries allow you to store information using key-value pairs.
Think about a real dictionary. You look up a word and find its meaning. Python dictionaries work in a similar way: you use a key to find its associated value.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
Here:
"name"is a key."Ada"is its value."age"is a key.21is its value."score"is a key.85is its value.
What Is a Dictionary?
A dictionary is a collection of data stored as key-value pairs.
Dictionaries are written using curly braces:
person = {
"name": "Olivia",
"age": 27,
"country": "Nigeria"
}
Each key is separated from its value using a colon
:.
The general structure looks like this:
{
key: value
}
Multiple key-value pairs are separated by commas.
Understanding Key-Value Pairs
The key identifies the information, while the value contains the information itself.
student = {
"name": "Ada",
"age": 21,
"course": "Biology"
}
You can think about this as:
| Key | Value |
|---|---|
| name | Ada |
| age | 21 |
| course | Biology |
The key gives you a way to find the corresponding value.
Creating a Dictionary
You create a dictionary using curly braces
{}.
car = {
"brand": "Toyota",
"model": "Corolla",
"year": 2025
}
You can also create an empty dictionary:
person = {}
Values can be strings, numbers, Boolean values, lists, dictionaries and other Python objects.
student = {
"name": "Ada",
"age": 21,
"passed": True,
"scores": [80, 85, 90]
}
Accessing Dictionary Values
To access a value, use its key inside square brackets.
student = {
"name": "Ada",
"age": 21
}
print(student["name"])
Output:
Ada
You can access the age in the same way:
print(student["age"])
Output:
21
0 and
1. Dictionaries use keys such as
"name" and "age".
Using get()
You can also access dictionary values using the
get() method.
student = {
"name": "Ada",
"age": 21
}
print(student.get("name"))
Output:
Ada
One useful difference is what happens when the key does not exist.
print(student.get("email"))
This returns:
None
You can also provide a default value:
print(student.get("email", "Not provided"))
Output:
Not provided
Changing Dictionary Values
Dictionaries are changeable. You can modify the value associated with an existing key.
student = {
"name": "Ada",
"score": 75
}
student["score"] = 90
print(student)
The score has been changed from 75 to 90.
Adding New Items
To add a new key-value pair, simply assign a value to a new key.
student = {
"name": "Ada",
"age": 21
}
student["course"] = "Biology"
print(student)
The new key "course" has been added.
Removing Items with pop()
The pop() method removes an item using its key.
student = {
"name": "Ada",
"age": 21,
"course": "Biology"
}
student.pop("age")
print(student)
The "age" key and its value are removed.
Removing the Last Inserted Item
The popitem() method removes and returns the
last inserted key-value pair.
student = {
"name": "Ada",
"age": 21,
"course": "Biology"
}
removed = student.popitem()
print(removed)
print(student)
This is useful when you specifically want to remove the last inserted pair.
Deleting Dictionary Items with del
You can use del to remove an item by its key.
student = {
"name": "Ada",
"age": 21
}
del student["age"]
print(student)
You can also delete the entire dictionary.
del student
Removing Everything with clear()
The clear() method removes all items from
the dictionary.
student = {
"name": "Ada",
"age": 21
}
student.clear()
print(student)
Output:
{}
Finding the Length of a Dictionary
Use len() to find the number of key-value pairs.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
print(len(student))
Output:
3
Getting Dictionary Keys
The keys() method returns a view containing
the dictionary's keys.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
print(student.keys())
You can loop through the keys:
for key in student.keys():
print(key)
Getting Dictionary Values
The values() method returns the dictionary's
values.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
for value in student.values():
print(value)
Getting Keys and Values with items()
The items() method allows you to work with
keys and values together.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
for key, value in student.items():
print(key, ":", value)
Output:
name : Ada
age : 21
score : 85
This pattern is extremely useful when processing dictionary data.
Checking Whether a Key Exists
Use the in operator to check whether a key
exists.
student = {
"name": "Ada",
"age": 21
}
print("name" in student)
Output:
True
You can also use not in.
print("email" not in student)
Updating a Dictionary
The update() method can add new key-value pairs
or change existing ones.
student = {
"name": "Ada",
"score": 75
}
student.update({
"score": 90,
"course": "Biology"
})
print(student)
The existing score was updated and the new course was added.
Copying a Dictionary
You can use copy() to create a copy of a
dictionary.
student = {
"name": "Ada",
"score": 85
}
student_copy = student.copy()
print(student_copy)
This creates a separate dictionary object containing the same key-value pairs.
Nested Dictionaries
A dictionary can contain another dictionary.
students = {
"student1": {
"name": "Ada",
"score": 85
},
"student2": {
"name": "John",
"score": 78
}
}
To access Ada's score:
print(students["student1"]["score"])
Output:
85
Nested dictionaries are useful when working with structured information.
Lists Inside Dictionaries
A dictionary can also contain lists.
student = {
"name": "Ada",
"scores": [80, 85, 90]
}
You can access the list:
print(student["scores"])
And access an individual score:
print(student["scores"][0])
Output:
80
Dictionaries with Conditions
Dictionaries become even more useful when combined with conditions.
student = {
"name": "Ada",
"score": 75
}
if student["score"] >= 50:
print("Pass")
else:
print("Fail")
Python gets the student's score from the dictionary and then evaluates the condition.
Looping Through a Dictionary
You can loop through a dictionary in several ways.
Loop Through Keys
student = {
"name": "Ada",
"age": 21,
"score": 85
}
for key in student:
print(key)
Loop Through Values
for value in student.values():
print(value)
Loop Through Both
for key, value in student.items():
print(key, value)
Dictionary Comprehension
Python provides a compact way to create dictionaries called dictionary comprehension.
For example:
squares = {
number: number * number
for number in range(1, 6)
}
print(squares)
Output:
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
If this syntax looks unfamiliar, do not worry. Learn ordinary dictionaries and loops first.
Dictionary Key Rules
Dictionary keys need to be hashable. Common examples include strings, integers and tuples containing suitable values.
data = {
"name": "Ada",
1: "One",
(2, 3): "Coordinates"
}
Lists and other mutable objects cannot be used directly as dictionary keys.
For beginners, strings are usually the easiest and clearest choice for dictionary keys.
Real-World Examples of Dictionaries
1. Student Information
student = {
"name": "Ada",
"age": 21,
"department": "Biology",
"score": 88
}
2. Product Information
product = {
"name": "Laptop",
"price": 850000,
"stock": 12
}
3. Weather Data
weather = {
"temperature": 29,
"humidity": 78,
"condition": "Cloudy"
}
4. Robotics Data
robot = {
"name": "AgriBot",
"battery": 87,
"speed": 1.5,
"active": True
}
A robotics program could use a dictionary to keep related state information together.
5. Agricultural Data
crop = {
"name": "Maize",
"soil_moisture": 42,
"temperature": 28,
"healthy": True
}
This is a simple example of how structured information about a crop could be represented in Python.
Common Beginner Mistakes
1. Forgetting the colon
Every key-value pair needs a colon.
student = {
"name": "Ada",
"age": 21
}
2. Trying to use a list index
Dictionaries are accessed using keys.
student["name"]
3. Accessing a key that does not exist
student["email"]
If the key does not exist, this raises a
KeyError.
If you want a safer lookup, consider:
student.get("email")
4. Confusing keys and values
student = {
"name": "Ada"
}
"name" is the key.
"Ada" is the value.
5. Accidentally replacing a value
student["score"] = 90
If "score" already exists, this changes its value.
If it does not exist, it creates a new key.
Practice Exercises
Exercise 1 — Create a Dictionary
Create a dictionary containing your name, age, country and favorite programming language.
Exercise 2 — Access Values
Print each value using its key.
Exercise 3 — Add a Key
Add a new key called "occupation".
Exercise 4 — Change a Value
Change one of the existing values.
Exercise 5 — Remove an Item
Remove one item using pop().
Exercise 6 — Check a Key
Use in to check whether a particular key exists.
Exercise 7 — Loop Through a Dictionary
Use items() to print every key and value.
Exercise 8 — Student Record
Create a dictionary containing a student's name and five scores stored inside a list.
Exercise 9 — Agricultural Data
Create a dictionary describing a crop. Include the crop name, temperature, soil moisture and whether the crop is healthy.
Mini Project: Student Record
Let's create a small student record using a dictionary.
student = {
"name": "Ada",
"age": 21,
"scores": [78, 85, 91]
}
print("Name:", student["name"])
print("Age:", student["age"])
scores = student["scores"]
print("Scores:", scores)
print("Highest Score:", max(scores))
print("Lowest Score:", min(scores))
print("Total Score:", sum(scores))
print("Average Score:", sum(scores) / len(scores))
Notice how the dictionary stores the student's information, while the list stores multiple scores.
This is an important programming idea: different data structures can work together.
Python Dictionaries Quiz
Test your understanding before moving on.
1. What does a Python dictionary store?
2. Which brackets are commonly used for dictionaries?
3. Which symbol separates a key from its value?
4. How do you access the value associated with the key "name"?
student = {"name": "Ada"}
5. Which method can safely return None when a key does not exist?
6. Which method returns dictionary keys?
7. Which method allows you to loop through keys and values together?
8. What happens when you assign a new value to an existing dictionary key?
Python Dictionaries Summary
Dictionaries organize information using key-value pairs. They are particularly useful when you need to give meaningful names to pieces of data.
| Concept | Purpose |
|---|---|
| Dictionary | Stores data as key-value pairs. |
| Key | Identifies a value. |
| Value | The data associated with a key. |
get() |
Retrieves a value safely. |
keys() |
Returns the dictionary's keys. |
values() |
Returns the dictionary's values. |
items() |
Provides key-value pairs for iteration. |
update() |
Adds or changes key-value pairs. |
pop() |
Removes an item by key. |
popitem() |
Removes the last inserted key-value pair. |
clear() |
Removes all items. |
in |
Checks whether a key exists. |
Use a dictionary when you want to associate meaningful
keys with values. For example, instead of remembering
that index 0 means a student's name, you can simply use
student["name"].
Python Functions
Imagine that you are building a large Python program. As your program grows, you may find yourself writing the same instructions again and again.
This is where functions become extremely useful.
A function allows you to group a set of instructions together, give that group a name, and run it whenever you need it.
def greet():
print("Hello!")
greet()
Instead of writing the print() instruction every time,
we placed it inside a function called greet().
Whenever we want the function to run, we simply call:
greet()
What Is a Function?
A function is a named block of code that performs a specific task.
Think of a function like a machine.
You give the machine some information, the machine performs an operation, and sometimes it gives you a result.
Input → Function → Output
For example, imagine a function that calculates the area of a rectangle.
def rectangle_area(length, width):
return length * width
You can then use it:
area = rectangle_area(10, 5)
print(area)
Output:
50
Why Use Functions?
Functions help you organize your programs and avoid unnecessary repetition.
1. Reuse Code
Write the instructions once and use them multiple times.
2. Make Programs Easier to Understand
A well-named function can tell you what a section of code does.
3. Reduce Repetition
Instead of copying the same code throughout your program, place it inside a function.
4. Make Debugging Easier
When something goes wrong, smaller sections of code are generally easier to inspect.
5. Build Larger Programs
Real applications are often divided into smaller tasks. Functions help you build those tasks separately.
Defining a Function
You create a function using the def keyword.
def greet():
print("Hello!")
Let's break this down.
deftells Python that you are defining a function.greetis the function's name.()contains parameters, if the function has any.:marks the beginning of the function body.- The indented code belongs to the function.
Calling a Function
Defining a function does not automatically execute it.
def greet():
print("Hello!")
Nothing is printed yet.
To execute the function, you call it:
greet()
Output:
Hello!
You can call the same function multiple times.
greet()
greet()
greet()
Output:
Hello!
Hello!
Hello!
Function Parameters
A parameter allows a function to receive information.
def greet(name):
print("Hello", name)
Here, name is a parameter.
When calling the function, provide an argument:
greet("Ada")
Output:
Hello Ada
You can call it with different values:
greet("John")
greet("Mary")
greet("David")
The same function can therefore work with different data.
Parameters vs Arguments
These two terms are related but are not exactly the same.
def greet(name):
print("Hello", name)
name is the parameter.
greet("Ada")
"Ada" is the argument.
Multiple Parameters
A function can have more than one parameter.
def add_numbers(a, b):
print(a + b)
Call the function:
add_numbers(10, 5)
Output:
15
The first argument goes into a, and the second
goes into b.
The return Statement
A function can calculate something and send the result back
using return.
def add(a, b):
return a + b
You can store the returned value:
result = add(10, 5)
print(result)
Output:
15
This is different from simply printing the result.
print() displays something.
return sends a value back to the place where
the function was called.
print() vs return
Beginners often confuse print() and
return.
Using print()
def add(a, b):
print(a + b)
This displays the answer.
Using return
def add(a, b):
return a + b
This gives the result back so you can store it or use it elsewhere.
result = add(10, 5)
double_result = result * 2
print(double_result)
Output:
30
return.
Default Parameters
You can give a parameter a default value.
def greet(name="Guest"):
print("Hello", name)
If you provide a name:
greet("Ada")
Output:
Hello Ada
If you do not provide one:
greet()
Output:
Hello Guest
Keyword Arguments
You can specify arguments using the parameter names.
def introduce(name, age):
print(name, age)
introduce(age=21, name="Ada")
Notice that the arguments were provided in a different order, but Python knows which value belongs to which parameter.
Positional Arguments
When you provide arguments without naming them, their position determines which parameter receives each value.
def introduce(name, age):
print(name, age)
introduce("Ada", 21)
"Ada" goes to name and
21 goes to age.
Using *args
Sometimes you do not know in advance how many positional arguments a function will receive.
Python allows you to use *args.
def add_numbers(*numbers):
total = 0
for number in numbers:
total += number
return total
print(add_numbers(2, 4, 6))
print(add_numbers(1, 2, 3, 4, 5))
The parameter numbers receives the positional
arguments as a tuple.
*args for basic Python programs.
Learn normal parameters first.
Using **kwargs
**kwargs allows a function to accept a variable
number of keyword arguments.
def show_info(**details):
for key, value in details.items():
print(key, ":", value)
show_info(
name="Ada",
age=21,
course="Biology"
)
The collected keyword arguments are stored in a dictionary.
This is a more advanced feature, so focus on ordinary parameters first.
Variable Scope
Variables created inside a function normally belong to that function.
def calculate():
number = 10
print(number)
calculate()
The variable number is local to the function.
You generally cannot access it directly outside the function.
def calculate():
number = 10
calculate()
print(number)
This produces an error because number was created
inside the function.
Global Variables and Functions
A variable created outside a function is generally available to code inside that function.
name = "Ada"
def greet():
print("Hello", name)
greet()
Output:
Hello Ada
However, beginners should avoid relying heavily on global variables. Passing information into functions through parameters is usually clearer.
Functions with Conditions
Functions can contain if, elif and
else statements.
def check_age(age):
if age >= 18:
return "Adult"
else:
return "Minor"
print(check_age(21))
print(check_age(15))
Output:
Adult
Minor
Functions with Loops
Functions can also contain loops.
def count_numbers():
for number in range(1, 6):
print(number)
count_numbers()
This combines two important Python concepts: functions and loops.
Functions with Lists
You can pass a list into a function.
def calculate_total(numbers):
total = 0
for number in numbers:
total += number
return total
scores = [70, 80, 90]
print(calculate_total(scores))
Output:
240
Functions with Dictionaries
Functions can also receive dictionaries.
def show_student(student):
print("Name:", student["name"])
print("Score:", student["score"])
student = {
"name": "Ada",
"score": 85
}
show_student(student)
This is useful when working with structured information.
Returning Multiple Values
Python allows a function to return multiple values.
def calculate(a, b):
total = a + b
difference = a - b
return total, difference
You can store the returned values separately:
total, difference = calculate(10, 4)
print(total)
print(difference)
Output:
14
6
Python packages these returned values together, and you can unpack them into separate variables.
What Happens When a Function Has No return?
If a function does not explicitly return a value, Python
returns None.
def greet():
print("Hello")
result = greet()
print(result)
Output:
Hello
None
The function printed Hello, but it did not return
a value.
Function Documentation
You can place a description inside a function using a docstring.
def add(a, b):
"""Return the sum of two numbers."""
return a + b
A docstring helps explain what the function is designed to do.
Introduction to Recursion
Recursion happens when a function calls itself.
A simple example:
def countdown(number):
if number <= 0:
print("Done!")
return
print(number)
countdown(number - 1)
countdown(5)
Output:
5
4
3
2
1
Done!
Recursion is an advanced concept. You do not need to master it before continuing with the rest of this beginner course.
Introduction to Lambda Functions
Python also provides a short way to create simple anonymous
functions using lambda.
square = lambda number: number * number
print(square(5))
Output:
25
For now, think of lambda functions as a compact form for simple operations.
def are more important
for beginners and should be your primary focus.
Functions in Real-World Programs
Functions are everywhere in real software.
Student Management
def calculate_average(scores):
return sum(scores) / len(scores)
Currency Conversion
def convert_currency(amount, rate):
return amount * rate
Agriculture
def check_soil_moisture(moisture):
if moisture < 30:
return "Water needed"
return "Moisture level okay"
Robotics
def calculate_distance(speed, time):
return speed * time
In a robotics program, you might have separate functions for reading sensors, calculating movement, controlling motors, checking battery levels and processing camera information.
Breaking a large program into functions makes the system much easier to understand and maintain.
Writing Good Functions
A function should ideally have a clear responsibility.
Compare these two ideas:
def process_everything():
...
with:
def calculate_average(scores):
...
def check_pass_mark(score):
...
def display_result(name, result):
...
The second approach makes each task easier to understand.
Common Beginner Mistakes
1. Forgetting to call the function
def greet():
print("Hello!")
Defining the function does not run it.
greet()
2. Forgetting the colon
def greet()
print("Hello")
The function definition needs a colon.
3. Incorrect indentation
def greet():
print("Hello")
The function body must be indented.
4. Providing the wrong number of arguments
def add(a, b):
return a + b
add(5)
The function requires two arguments.
5. Confusing print and return
Remember that displaying a result and returning a result are different operations.
6. Returning too early
def example():
return 10
print("This will not run")
Once Python executes return, the function ends.
7. Creating unnecessarily large functions
If a function becomes difficult to understand, consider breaking it into smaller functions.
Practice Exercises
Exercise 1 — Greeting Function
Create a function called greet() that prints
"Hello, Python!".
Exercise 2 — Personalized Greeting
Create a function that accepts a person's name and prints a greeting.
Exercise 3 — Addition
Create a function that accepts two numbers and returns their sum.
Exercise 4 — Average
Create a function that accepts a list of numbers and returns the average.
Exercise 5 — Even or Odd
Create a function that accepts a number and returns
"Even" if it is even and "Odd"
otherwise.
Exercise 6 — Maximum Number
Create a function that accepts a list and returns its largest value.
Exercise 7 — Student Result
Create a function that accepts a student's score and returns
"Pass" if the score is at least 50 and
"Fail" otherwise.
Exercise 8 — Temperature Conversion
Create a function that converts Celsius to Fahrenheit.
Formula:
Fahrenheit = (Celsius * 9 / 5) + 32
Mini Project: Student Performance Analyzer
Let's combine functions, lists, conditions and basic calculations.
def calculate_total(scores):
return sum(scores)
def calculate_average(scores):
return sum(scores) / len(scores)
def check_result(average):
if average >= 50:
return "Pass"
return "Fail"
scores = [65, 72, 81, 55]
total = calculate_total(scores)
average = calculate_average(scores)
result = check_result(average)
print("Scores:", scores)
print("Total:", total)
print("Average:", average)
print("Result:", result)
Notice how each function has one clear responsibility.
calculate_total()calculates the total.calculate_average()calculates the average.check_result()determines the result.
This is one of the main reasons programmers use functions: a complicated task can be broken into smaller, understandable pieces.
Python Functions Quiz
Test what you have learned.
1. Which keyword is used to define a function?
2. What do you use to execute a function?
3. What does a parameter provide?
4. Which keyword sends a value back from a function?
5. What happens when a function has no explicit return value?
6. What is the difference between print() and return?
7. What does *args collect?
8. Why are functions useful?
Python Functions Summary
| Concept | Purpose |
|---|---|
def |
Defines a function. |
| Function call | Executes a function. |
| Parameter | Receives information inside a function. |
| Argument | The actual value supplied to a parameter. |
return |
Sends a value back from a function. |
| Default parameter | Provides a value when an argument is omitted. |
| Keyword argument | Passes a value using its parameter name. |
*args |
Collects variable positional arguments. |
**kwargs |
Collects variable keyword arguments. |
| Local variable | A variable created inside a function. |
| Docstring | Documents what a function does. |
Functions allow you to break a large program into smaller, reusable pieces. Instead of writing one enormous block of code, you can create functions that each perform a clear task.
As your Python programs become more advanced, functions will become one of the tools you use most frequently.
Python Modules
As your Python programs become larger, putting everything into one file can quickly become difficult to manage.
Imagine building a large agricultural application that contains hundreds or thousands of lines of code. You might have code for calculating data, working with dates, reading files, processing images, communicating with sensors and controlling equipment.
Putting all of that into one file would make the program harder to understand and maintain.
Python solves this problem by allowing you to organize related code into separate files called modules.
math_tools.py
If math_tools.py contains useful functions, another
Python file can import them and use them.
What Is a Module?
A module is simply a Python file with a
.py extension.
For example:
calculator.py
weather.py
students.py
robot.py
crop_data.py
Each file can contain variables, functions, classes and other Python code.
You can then import that code into another Python program.
Why Use Modules?
Modules help you organize your programs and reuse code.
1. Organize Your Code
Related functionality can be placed in its own file.
2. Reuse Code
You can write a function once and use it in multiple programs.
3. Make Programs Easier to Maintain
Smaller files are generally easier to understand than one extremely large file.
4. Avoid Repetition
Instead of copying the same functions into different programs, place them inside a module and import them.
5. Work on Larger Projects
Modules are one of the building blocks used to structure larger Python applications.
Creating Your Own Module
Let's create a simple module.
Create a file called:
math_tools.py
Put the following code inside it:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
You have now created your own Python module.
Importing a Module
To use a module, you can use the import keyword.
Create another file in the same folder:
main.py
Then write:
import math_tools
You can now use functions from the module.
import math_tools
result = math_tools.add(10, 5)
print(result)
Output:
15
The dot:
math_tools.add
means that you are accessing add from the
math_tools module.
Importing Multiple Modules
A program can import more than one module.
import math_tools
import random
You can then use functionality from both modules.
Importing Specific Functions
Instead of importing the entire module name, you can import a specific function.
from math_tools import add
print(add(10, 5))
Now you can call add() directly.
import math_tools requires
math_tools.add(), while
from math_tools import add allows you to use
add() directly.
Importing Multiple Items
You can import more than one function from a module.
from math_tools import add, subtract
print(add(10, 5))
print(subtract(10, 5))
Output:
15
5
Variables Inside Modules
Modules can contain variables as well as functions.
Suppose student_data.py contains:
school = "Gabbywall Academy"
students = 120
Another program can import the module:
import student_data
print(student_data.school)
print(student_data.students)
Python's Built-In Modules
Python comes with many modules that provide useful functionality.
You do not have to create everything yourself.
Some useful examples include:
math— mathematical functions.random— random numbers and selections.datetime— dates and times.os— operating-system related functionality.json— working with JSON data.statistics— statistical calculations.
The math Module
The math module provides additional mathematical
functions.
import math
print(math.sqrt(25))
Output:
5.0
Another example:
import math
print(math.pi)
The module provides many other mathematical tools.
The random Module
The random module is useful when you need
random values or random selections.
import random
number = random.randint(1, 10)
print(number)
The program produces a random integer between 1 and 10, inclusive.
This module can be useful when creating games, simulations, testing programs and other applications.
The datetime Module
Python's datetime module provides tools for
working with dates and times.
from datetime import datetime
now = datetime.now()
print(now)
This retrieves the current date and time from the computer's environment.
Using an Alias
You can give an imported module a shorter name using
as.
import math as m
print(m.sqrt(25))
Here, m is an alias for math.
Aliases can be useful when a module name is long or when a commonly used abbreviation is appropriate.
Using dir()
The dir() function can help you inspect the names
available inside a module or object.
import math
print(dir(math))
Python displays a list of names available in the module.
You do not need to memorize everything that appears. The purpose is to help you explore what is available.
Understanding if __name__ == "__main__"
You will eventually encounter code like this:
if __name__ == "__main__":
print("Program started")
This is commonly used to make code run when a file is executed directly, but not automatically run when the file is imported as a module.
For example:
def greet():
print("Hello")
if __name__ == "__main__":
greet()
When this file is run directly, greet() executes.
When the file is imported into another program, the code inside
the if block does not execute automatically.
Introduction to Packages
As projects become larger, you may need more than a few modules.
Python allows related modules to be organized into packages.
A simple way to think about it is:
Package
│
├── module1.py
├── module2.py
└── module3.py
A package is therefore a way of organizing related Python modules.
Packages become especially important when working with larger applications and external libraries.
Python's Standard Library
Python comes with a large collection of modules that are commonly referred to as the Python Standard Library.
This means that many useful capabilities are already available without you having to install additional packages.
For example:
import math
import random
import datetime
import json
import statistics
Learning how to discover and use these modules will make you much more productive as a Python programmer.
Modules in Real-World Projects
Imagine you are building an agricultural monitoring system.
Instead of placing everything in one file, you could organize your program like this:
agri_system/
│
├── main.py
├── sensors.py
├── soil.py
├── crops.py
├── weather.py
└── reports.py
Each module could have a different responsibility.
sensors.pycould handle sensor readings.soil.pycould process soil information.crops.pycould store crop-related functions.weather.pycould process weather information.reports.pycould generate reports.main.pycould coordinate the application.
This approach keeps the project organized as it grows.
Robotics Example
robot_project/
│
├── main.py
├── motors.py
├── sensors.py
├── navigation.py
├── battery.py
└── camera.py
This type of organization becomes particularly useful when a project starts combining hardware, data processing and decision-making.
Common Beginner Mistakes
1. Misspelling the Module Name
import math_tools
The filename must be correctly named and Python must be able to find it.
2. Putting Files in the Wrong Location
When learning basic modules, keeping your Python files in the same project folder makes things easier.
3. Forgetting the Dot
import math_tools
print(math_tools.add(2, 3))
If you imported the whole module, remember to access its function through the module name.
4. Confusing Module and Function Names
A module and the functions inside that module are different things.
math_tools.add()
Here math_tools is the module and
add() is the function.
5. Naming Your File After a Standard Module
Avoid naming your own file something like
math.py, random.py or
json.py.
Such names can cause confusing import problems because Python may find your file instead of the standard library module you intended to use.
6. Importing Everything Without Understanding It
When learning, understand what you are importing and why you need it.
Practice Exercises
Exercise 1 — Create a Module
Create a file called calculator.py.
Add functions for addition and subtraction.
Exercise 2 — Import the Module
Create main.py and import your calculator module.
Exercise 3 — Import Specific Functions
Import only the addition function from your module.
Exercise 4 — Create a Student Module
Create a module containing a function that calculates the average of a list of scores.
Exercise 5 — Use the math Module
Import math and use sqrt() to find
the square root of 144.
Exercise 6 — Use the random Module
Generate a random number between 1 and 100.
Exercise 7 — Create an Agriculture Module
Create a module called crop_tools.py containing
a function that checks soil moisture.
The function should return "Water needed" when
moisture is below 30 and "Moisture okay"
otherwise.
Mini Project: Modular Student System
Let's create a small project using multiple Python files.
File 1 — student_tools.py
def calculate_total(scores):
return sum(scores)
def calculate_average(scores):
return sum(scores) / len(scores)
def check_result(average):
if average >= 50:
return "Pass"
return "Fail"
File 2 — main.py
import student_tools
scores = [70, 80, 65, 90]
total = student_tools.calculate_total(scores)
average = student_tools.calculate_average(scores)
result = student_tools.check_result(average)
print("Scores:", scores)
print("Total:", total)
print("Average:", average)
print("Result:", result)
The important idea is not the size of this project. The important idea is that we separated reusable functions from the main program.
As your projects become larger, this separation becomes much more valuable.
Python Modules Quiz
1. What is a Python module?
2. Which keyword is commonly used to import a module?
3. If you write import math_tools, how could you call the add function?
4. Which statement imports a specific function?
5. Which module is commonly used for random values?
6. Which module provides mathematical functions such as sqrt()?
7. What is one major benefit of modules?
8. What does the dot in math.sqrt() represent?
Python Modules Summary
| Concept | Purpose |
|---|---|
| Module | A Python file containing reusable code. |
import |
Imports a module. |
from ... import ... |
Imports specific items from a module. |
as |
Creates an alias for an imported module or item. |
dir() |
Helps inspect names available in a module or object. |
| Package | Organizes related Python modules. |
| Standard Library | Collection of modules included with Python. |
Modules allow you to divide a Python program into organized, reusable pieces. Instead of putting everything into one enormous file, you can create separate modules for different responsibilities.
You have now moved from writing individual functions to organizing functions and other code into reusable files.
Python File Handling
So far, most of the Python programs you have written have worked with data temporarily stored in variables, lists, tuples, dictionaries and other objects.
But what happens when you want your program to save information so that it is still available after the program closes?
This is where file handling becomes important.
For example, a student management program could save student records to a file. An agricultural application could save sensor readings. A robotics program could store logs from a robot.
Python Program
↓
File
↓
Saved Information
What Is File Handling?
File handling means using Python to work with files on a computer.
A file might contain:
- Text
- Numbers
- Student records
- Configuration information
- Logs
- Sensor readings
- Reports
Python provides built-in tools that allow you to interact with these files.
Common File Types
You will encounter many different file types while programming.
| Extension | Common Use |
|---|---|
.txt |
Plain text |
.csv |
Tabular data |
.json |
Structured data |
.py |
Python source code |
.log |
Program or system logs |
In this lesson, we will mainly work with text files.
Opening a File
Python provides the open() function for opening
files.
file = open("data.txt")
This tells Python to open a file called
data.txt.
However, simply opening a file is not enough. You also need to decide what you want to do with it.
File Modes
The second argument of open() determines how
the file will be used.
| Mode | Meaning |
|---|---|
"r" |
Read the file |
"w" |
Write to the file |
"a" |
Append to the file |
"x" |
Create a new file |
For beginners, focus first on r,
w and a.
Reading a File
Suppose notes.txt contains:
Python is interesting.
I am learning file handling.
You can read the file using:
file = open("notes.txt", "r")
content = file.read()
print(content)
file.close()
Output:
Python is interesting.
I am learning file handling.
Closing a File
After working with a file, you should close it when using
the basic open() approach.
file = open("notes.txt", "r")
content = file.read()
print(content)
file.close()
Closing the file tells Python that you are finished working with it.
with open(...), which automatically handles
closing the file.
Using with open()
A cleaner and safer way to work with files is to use the
with statement.
with open("notes.txt", "r") as file:
content = file.read()
print(content)
When the with block finishes, Python takes care
of closing the file.
This is the style you should become comfortable using.
The read() Method
The read() method reads the contents of a file.
with open("notes.txt", "r") as file:
content = file.read()
print(content)
You can also specify how many characters to read.
with open("notes.txt", "r") as file:
content = file.read(10)
print(content)
This reads up to 10 characters.
The readline() Method
The readline() method reads one line at a time.
with open("notes.txt", "r") as file:
first_line = file.readline()
print(first_line)
You can call it again to read the next line.
with open("notes.txt", "r") as file:
print(file.readline())
print(file.readline())
The readlines() Method
The readlines() method reads the lines and returns
them as a list.
with open("notes.txt", "r") as file:
lines = file.readlines()
print(lines)
For example, the result might look like:
[
"Python is interesting.\n",
"I am learning file handling.\n"
]
Looping Through a File
You can loop through a file one line at a time.
with open("notes.txt", "r") as file:
for line in file:
print(line)
This approach is useful when working with files containing many lines of information.
Writing to a File
Use "w" when you want to write content to a file.
with open("notes.txt", "w") as file:
file.write("Hello from Python!")
If the file does not exist, Python can create it.
If the file already contains information, writing with
"w" replaces its existing contents.
Writing Multiple Lines
You can write multiple lines using newline characters.
with open("notes.txt", "w") as file:
file.write("Python\n")
file.write("JavaScript\n")
file.write("C++\n")
The \n character moves the next text to a new line.
Appending to a File
Use "a" when you want to add information to the
end of an existing file without replacing its contents.
with open("notes.txt", "a") as file:
file.write("\nAnother line.")
This adds the new content after the existing content.
Creating a New File
The "x" mode can be used to create a new file.
with open("new_file.txt", "x") as file:
file.write("This is a new file.")
If the file already exists, Python raises an error rather than replacing it.
Checking Whether a File Exists
The os module provides tools for interacting
with the operating system.
import os
if os.path.exists("notes.txt"):
print("File exists")
else:
print("File does not exist")
This can help your program avoid trying to work with a file that is not available.
Deleting a File
Python can also delete files.
import os
if os.path.exists("notes.txt"):
os.remove("notes.txt")
Understanding File Paths
A file path tells Python where a file is located.
A simple filename:
"notes.txt"
refers to a file Python can find from the program's current working location.
You can also work with files inside folders.
"data/notes.txt"
When working with paths in larger programs, Python's
pathlib module provides a modern and convenient
way to handle paths.
Introduction to pathlib
Python provides the pathlib module for working
with filesystem paths.
from pathlib import Path
file_path = Path("notes.txt")
if file_path.exists():
print("The file exists")
You can also read a small text file using:
from pathlib import Path
content = Path("notes.txt").read_text()
print(content)
pathlib becomes particularly useful when working
with files and folders across different operating systems.
File Encoding
Text files are stored using character encodings.
UTF-8 is a common choice for text files.
You can explicitly specify it when opening a text file.
with open("notes.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
Being explicit about encoding can help your program correctly handle a wide range of characters and languages.
Common File Errors
File operations can fail for several reasons.
FileNotFoundError
This occurs when Python tries to open a file that cannot be found.
with open("missing.txt", "r") as file:
content = file.read()
PermissionError
This can happen when your program does not have permission to perform the requested operation.
IsADirectoryError
This can occur when code expecting a file is given a directory instead.
You will learn how to handle these errors properly in the next major section on Errors and Exceptions.
Saving Dictionary Information
You can convert information into text and save it to a file.
student = {
"name": "Ada",
"age": 21,
"score": 85
}
with open("student.txt", "w") as file:
file.write("Name: " + student["name"] + "\n")
file.write("Age: " + str(student["age"]) + "\n")
file.write("Score: " + str(student["score"]))
Notice that numbers are converted to strings before being combined with text.
File Handling in Real-World Programs
File handling becomes particularly useful when your program needs to preserve information between executions.
Student Management System
A program could save student records to a file.
Application Logs
with open("app.log", "a") as file:
file.write("Program started\n")
Agricultural Monitoring
soil_moisture = 42
with open("sensor_log.txt", "a") as file:
file.write("Soil moisture: " + str(soil_moisture) + "\n")
Robotics
battery = 87
speed = 1.5
with open("robot_log.txt", "a") as file:
file.write(
"Battery: " + str(battery) +
"%, Speed: " + str(speed) +
"\n"
)
A real robot could generate thousands of sensor readings. Saving those readings allows you to inspect them later.
Introduction to CSV Files
CSV stands for Comma-Separated Values.
CSV files are commonly used to store tabular data.
Name,Age,Score
Ada,21,85
John,22,78
Mary,20,91
Python provides the built-in csv module for
working with CSV files.
import csv
with open("students.csv", "r", newline="") as file:
reader = csv.reader(file)
for row in reader:
print(row)
CSV files are especially useful when working with datasets and spreadsheet-style information.
Introduction to JSON Files
JSON is another common format for storing structured data.
{
"name": "Ada",
"age": 21,
"score": 85
}
Python provides the json module for working
with JSON data.
import json
student = {
"name": "Ada",
"age": 21,
"score": 85
}
with open("student.json", "w") as file:
json.dump(student, file, indent=4)
JSON becomes especially important when applications need to exchange structured data.
Common Beginner Mistakes
1. Forgetting the File Name
open("notes.txt", "r")
Make sure the filename and path are correct.
2. Using the Wrong Mode
Remember:
rreads.wwrites and can replace existing content.aadds content to the end.xcreates a new file.
3. Accidentally Overwriting a File
with open("important.txt", "w") as file:
file.write("New content")
Using w can replace existing content.
4. Forgetting to Convert Numbers to Strings
age = 21
with open("student.txt", "w") as file:
file.write(age)
This does not work because write() expects text.
Convert the number:
file.write(str(age))
5. Not Handling Missing Files
A program should account for the possibility that a file does not exist.
6. Using Complicated Paths Without Understanding Them
When learning, start with simple project folders and gradually learn more advanced path handling.
Practice Exercises
Exercise 1 — Create a File
Create a file called hello.txt and write
"Hello Python!" into it.
Exercise 2 — Read the File
Write a program that reads hello.txt and prints
its contents.
Exercise 3 — Add Another Line
Use append mode to add another sentence without deleting the existing content.
Exercise 4 — Student File
Create a text file containing a student's name, age and score.
Exercise 5 — Count Lines
Create a program that opens a text file and counts how many lines it contains.
Exercise 6 — Sensor Log
Create a program that asks for a temperature and appends the reading to a file.
Exercise 7 — Check a File
Use os.path.exists() to check whether a file
exists before trying to open it.
Exercise 8 — CSV Practice
Create a CSV file containing three students and their scores. Use Python to read and print each row.
Mini Project: Simple Notes App
Let's build a very small notes application.
The program will allow the user to type a note and save it to a file.
note = input("Enter your note: ")
with open("notes.txt", "a") as file:
file.write(note + "\n")
print("Note saved successfully.")
Every time you run the program, the new note is added to the file instead of replacing the previous notes.
Reading the Notes
with open("notes.txt", "r") as file:
for line in file:
print(line.strip())
You now have the foundation of a simple persistent notes application.
The important concept is that the information survives after the Python program closes because it has been stored in a file.
Python File Handling Quiz
1. Which function is commonly used to open a file?
2. Which mode is used to read a file?
3. Which mode can overwrite existing file content?
4. Which mode adds content to the end of a file?
5. What does read() do?
6. Why is with open() useful?
7. Which module can be used to check whether a file exists?
8. What does CSV commonly represent?
Python File Handling Summary
| Concept | Purpose |
|---|---|
open() |
Opens a file. |
"r" |
Reads a file. |
"w" |
Writes to a file and can replace its contents. |
"a" |
Appends content to a file. |
"x" |
Creates a new file. |
read() |
Reads file content. |
readline() |
Reads one line. |
readlines() |
Reads lines into a list. |
write() |
Writes text into a file. |
os.path.exists() |
Checks whether a path exists. |
os.remove() |
Removes a file. |
pathlib |
Provides modern tools for working with paths. |
csv |
Works with CSV data. |
json |
Works with JSON data. |
Variables hold data while your program is running. Files allow your program to store information so it can be used again later.
This is an important step toward building useful applications. Once your programs can save and retrieve information, they can start behaving more like real-world software.
Python Errors & Exceptions
When you write Python programs, your code will not always work perfectly on the first attempt.
You may misspell something, use the wrong type of data, try to open a file that does not exist, or perform an operation that Python cannot complete.
Python responds to these problems by producing errors or exceptions.
What Is an Error?
An error is a problem in your program that prevents Python from doing what you asked it to do.
For example:
print("Hello"
The closing parenthesis is missing, so Python cannot correctly understand the instruction.
Python will report the problem instead of pretending that everything is fine.
Why Do Errors Matter?
Learning programming does not mean learning how to write code without ever making mistakes.
In real programming, errors are normal.
The important skill is learning how to:
- Recognize what went wrong.
- Read the error message.
- Find the part of the program causing the problem.
- Fix the underlying issue.
- Handle expected problems gracefully.
Error messages are therefore not your enemy. They are clues from Python.
Syntax Errors
A syntax error happens when Python cannot understand the structure of your code.
Think of syntax as the grammar of Python.
For example:
if age >= 18
print("Adult")
The colon after the condition is missing.
The correct version is:
if age >= 18:
print("Adult")
Indentation Errors
Python uses indentation to determine which statements belong to a block of code.
For example:
if age >= 18:
print("You are an adult.")
If the indentation is missing or inconsistent, Python may raise an indentation-related error.
if age >= 18:
print("You are an adult.")
The print() statement needs to be indented.
NameError
A NameError commonly occurs when you try to use
a variable or name that Python does not know.
name = "Olivia"
print(username)
Python knows about name, but not
username.
A common cause is simply spelling a variable incorrectly.
student_name = "Ada"
print(student_nam)
The names are different, so Python cannot find the second one.
TypeError
A TypeError occurs when an operation is not valid
for the type of data being used.
For example:
age = 20
print("Age: " + age)
You are trying to combine a string and an integer using string concatenation.
One solution is to convert the number to a string:
age = 20
print("Age: " + str(age))
Another common approach is an f-string:
age = 20
print(f"Age: {age}")
ValueError
A ValueError can occur when the type of operation
is valid but the value provided is inappropriate.
For example:
number = int("hello")
Python knows how to convert a string containing digits into
an integer, but "hello" is not a valid integer.
Another example:
number = int("25")
This works because "25" represents a valid integer.
ZeroDivisionError
Python cannot divide a number by zero.
result = 10 / 0
This produces a ZeroDivisionError.
This is particularly important when your program receives numbers from users or external data.
IndexError
An IndexError can happen when you try to access
a list position that does not exist.
fruits = ["apple", "banana", "orange"]
print(fruits[5])
The list has indexes 0, 1 and 2. Index 5 does not exist.
KeyError
A KeyError can occur when you try to access a
dictionary key that does not exist.
student = {
"name": "Ada",
"score": 85
}
print(student["age"])
There is no "age" key in the dictionary.
You can avoid this particular problem by using
get() when appropriate.
print(student.get("age"))
If the key is missing, this returns None by
default instead of raising a KeyError.
FileNotFoundError
You may encounter this error when your program tries to open a file that cannot be found.
with open("missing.txt", "r") as file:
content = file.read()
If missing.txt does not exist in the expected
location, Python raises a FileNotFoundError.
What Is an Exception?
An exception is a problem that occurs while a Python program is running.
For example:
number = int(input("Enter a number: "))
If the user enters:
hello
Python cannot convert that text into an integer and raises a
ValueError.
Instead of allowing the program to stop abruptly, you can handle the expected exception.
The try and except Statements
The try block contains code that might produce
an exception.
The except block tells Python what to do if a
particular exception occurs.
try:
number = int(input("Enter a number: "))
print(number)
except ValueError:
print("Please enter a valid number.")
If the user enters 25, the conversion succeeds.
If the user enters hello, Python executes the
except block.
Handle Specific Exceptions
It is generally better to catch the specific exception you expect.
try:
number = int(input("Enter a number: "))
except ValueError:
print("That is not a valid integer.")
This is more informative than catching every possible exception without knowing what happened.
Handling Multiple Exceptions
A program can have more than one except block.
try:
number = int(input("Enter a number: "))
result = 100 / number
print(result)
except ValueError:
print("Please enter a valid number.")
except ZeroDivisionError:
print("You cannot divide by zero.")
Different problems can therefore receive different responses.
Getting Information About an Exception
You can store the exception in a variable using
as.
try:
number = int("hello")
except ValueError as error:
print("Something went wrong:")
print(error)
This can be useful while debugging because the exception object contains information about the problem.
The else Statement
You can use else when you want some code to run
only if no exception occurred.
try:
number = int(input("Enter a number: "))
except ValueError:
print("Invalid number.")
else:
print("You entered:", number)
The else block runs only when the
try block succeeds.
The finally Statement
The finally block runs whether an exception
occurs or not.
try:
print("Program is running.")
except Exception:
print("An error occurred.")
finally:
print("This message runs either way.")
This can be useful for cleanup operations.
try + except + else + finally
Python allows these parts to work together.
try:
number = int(input("Enter a number: "))
except ValueError:
print("Invalid number.")
else:
print("Number accepted:", number)
finally:
print("Finished.")
Remember the general flow:
try— attempt the operation.except— respond if an exception occurs.else— run if no exception occurs.finally— run regardless of the result.
Raising an Exception
Sometimes you want your own program to deliberately signal that something is wrong.
Python provides the raise statement for this.
age = -5
if age < 0:
raise ValueError("Age cannot be negative.")
Here, the program detects an invalid value and raises a
ValueError.
You will use this technique more as you start building larger programs.
Handling Invalid User Input
User input is one of the most common places where exceptions can occur.
Consider a program that asks for someone's age.
age = int(input("Enter your age: "))
If the user enters letters instead of a number, the program can fail.
A safer version is:
try:
age = int(input("Enter your age: "))
print("Your age is:", age)
except ValueError:
print("Please enter your age as a number.")
Using Exceptions with Loops
You can combine exception handling with loops to keep asking the user until valid information is provided.
while True:
try:
age = int(input("Enter your age: "))
break
except ValueError:
print("Please enter a valid number.")
print("Your age is:", age)
The loop continues when the user enters invalid information.
Once a valid number is entered, break ends the
loop.
This is a useful pattern for building interactive programs.
Using Errors to Debug Your Code
Debugging means finding and fixing problems in a program.
When Python gives you an error, do not immediately panic. Read the message carefully.
A typical traceback gives you useful information such as:
- The type of exception.
- The line where the problem occurred.
- The operation Python was attempting.
- Additional information about the problem.
For example:
ValueError: invalid literal for int()
The important part is ValueError. It tells you
what kind of problem Python encountered.
Why You Should Avoid a Bare except
You may sometimes see:
try:
risky_code()
except:
print("Something went wrong.")
This catches a very broad range of problems and can make debugging more difficult.
When possible, catch the specific exception you expect.
try:
number = int(input("Enter a number: "))
except ValueError:
print("Please enter a valid number.")
This makes your program easier to understand and maintain.
Custom Exceptions
Python also allows developers to create custom exception classes.
You do not need this technique for beginner programs, but it is useful to know that it exists.
class InvalidScoreError(Exception):
pass
You could then raise your custom exception when appropriate.
score = 120
if score > 100:
raise InvalidScoreError("Score cannot be greater than 100.")
Custom exceptions become more useful in larger applications where you want errors to clearly represent your application's own rules.
Errors & Exceptions in Real-World Programs
Exception handling is not just something you learn for programming exercises.
Real applications constantly deal with unexpected situations.
Student Management System
A student may enter a score such as:
abc
Your program can catch the invalid input instead of crashing.
File-Based Applications
A file might have been deleted or moved.
try:
with open("students.txt", "r") as file:
data = file.read()
except FileNotFoundError:
print("The student file could not be found.")
Agricultural Systems
An agricultural application may receive unexpected sensor values or missing data.
Exception handling can help the application respond safely instead of stopping completely.
Robotics
A robotics program may communicate with hardware, read sensor data or process files. Problems can occur during any of these operations.
Proper error handling allows the software to detect certain problems and respond appropriately.
Common Beginner Mistakes
1. Ignoring the Error Message
Do not simply delete the line producing the error without understanding why it happened.
2. Catching Every Exception
Avoid using a broad except: when a specific
exception is appropriate.
3. Putting Too Much Code Inside try
Keep the try block focused on the operation that
might actually fail.
4. Using Exceptions Instead of Basic Logic
Exception handling is useful, but it should not replace ordinary validation and sensible program logic.
5. Thinking Errors Mean You Are Bad at Programming
Errors are part of programming.
Experienced developers encounter errors every day. The difference is that they have learned how to investigate and solve them.
Practice Exercises
Exercise 1 — Find the Syntax Error
if score > 50
print("Pass")
Find and correct the problem.
Exercise 2 — Handle Invalid Numbers
Ask the user to enter a number. Use try and
except to handle invalid input.
Exercise 3 — Division Calculator
Ask the user for two numbers and divide the first by the second.
Handle both invalid numbers and division by zero.
Exercise 4 — Safe File Reading
Try to open a file and handle FileNotFoundError
if the file does not exist.
Exercise 5 — List Index
Create a list and ask the user for an index. Handle an
IndexError if the index is outside the list.
Exercise 6 — Dictionary Lookup
Create a dictionary and ask the user for a key. Handle the situation where the key does not exist.
Exercise 7 — Keep Asking
Use a while loop and exception handling to keep
asking for a number until the user enters a valid one.
Mini Project: Safe Number Calculator
Let's build a small calculator that handles common input problems.
while True:
try:
first = float(input("Enter the first number: "))
second = float(input("Enter the second number: "))
result = first / second
print("Result:", result)
break
except ValueError:
print("Please enter valid numbers.")
except ZeroDivisionError:
print("The second number cannot be zero.")
Notice how the program does not immediately crash when the user enters invalid information.
Instead, it explains the problem and gives the user another opportunity.
Improve the program so the user can choose between addition, subtraction, multiplication and division.
Then add exception handling for invalid menu choices and invalid numbers.
Python Errors & Exceptions Quiz
1. What does a syntax error usually mean?
2. Which exception commonly occurs when converting invalid text to an integer?
3. Which exception occurs when dividing by zero?
4. Which block contains code that might raise an exception?
5. What does except do?
6. When does an else block in try/except normally run?
7. Which block is designed to run whether an exception occurs or not?
8. Which exception can occur when accessing a list index that does not exist?
Python Errors & Exceptions Summary
| Concept | Meaning |
|---|---|
| SyntaxError | Python cannot understand the structure of the code. |
| IndentationError | Indentation is missing or incorrect. |
| NameError | A name or variable cannot be found. |
| TypeError | An operation is not valid for the given data types. |
| ValueError | The value provided is inappropriate for the operation. |
| ZeroDivisionError | An attempt was made to divide by zero. |
| IndexError | A list or sequence index does not exist. |
| KeyError | A dictionary key does not exist. |
| FileNotFoundError | A requested file could not be found. |
try |
Contains code that might raise an exception. |
except |
Handles an exception. |
else |
Runs when the try block succeeds. |
finally |
Runs whether an exception occurs or not. |
raise |
Manually raises an exception. |
Errors are part of programming. Your goal is not to eliminate every possible error. Your goal is to understand what went wrong, fix your code, and handle expected problems properly.
Once you understand errors and exceptions, your programs can become much more reliable and easier to use.
Python Classes & Objects
You have now learned variables, data types, operators, conditions, loops, strings, lists, tuples, sets, dictionaries, functions, modules, file handling, and exception handling.
Now we are going to introduce one of the most important ideas in Python: Object-Oriented Programming, commonly called OOP.
OOP allows you to organize programs around objects that contain both data and behavior.
For example, imagine you are building a program for a farm. You might have many sensors.
Instead of writing separate variables and functions for every sensor, you could create a Sensor class and then create many sensor objects from it.
What Is Object-Oriented Programming?
Object-Oriented Programming is a way of organizing software around objects.
An object can contain:
- Data that describes it.
- Functions that describe what it can do.
In OOP, the data inside an object is commonly represented by attributes, while functions associated with an object are called methods.
For example, a student object might have:
- Name
- Age
- Score
And it might have methods such as:
- Display information
- Calculate a grade
- Update a score
What Is a Class?
A class is a blueprint or template used to create objects.
Think about a building blueprint.
The blueprint describes how the building should be structured, but the blueprint itself is not the building.
Similarly, a class describes what an object should contain, while the actual object is created from that class.
class Student:
pass
This creates a class called Student.
The pass statement simply tells Python that we
intentionally have nothing else inside the class yet.
What Is an Object?
An object is an instance of a class.
Once you create a class, you can create objects from it.
class Student:
pass
student1 = Student()
student2 = Student()
Here, student1 and student2 are two
separate objects created from the same class.
Attributes
Attributes are pieces of data that belong to an object.
For example:
class Student:
pass
student = Student()
student.name = "Ada"
student.age = 21
student.score = 85
print(student.name)
print(student.age)
print(student.score)
The object now has three attributes:
nameagescore
Although this works, there is a better way to initialize objects.
The __init__() Method
The __init__() method is commonly used to
initialize an object when it is created.
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
Now you can create a student like this:
student1 = Student("Ada", 21, 85)
print(student1.name)
print(student1.age)
print(student1.score)
When Student() is called, Python runs the
__init__() method to initialize the object.
What Is self?
You will see the word self frequently when
working with Python classes.
self refers to the particular object currently
being worked with.
class Student:
def __init__(self, name):
self.name = name
When you create:
student1 = Student("Ada")
self.name refers to the name
belonging to that particular student object.
If you create another object:
student2 = Student("John")
student2.name contains "John",
while student1.name contains "Ada".
Methods
A method is a function that belongs to a class or object.
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def introduce(self):
print(f"My name is {self.name}.")
student = Student("Ada", 85)
student.introduce()
The introduce() method belongs to the
Student class.
You call it using the object:
student.introduce()
Methods Can Work With Attributes
One of the strengths of OOP is that methods can operate on the object's own data.
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def show_score(self):
print(f"{self.name} scored {self.score}.")
student = Student("Ada", 85)
student.show_score()
The method accesses the attributes belonging to that object.
Changing Object Attributes
Object attributes can be changed after the object has been created.
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
student = Student("Ada", 85)
student.score = 92
print(student.score)
The score changes from 85 to 92.
Methods Can Change Object Data
You can also create methods that modify attributes.
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def update_score(self, new_score):
self.score = new_score
student = Student("Ada", 85)
student.update_score(95)
print(student.score)
This keeps the operation inside the class.
Creating Multiple Objects
One class can be used to create many objects.
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
student1 = Student("Ada", 85)
student2 = Student("John", 78)
student3 = Student("Mary", 91)
print(student1.name)
print(student2.name)
print(student3.name)
All three objects follow the same class structure, but each object contains its own data.
Default Values in Classes
You can give an attribute a default value.
class Student:
def __init__(self, name, score=0):
self.name = name
self.score = score
student = Student("Ada")
print(student.score)
Because no score was provided, Python uses the default value
of 0.
Class Variables
A class variable is shared by objects created from the class.
class Student:
school = "Python Academy"
def __init__(self, name):
self.name = name
student1 = Student("Ada")
student2 = Student("John")
print(student1.school)
print(student2.school)
Both objects can access the same class variable.
This is different from an instance attribute such as
self.name, which normally belongs to a particular
object.
Instance Variables vs Class Variables
| Type | Meaning |
|---|---|
| Instance variable | Usually belongs to one specific object. |
| Class variable | Shared at the class level. |
class Student:
school = "Python Academy"
def __init__(self, name):
self.name = name
Here, school is a class variable while
name is an instance variable.
Inheritance
Inheritance allows one class to inherit attributes and methods from another class.
Think of it as creating a more specialized version of an existing class.
For example, imagine a general class called
Animal.
class Animal:
def speak(self):
print("The animal makes a sound.")
Another class can inherit from it:
class Dog(Animal):
pass
dog = Dog()
dog.speak()
The Dog class inherits the
speak() method from Animal.
Parent and Child Classes
The class being inherited from is commonly called the parent class or base class.
The class doing the inheriting is commonly called the child class or derived class.
class Vehicle:
def move(self):
print("The vehicle is moving.")
class Car(Vehicle):
pass
Here:
Vehicleis the parent class.Caris the child class.
Adding Methods to a Child Class
A child class can have its own methods in addition to the methods inherited from its parent.
class Vehicle:
def move(self):
print("Vehicle is moving.")
class Car(Vehicle):
def honk(self):
print("Beep beep!")
car = Car()
car.move()
car.honk()
The object can use both the inherited method and its own method.
The super() Function
The super() function can be used to call behavior
from a parent class.
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
dog = Dog("Max", "Labrador")
print(dog.name)
print(dog.breed)
super() allows the child class to use the parent
class's initialization logic.
Method Overriding
A child class can provide its own version of a method inherited from the parent class.
class Animal:
def speak(self):
print("Some animal sound.")
class Dog(Animal):
def speak(self):
print("Woof!")
dog = Dog()
dog.speak()
The Dog class replaces the inherited behavior of
speak() with its own version.
Polymorphism
Polymorphism means that different objects can respond to the same method name in different ways.
class Dog:
def speak(self):
print("Woof!")
class Cat:
def speak(self):
print("Meow!")
animals = [Dog(), Cat()]
for animal in animals:
animal.speak()
Both objects have a speak() method, but each
object performs it differently.
You do not always need to know the exact object type before calling the method.
Encapsulation
Encapsulation is the idea of keeping related data and behavior together and controlling how the internal state of an object is accessed or changed.
Python does not enforce strict private fields in the same way some languages do, but naming conventions and properties can help communicate intended access.
You may see a leading underscore:
class BankAccount:
def __init__(self, balance):
self._balance = balance
The underscore convention communicates that
_balance is intended for internal use.
Properties
A property allows you to control access to an attribute while keeping a simple attribute-like interface.
class Student:
def __init__(self, score):
self._score = score
@property
def score(self):
return self._score
Properties become especially useful when you need validation or controlled access to data.
This is an advanced OOP feature, so do not worry if it feels unfamiliar at first.
The __str__() Method
Python provides special methods with names surrounded by double underscores. These are often called dunder methods.
One useful example is __str__().
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __str__(self):
return f"{self.name}: {self.score}"
student = Student("Ada", 85)
print(student)
The __str__() method defines a readable string
representation of the object.
Other Special Methods
Python contains many special methods that allow objects to interact naturally with built-in operations.
Examples include:
__init__()— initialization.__str__()— readable string representation.__len__()— behavior forlen().__eq__()— behavior for equality comparison.
You do not need to memorize all special methods now. Learn them as you encounter situations where they are useful.
Composition
Another useful OOP idea is composition.
Composition means creating an object that contains another object.
For example, a robot can contain a sensor.
class Sensor:
def read(self):
return 42
class Robot:
def __init__(self):
self.sensor = Sensor()
robot = Robot()
print(robot.sensor.read())
The Robot object contains a
Sensor object.
Composition is very useful when modeling systems made of multiple components.
Agricultural Example
Suppose you are developing an agricultural monitoring system.
You could represent a farm sensor using a class.
class SoilSensor:
def __init__(self, location):
self.location = location
self.moisture = 0
def update_moisture(self, value):
self.moisture = value
def show_reading(self):
print(
f"{self.location}: "
f"{self.moisture}% soil moisture"
)
sensor1 = SoilSensor("Field A")
sensor1.update_moisture(42)
sensor1.show_reading()
Now you can create another sensor without rewriting the entire structure.
sensor2 = SoilSensor("Field B")
sensor2.update_moisture(67)
sensor2.show_reading()
This is one reason OOP becomes powerful for larger projects.
Robotics Example
A robot can also be represented as an object.
class Robot:
def __init__(self, name):
self.name = name
self.battery = 100
def move(self):
print(f"{self.name} is moving.")
def show_battery(self):
print(f"Battery: {self.battery}%")
robot = Robot("AgriBot")
robot.move()
robot.show_battery()
As your robotics knowledge grows, this basic idea can be expanded to represent motors, sensors, batteries and other components.
When Should You Use a Class?
Not every small Python program needs a class.
For a tiny calculation, a few variables and functions may be enough.
Classes become particularly useful when:
- Your program has many related pieces of data.
- You need many similar objects.
- Objects have their own behavior.
- Your application is becoming larger.
- You want to organize complex systems.
Common Beginner Mistakes
1. Forgetting self
Instance methods normally need self as their
first parameter.
class Student:
def show_name(self):
print(self.name)
2. Confusing a Class With an Object
The class is the blueprint. The object is an instance created from that blueprint.
3. Forgetting Parentheses When Creating an Object
student = Student()
You normally create an instance by calling the class.
4. Forgetting self When Accessing Attributes
class Student:
def __init__(self, name):
self.name = name
The attribute belongs to the object, so it is accessed using
self.name inside the instance method.
5. Making Every Program a Class
Classes are useful, but they are not required for every small script.
Practice Exercises
Exercise 1 — Create a Person Class
Create a class called Person with a name and age.
Exercise 2 — Add a Method
Add a method called introduce() that prints the
person's name and age.
Exercise 3 — Student Class
Create a Student class with:
- Name
- Course
- Score
Add a method that displays the student's information.
Exercise 4 — Bank Account
Create a BankAccount class with a balance.
Add methods for depositing and withdrawing money.
Exercise 5 — Farm Sensor
Create a Sensor class with a location and
moisture value.
Add a method that displays the sensor reading.
Exercise 6 — Robot
Create a Robot class with a name and battery
level.
Add methods to move and display the battery level.
Exercise 7 — Inheritance
Create a parent class called Animal and a child
class called Dog.
Give the parent a method and allow the child to inherit it.
Mini Project: Agricultural Sensor Manager
Let's combine classes and objects into a small agricultural monitoring example.
class Sensor:
def __init__(self, location, moisture):
self.location = location
self.moisture = moisture
def show_reading(self):
print(
f"Location: {self.location}"
)
print(
f"Soil moisture: {self.moisture}%"
)
def update_moisture(self, new_value):
self.moisture = new_value
sensor1 = Sensor("Field A", 35)
sensor1.show_reading()
sensor1.update_moisture(48)
print("Updated reading:")
sensor1.show_reading()
Now create another sensor:
sensor2 = Sensor("Field B", 72)
sensor2.show_reading()
Notice that we did not need to rewrite the class.
We simply created another object from the same blueprint.
Add a temperature attribute to the sensor.
Then create a method called
show_all_readings() that displays both
moisture and temperature.
Python Classes & Objects Quiz
1. What is a class?
2. What is an object?
3. Which method is commonly used to initialize an object?
4. What does self usually refer to?
5. What is a method?
6. What does inheritance allow?
7. Which function is commonly used to access parent-class behavior?
8. What is an attribute?
Python Classes & Objects Summary
| Concept | Meaning |
|---|---|
| Class | A blueprint used to create objects. |
| Object | An instance created from a class. |
| Attribute | Data associated with an object. |
| Method | A function associated with a class or object. |
__init__() |
Commonly used to initialize objects. |
self |
Refers to the current object in an instance method. |
| Inheritance | Allows a class to inherit from another class. |
super() |
Provides access to parent-class behavior. |
| Polymorphism | Allows different objects to respond to the same operation in different ways. |
| Encapsulation | Organizes and controls access to an object's data and behavior. |
| Composition | Builds objects using other objects as components. |
Classes allow you to create reusable blueprints, while objects allow you to create individual instances of those blueprints.
This becomes especially powerful when building larger systems such as agricultural applications, robotics software, management systems and other complex programs.
17. Python Date & Time
Programs often need to work with dates and times. For example, a program may need to record when a user registered, calculate someone's age, determine how many days remain until an event, or display the current date and time.
Python provides the built-in datetime module for working with
dates and times.
- How Python represents dates and times
- How to get the current date and time
- How to create specific dates
- How to access parts of a date
- How to format dates and times
- How to compare dates
- How to calculate differences between dates
- How to work with time intervals
- How to build practical date and time programs
Python Date & Time: Introduction
Python does not treat a date such as September 5, 2026 as
ordinary text when you use the datetime module.
Instead, Python can represent the date as a structured object containing information such as the year, month and day.
This makes it possible to perform operations on dates rather than simply displaying them.
For example, Python can help you answer questions such as:
- What is today's date?
- What time is it?
- What date will it be 30 days from now?
- How many days are between two dates?
- What day of the week was a particular date?
The datetime Module
The first thing you need to do when working with Python dates and times is
import the datetime module.
import datetime
Python's datetime module contains several useful classes for
working with dates and times.
The most commonly used ones are:
date— represents a calendar date.time— represents a time.datetime— represents both a date and a time.timedelta— represents a difference or duration between dates or times.
Getting the Current Date
You can use datetime.date.today() to get today's date.
import datetime
today = datetime.date.today()
print(today)
The result may look like:
2026-09-05
Python displays the date in the format:
YYYY-MM-DD
For example:
2026= year09= month05= day
Getting the Year, Month and Day
Once you have a date object, you can access individual parts of the date.
import datetime
today = datetime.date.today()
print(today.year)
print(today.month)
print(today.day)
Each part is accessed using an attribute:
.yeargives the year..monthgives the month..daygives the day.
This is useful when you need to use only one part of a date.
Creating a Specific Date
You can create a specific date using datetime.date().
import datetime
birthday = datetime.date(2000, 5, 12)
print(birthday)
Here:
2000is the year.5is the month.12is the day.
The result is:
2000-05-12
Getting the Current Date and Time
If you need both the current date and current time, you can use
datetime.datetime.now().
import datetime
now = datetime.datetime.now()
print(now)
A result might look like:
2026-09-05 12:15:30.123456
The value contains the year, month, day, hour, minute, second and microseconds.
Accessing Parts of a datetime
A datetime object contains both date and time information.
You can access each part individually.
import datetime
now = datetime.datetime.now()
print(now.year)
print(now.month)
print(now.day)
print(now.hour)
print(now.minute)
print(now.second)
The time-related attributes include:
.hour.minute.second.microsecond
Creating a Time Object
Python can also represent a time without a date.
import datetime
meeting_time = datetime.time(14, 30, 0)
print(meeting_time)
The result is:
14:30:00
The arguments represent:
- Hour
- Minute
- Second
For example, 14:30:00 represents 2:30 PM using the
24-hour clock.
Formatting Dates with strftime()
Sometimes the default date format is not suitable for users.
For example, Python may display:
2026-09-05
But you may want to display:
05 September 2026
The strftime() method allows you to format a date or time.
import datetime
today = datetime.date.today()
formatted_date = today.strftime("%d %B %Y")
print(formatted_date)
The result could be:
05 September 2026
Common strftime() Format Codes
The symbols used inside strftime() tell Python how the date
should be displayed.
| Code | Meaning | Example |
|---|---|---|
%Y |
Four-digit year | 2026 |
%y |
Two-digit year | 26 |
%m |
Month as a number | 09 |
%B |
Full month name | September |
%b |
Short month name | Sep |
%d |
Day of the month | 05 |
%A |
Full weekday name | Saturday |
%a |
Short weekday name | Sat |
%H |
Hour using 24-hour clock | 14 |
%I |
Hour using 12-hour clock | 02 |
%M |
Minute | 30 |
%S |
Second | 45 |
%p |
AM or PM | PM |
For example:
import datetime
now = datetime.datetime.now()
print(now.strftime("%A, %d %B %Y"))
print(now.strftime("%I:%M %p"))
Converting Text into a Date
Sometimes a date starts as a string.
date_text = "05/09/2026"
Python sees this as text. If you want to perform date calculations on it,
you can convert it into a datetime object using
strptime().
import datetime
date_text = "05/09/2026"
date_object = datetime.datetime.strptime(
date_text,
"%d/%m/%Y"
)
print(date_object)
strptime() means that Python is parsing a string according to
the format you provide.
Finding the Day of the Week
You can use weekday() to determine the weekday number of a
date.
import datetime
date = datetime.date(2026, 9, 5)
print(date.weekday())
Python numbers weekdays from 0 to 6:
0= Monday1= Tuesday2= Wednesday3= Thursday4= Friday5= Saturday6= Sunday
You can also use strftime() when you want the actual weekday
name.
import datetime
date = datetime.date(2026, 9, 5)
print(date.strftime("%A"))
Using timedelta
The timedelta class represents a period of time.
It is especially useful when you want to add or subtract time from a date.
import datetime
today = datetime.date.today()
future_date = today + datetime.timedelta(days=7)
print(future_date)
The program calculates the date seven days after today.
You can also subtract days:
import datetime
today = datetime.date.today()
previous_date = today - datetime.timedelta(days=7)
print(previous_date)
Calculating Dates
Date calculations become useful in real programs.
For example, imagine a subscription that lasts 30 days.
import datetime
start_date = datetime.date.today()
end_date = start_date + datetime.timedelta(days=30)
print("Start:", start_date)
print("End:", end_date)
Notice that timedelta(days=30) means exactly 30 days. It does
not mean "the same day next month," because calendar months have different
numbers of days.
Finding the Difference Between Dates
You can subtract one date from another.
import datetime
start = datetime.date(2026, 9, 1)
end = datetime.date(2026, 9, 20)
difference = end - start
print(difference)
The result is:
19 days, 0:00:00
You can access the number of days directly using .days.
print(difference.days)
Result:
19
Calculating Age with Dates
Dates can be used to build practical programs such as an age calculator.
A simple approach is to compare the person's birth year with the current year.
import datetime
birth_year = 2000
current_year = datetime.date.today().year
age = current_year - birth_year
print("Approximate age:", age)
This gives an approximate age based only on the year. A precise age calculation should also check whether the person's birthday has already occurred this year.
This is an important programming lesson: the simplest calculation is not always the most accurate calculation.
Comparing Dates
Date objects can be compared using the same comparison operators you learned earlier.
import datetime
today = datetime.date.today()
deadline = datetime.date(2026, 12, 31)
if today < deadline:
print("The deadline has not passed.")
else:
print("The deadline has passed.")
You can use operators such as:
<><=>===!=
Working with User Date Input
When a user enters a date, Python initially receives it as a string.
date_text = input("Enter a date (DD/MM/YYYY): ")
You can convert that text into a date using strptime().
import datetime
date_text = input("Enter a date (DD/MM/YYYY): ")
date = datetime.datetime.strptime(
date_text,
"%d/%m/%Y"
).date()
print("You entered:", date)
This technique is useful for applications that accept birthdays, appointments, deadlines and booking dates.
date vs datetime
It is important to understand the difference between these two objects.
| Object | Contains |
|---|---|
date |
Year, month and day |
time |
Hour, minute, second and microsecond |
datetime |
Both date and time |
timedelta |
A duration or difference |
Choosing the appropriate object makes your code easier to understand.
Using an Import Alias
You can give an imported module a shorter name using as.
import datetime as dt
today = dt.date.today()
print(today)
This can make your code shorter, especially when you use a module many times.
Understanding Time Zones
Time becomes more complicated when your application is used in different parts of the world.
For example, a meeting scheduled for 10:00 AM in Nigeria does not happen at the same local time everywhere else.
Python can work with time-zone-aware dates and times. Modern Python code
can use the zoneinfo module for IANA time zones.
from datetime import datetime
from zoneinfo import ZoneInfo
lagos_time = datetime.now(ZoneInfo("Africa/Lagos"))
print(lagos_time)
A time-zone-aware datetime contains information about the time zone, making it safer for applications that work across different locations.
Time zones are particularly important for travel applications, appointment systems, online meetings, financial systems and distributed software.
Understanding UTC
UTC stands for Coordinated Universal Time. It is commonly used as a reference point when applications work with multiple time zones.
A common software practice is to store timestamps in UTC and convert them to the user's local time when displaying them.
The important idea is not to assume that every user's clock is in the same time zone.
Date & Time in the Real World
Date and time handling appears in many types of software.
- Booking systems: store appointment dates and times.
- Travel applications: calculate departure and arrival times.
- School systems: record registration and examination dates.
- Banking systems: record transaction timestamps.
- Web applications: display when posts or accounts were created.
- Robotics: record when sensors collected measurements.
- Agriculture: track planting, irrigation and harvesting dates.
For example, an agricultural monitoring system might record the time a sensor detected a change in soil conditions.
from datetime import datetime
reading_time = datetime.now()
print("Sensor reading recorded at:", reading_time)
Common Date & Time Mistakes
1. Treating dates as ordinary strings
Strings can display dates, but they are not ideal for date calculations.
date = "2026-09-05"
If you need to calculate with the date, convert it into a proper date or datetime object.
2. Confusing date and datetime
A date does not contain a time. A datetime
contains both.
3. Forgetting date format codes
When using strftime() or strptime(), make sure
your format matches the actual date.
For example, 05/09/2026 interpreted as
%d/%m/%Y means 5 September 2026.
4. Ignoring time zones
Applications used internationally should not assume that every timestamp belongs to the same local time zone.
5. Assuming every month has the same number of days
A month can contain 28, 29, 30 or 31 days. For calendar-month calculations, do not simply assume that every month contains 30 days.
Practice Exercises
Try these exercises yourself before looking for a solution.
Exercise 1: Current Date
Write a program that prints today's date.
Exercise 2: Current Time
Write a program that prints the current date and time.
Exercise 3: Birthday
Create a date object representing your birthday and print it.
Exercise 4: Formatted Date
Display today's date in this format:
05 September 2026
Exercise 5: Seven Days Later
Write a program that calculates the date seven days from today.
Exercise 6: Days Until an Event
Create a future date and calculate how many days remain until that date.
Exercise 7: User Date
Ask the user to enter a date in DD/MM/YYYY format and convert
it into a Python date.
Mini Project: Appointment Countdown
Let's combine several things you have learned to create a small appointment countdown program.
The program asks the user for an appointment date and calculates how many days remain.
import datetime
date_text = input("Enter appointment date (DD/MM/YYYY): ")
appointment = datetime.datetime.strptime(
date_text,
"%d/%m/%Y"
).date()
today = datetime.date.today()
if appointment < today:
print("This appointment date has already passed.")
elif appointment == today:
print("The appointment is today!")
else:
days_remaining = (appointment - today).days
print("Days remaining:", days_remaining)
This small project combines:
input()- Strings
datetimestrptime()date.today()- Conditions
- Date subtraction
.days
Notice how concepts from earlier modules begin to work together. This is an important stage in learning programming: you are no longer learning individual features in isolation.
Python Date & Time Quiz
Test yourself before continuing.
Python Date & Time Summary
The datetime module gives Python the ability to work with
calendar dates, times and durations.
In this lesson, you learned how to:
- Import the
datetimemodule. - Get today's date.
- Get the current date and time.
- Create specific dates and times.
- Access individual date and time components.
- Format dates using
strftime(). - Convert strings into dates using
strptime(). - Compare dates.
- Calculate differences between dates.
- Add and subtract periods using
timedelta. - Understand the importance of time zones.
18. Python Regular Expressions
Regular expressions, often called regex, are patterns used to search and manipulate text.
Imagine you have a large piece of text containing hundreds of email addresses. Instead of checking every character manually, you can give Python a pattern and ask it to find text that follows that pattern.
Regular expressions can be used to:
- Search for specific patterns in text.
- Check whether text follows a particular format.
- Extract information from larger pieces of text.
- Replace matching text.
- Split text using patterns.
- Validate things such as usernames, phone numbers and email-like strings.
What Are Regular Expressions?
A regular expression is a pattern that describes text you want Python to find.
For example, suppose we have:
text = "My phone number is 08012345678"
We could create a pattern that looks for a sequence of digits.
\d+
The pattern tells Python to look for one or more digits.
This allows us to find 08012345678 without knowing the exact
number beforehand.
The re Module
Python provides regular expression functionality through the built-in
re module.
import re
Once imported, you can use functions such as:
re.search()re.match()re.findall()re.finditer()re.sub()re.split()
Why Regex Patterns Often Use r""
You will often see regular expression patterns written using a raw string.
pattern = r"\d+"
The r before the quotation mark tells Python to treat the
string as a raw string.
This is particularly useful because regular expressions make heavy use of backslashes.
For example:
r"\d+"
r"\w+"
r"\s+"
Using raw strings makes regex patterns easier to write and read.
re.search()
re.search() searches through a string and returns the first
match it finds.
import re
text = "Python is powerful."
result = re.search("Python", text)
print(result)
If the pattern is found, Python returns a match object. If it is not found,
it returns None.
You can check whether a match was found using a condition.
import re
text = "Python is powerful."
if re.search("Python", text):
print("Found Python!")
re.match()
re.match() checks for a match at the beginning
of the string.
import re
text = "Python is fun."
result = re.match("Python", text)
if result:
print("The text starts with Python.")
Compare this with re.search(): search() can find
the pattern anywhere in the string, while match() checks the
beginning.
re.findall()
re.findall() finds all occurrences of a pattern and returns
them as a list.
import re
text = "Python is easy. Python is powerful."
matches = re.findall("Python", text)
print(matches)
The result is:
['Python', 'Python']
This is useful when you need every occurrence rather than only the first one.
Finding Digits with \d
One of the most useful regex symbols is \d.
It represents a digit from 0 to 9.
import re
text = "I have 3 apples and 12 oranges."
numbers = re.findall(r"\d+", text)
print(numbers)
The result is:
['3', '12']
The + means "one or more".
Therefore, \d+ means one or more consecutive digits.
Common Regex Character Classes
| Pattern | Meaning |
|---|---|
\d |
A digit |
\D |
A non-digit |
\w |
A word character |
\W |
A non-word character |
\s |
Whitespace |
\S |
Non-whitespace |
. |
Almost any character except a newline |
The + Quantifier
The + symbol means one or more occurrences of
the preceding pattern.
r"\d+"
This finds one or more consecutive digits.
For example:
import re
text = "Room 12, floor 3."
numbers = re.findall(r"\d+", text)
print(numbers)
Result:
['12', '3']
The * Quantifier
The * symbol means zero or more occurrences
of the preceding pattern.
r"\d*"
This can match even when no digit exists, so you need to use it carefully.
The ? Quantifier
The ? symbol means zero or one occurrence of
the preceding pattern.
This is useful when part of a pattern is optional.
r"colou?r"
This pattern can match both:
color
colour
Exact Repetitions with {}
Curly brackets allow you to specify how many times something should occur.
r"\d{4}"
This means exactly four digits.
For example:
import re
text = "Year 2026"
result = re.findall(r"\d{4}", text)
print(result)
Result:
['2026']
You can also specify a range.
r"\d{2,4}"
This means between two and four digits.
Character Sets with []
Square brackets allow you to specify a set of characters.
r"[abc]"
This matches one character that is either a, b or
c.
You can also specify a range:
r"[a-z]"
This matches a lowercase letter from a to z.
For digits:
r"[0-9]"
Negated Character Sets
A caret ^ inside square brackets means "not these
characters."
r"[^0-9]"
This matches a character that is not a digit.
^ and $ Anchors
The caret and dollar sign have another important use outside character sets.
^means the beginning of the string.$means the end of the string.
For example:
r"^Python"
This means the string must begin with "Python".
And:
r"Python$"
means the string must end with "Python".
Groups with Parentheses
Parentheses allow you to group parts of a pattern.
r"(cat|dog)"
This pattern can match either cat or dog.
The vertical bar | means "or".
import re
text = "I have a cat and a dog."
animals = re.findall(r"(cat|dog)", text)
print(animals)
Result:
['cat', 'dog']
Finding Email-Like Patterns
Regular expressions can be used to locate text that resembles an email address.
import re
text = "Contact us at hello@example.com."
pattern = r"[\w.-]+@[\w.-]+\.\w+"
emails = re.findall(pattern, text)
print(emails)
Result:
['hello@example.com']
This pattern is useful for learning how regex works, but real-world email validation can be more complicated than a single regex.
Finding Phone Numbers
You can also use regex to locate sequences that resemble phone numbers.
import re
text = "Call 08012345678 for more information."
pattern = r"\b\d{11}\b"
numbers = re.findall(pattern, text)
print(numbers)
Here, \b represents a word boundary and
\d{11} means exactly eleven digits.
Replacing Text with re.sub()
Regular expressions are not only for finding text. They can also replace matching text.
import re
text = "Python is difficult."
new_text = re.sub(
"difficult",
"powerful",
text
)
print(new_text)
Result:
Python is powerful.
The general structure is:
re.sub(pattern, replacement, text)
Removing Numbers
You can combine re.sub() with a regex pattern to remove
unwanted characters.
import re
text = "Python123"
clean_text = re.sub(r"\d", "", text)
print(clean_text)
Result:
Python
Splitting Text with re.split()
re.split() splits text wherever the pattern occurs.
import re
text = "apple,banana;orange"
items = re.split(r"[,;]", text)
print(items)
Result:
['apple', 'banana', 'orange']
This is useful when information may be separated by different delimiters.
Regex Flags
Regex functions can accept flags that change how the pattern behaves.
One useful flag is re.IGNORECASE.
import re
text = "Python PYTHON python"
matches = re.findall(
"python",
text,
re.IGNORECASE
)
print(matches)
This allows the pattern to match different combinations of uppercase and lowercase letters.
Compiling a Regex Pattern
If you are going to use the same pattern multiple times, you can compile it into a regex object.
import re
pattern = re.compile(r"\d+")
print(pattern.findall("There are 12 apples and 5 oranges."))
This can make repeated use of the same pattern cleaner.
Understanding Match Objects
Functions such as re.search() can return a match object.
import re
text = "My score is 95."
result = re.search(r"\d+", text)
if result:
print(result.group())
Result:
95
The group() method retrieves the text that matched the
pattern.
Using re.finditer()
re.finditer() returns an iterator containing match objects for
every match.
import re
text = "Scores: 75, 82, 91"
for match in re.finditer(r"\d+", text):
print(match.group())
Output:
75
82
91
This becomes particularly useful when you need additional information about each match, such as where it appears in the text.
Using Regex for Validation
Validation means checking whether data follows rules you expect.
For example, suppose you want a username containing only letters, numbers and underscores.
import re
username = input("Enter username: ")
if re.fullmatch(r"[A-Za-z0-9_]+", username):
print("Valid username.")
else:
print("Invalid username.")
fullmatch() requires the entire string to match the pattern.
This is often more appropriate for validation than simply searching for a matching part of the input.
re.fullmatch()
re.fullmatch() checks whether the entire string matches a
pattern.
import re
text = "12345"
if re.fullmatch(r"\d+", text):
print("The entire string contains digits.")
This is different from searching for digits somewhere inside the string.
Regular Expressions in the Real World
Regex is useful in many areas of software development.
- Extracting information from documents.
- Validating form input.
- Finding phone numbers.
- Finding email-like strings.
- Cleaning datasets.
- Processing log files.
- Searching source code.
- Preparing data for analysis.
For example, imagine an agricultural monitoring system producing logs:
Sensor A12: temperature=31.5
Sensor B07: temperature=29.8
Sensor C03: temperature=30.1
A regular expression could help extract the sensor identifiers or temperature values automatically.
import re
text = """
Sensor A12: temperature=31.5
Sensor B07: temperature=29.8
Sensor C03: temperature=30.1
"""
temperatures = re.findall(
r"temperature=(\d+\.\d+)",
text
)
print(temperatures)
Result:
['31.5', '29.8', '30.1']
This is a simple example of how regex can become useful in data processing and automation.
Common Regex Mistakes
1. Forgetting that regex is pattern-based
A regex pattern should describe what you are looking for rather than simply containing the exact text you expect every time.
2. Confusing + and *
+ means one or more. * means zero or more.
3. Forgetting raw strings
Using r"..." is often clearer when writing patterns containing
backslashes.
4. Using search() when you need full validation
search() can find a valid-looking part of a string. For
validation, fullmatch() is often a better choice.
5. Making patterns unnecessarily complicated
Start with the simplest pattern that solves the problem. Complicated regular expressions can become difficult to understand and maintain.
Practice Exercises
Exercise 1: Find Numbers
Given the text below, use regex to find all numbers.
text = "I bought 5 books, 2 pens and 10 notebooks."
Exercise 2: Find Python
Find every occurrence of the word "Python" in a string.
Exercise 3: Replace Digits
Remove all digits from:
"Python123"
Exercise 4: Extract Phone Numbers
Find an eleven-digit phone number inside a larger string.
Exercise 5: Validate Username
Create a pattern that allows only letters, numbers and underscores in a username.
Exercise 6: Extract Temperatures
From this text, extract all temperature values:
temperature=31.5
temperature=28.9
temperature=30.2
Mini Project: Information Extractor
Let's build a small program that extracts email-like addresses and phone numbers from a piece of text.
import re
text = """
Contact us at hello@example.com
or support@example.org.
Call 08012345678 for assistance.
"""
email_pattern = r"[\w.-]+@[\w.-]+\.\w+"
phone_pattern = r"\b\d{11}\b"
emails = re.findall(email_pattern, text)
phones = re.findall(phone_pattern, text)
print("Emails:")
for email in emails:
print(email)
print("\nPhone numbers:")
for phone in phones:
print(phone)
This project combines strings, lists, loops, functions from the
re module and regular expression patterns.
Python Regular Expressions Quiz
Regular Expressions Summary
Regular expressions allow Python to work with patterns in text.
You learned how to:
- Import the
remodule. - Search for patterns with
re.search(). - Check the beginning of text with
re.match(). - Find all matches with
re.findall(). - Use
\d,\wand\s. - Use quantifiers such as
+,*and?. - Use exact repetitions with
{}. - Create character sets using
[]. - Use
^and$as anchors. - Group patterns with parentheses.
- Replace text using
re.sub(). - Split text using
re.split(). - Validate complete strings with
re.fullmatch(). - Use regex for practical data extraction.
19. Python Iterators & Generators
You have already used for loops many times in this course.
For example:
numbers = [10, 20, 30, 40]
for number in numbers:
print(number)
But what actually happens behind the scenes when Python goes through the list one item at a time?
This is where iterators come in.
Generators take this idea even further. They allow you to produce values one at a time instead of creating all the values in memory at once.
- What iteration means
- What iterators are
- How
iter()works - How
next()works - What
StopIterationmeans - How to create your own iterator
- What generators are
- How
yieldworks - Generator functions
- Generator expressions
- Why generators are useful for large datasets
What Is Iteration?
Iteration means going through items one at a time.
You have already been doing this with loops.
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
Python takes the items from the collection one after another.
The important idea is:
What Is an Iterable?
An iterable is an object that Python can go through one item at a time.
Common examples include:
- Lists
- Tuples
- Strings
- Sets
- Dictionaries
- Files
For example, a string is iterable:
word = "Python"
for letter in word:
print(letter)
Output:
P
y
t
h
o
n
Python can therefore move through the characters of the string one at a time.
What Is an Iterator?
An iterator is an object that keeps track of where it is during iteration and produces the next value when requested.
You can obtain an iterator from an iterable using iter().
numbers = [10, 20, 30]
iterator = iter(numbers)
print(iterator)
The iterator remembers the current position in the sequence.
The iter() Function
The iter() function creates an iterator from an iterable.
fruits = ["apple", "banana", "orange"]
fruit_iterator = iter(fruits)
The list is the iterable, while fruit_iterator is the
iterator.
You can then request values from the iterator using next().
The next() Function
The next() function asks an iterator for its next value.
fruits = ["apple", "banana", "orange"]
iterator = iter(fruits)
print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
apple
banana
orange
Every time next() is called, the iterator moves forward.
StopIteration
What happens when there are no more values?
fruits = ["apple", "banana"]
iterator = iter(fruits)
print(next(iterator))
print(next(iterator))
print(next(iterator))
The third call has no value to return. Python raises a
StopIteration exception.
This tells Python that the iterator has reached the end.
You normally do not see this exception when using a regular
for loop because Python handles the iteration process for you.
How for Loops Use Iterators
A for loop handles much of the iterator work automatically.
numbers = [10, 20, 30]
for number in numbers:
print(number)
Conceptually, Python obtains an iterator, repeatedly requests the next value and stops when the iterator is exhausted.
You do not normally need to manually call iter() and
next() when writing ordinary loops.
The Iterator Protocol
Python iterators follow a simple protocol.
An iterator provides:
__iter__()— returns the iterator itself.__next__()— returns the next value.
These are special methods, sometimes called dunder methods because their names begin and end with double underscores.
You do not need to memorize the implementation immediately. The important idea is that Python knows how to ask an iterator for its next value.
Creating Your Own Iterator
Because you have already learned classes, you can create a custom iterator using a class.
class CountUp:
def __init__(self, maximum):
self.current = 1
self.maximum = maximum
def __iter__(self):
return self
def __next__(self):
if self.current <= self.maximum:
value = self.current
self.current += 1
return value
raise StopIteration
counter = CountUp(5)
for number in counter:
print(number)
Output:
1
2
3
4
5
This example demonstrates the iterator protocol directly.
What Are Generators?
A generator is a convenient way to create an iterator.
Instead of manually creating a class with __iter__() and
__next__(), you can often write a generator function using
yield.
This makes many iterator problems much simpler.
The yield Keyword
The yield keyword produces a value from a generator.
def count_up():
yield 1
yield 2
yield 3
Calling the function does not immediately produce all three values.
numbers = count_up()
print(next(numbers))
print(next(numbers))
print(next(numbers))
Output:
1
2
3
After yielding a value, the generator pauses. When next() is
called again, it continues from where it stopped.
Generator Functions
A function containing yield is called a generator function.
def numbers():
yield 10
yield 20
yield 30
for number in numbers():
print(number)
Output:
10
20
30
The generator produces each value as the loop requests it.
yield vs return
You already learned about return in functions. It is important
to understand how it differs from yield.
| return | yield |
|---|---|
| Returns a value and ends the function. | Produces a value and pauses the generator. |
| Normally produces one result. | Can produce many values over time. |
| Used in ordinary functions. | Used to create generators. |
For example:
def normal_function():
return 1
Compared with:
def generator_function():
yield 1
yield 2
yield 3
Generators Remember Their State
One of the most useful features of a generator is that it remembers where it stopped.
def count():
number = 1
while number <= 3:
yield number
number += 1
counter = count()
print(next(counter))
print(next(counter))
print(next(counter))
The generator remembers the value of number between calls.
This is what allows the generator to pause and continue later.
Using Generators with for Loops
Most of the time, you will use generators with for loops.
def count_up_to(limit):
number = 1
while number <= limit:
yield number
number += 1
for number in count_up_to(5):
print(number)
Output:
1
2
3
4
5
Why Generators Can Save Memory
Consider a program that needs to work with one million numbers.
A list stores all of the numbers in memory:
numbers = [number for number in range(1000000)]
A generator can produce the numbers one at a time:
numbers = (number for number in range(1000000))
The generator does not need to create the entire sequence as a list at once.
Generator Expressions
Generator expressions look similar to list comprehensions.
A list comprehension creates a list:
squares = [number * number for number in range(5)]
print(squares)
A generator expression uses parentheses:
squares = (number * number for number in range(5))
for square in squares:
print(square)
The generator produces each square when it is requested.
List vs Generator
| List | Generator |
|---|---|
| Stores generated values. | Produces values when requested. |
| Can be indexed directly. | Does not work like a normal indexed list. |
| Can consume more memory for large sequences. | Can be much more memory-efficient. |
| Useful when you need all values available. | Useful when processing values one at a time. |
Generators and Large Files
Generators become particularly useful when processing large files.
Instead of loading an entire file into memory, you can process one line at a time.
def read_lines(filename):
with open(filename, "r", encoding="utf-8") as file:
for line in file:
yield line.strip()
for line in read_lines("large_data.txt"):
print(line)
The generator yields one line at a time.
This approach can be useful when dealing with very large datasets.
Filtering Data with a Generator
Generators can also be used to process only the information you need.
def even_numbers(numbers):
for number in numbers:
if number % 2 == 0:
yield number
values = [1, 2, 3, 4, 5, 6]
for number in even_numbers(values):
print(number)
Output:
2
4
6
The generator does not need to create another list containing all the even numbers.
Generator Pipelines
Generators can be combined to create processing pipelines.
Imagine that you have thousands of sensor readings. One generator could read the data, another could filter it, and another could transform it.
def numbers():
for number in range(1, 11):
yield number
def even_numbers(values):
for value in values:
if value % 2 == 0:
yield value
def squared(values):
for value in values:
yield value * value
data = squared(even_numbers(numbers()))
for value in data:
print(value)
Output:
4
16
36
64
100
Notice that the data flows through the stages instead of requiring every intermediate result to be stored in a large list.
Infinite Generators
A generator can theoretically produce values forever.
def counter():
number = 1
while True:
yield number
number += 1
This generator does not have a natural stopping point.
You must therefore control how many values you request.
numbers = counter()
for _ in range(5):
print(next(numbers))
Output:
1
2
3
4
5
Be careful with infinite generators. A loop that tries to consume the entire generator will never finish.
return in a Generator
A generator can also contain return.
def example():
yield 1
yield 2
return
yield 3
Once the generator reaches return, it stops producing values.
In ordinary beginner programs, you will usually use yield to
produce values and allow the generator to finish naturally.
When Should You Use Generators?
Generators are particularly useful when:
- You are processing a large amount of data.
- You only need one item at a time.
- You are reading large files.
- You are processing streams of information.
- You want to create a sequence lazily.
- You want to build data-processing pipelines.
A generator is not automatically better than a list. If you need to access values repeatedly by index, a list may be more appropriate.
Generators in Agriculture and Data Processing
Generators become especially interesting when working with large datasets.
Imagine a farm monitoring system collecting thousands of temperature readings.
def sensor_readings():
readings = [
29.5,
31.2,
30.8,
28.9,
32.1
]
for reading in readings:
yield reading
for temperature in sensor_readings():
if temperature > 30:
print("High temperature:", temperature)
In a real agricultural system, the readings might come from sensors, files, databases or network streams instead of a small list.
The same generator concept can still be used to process each reading as it arrives.
Generators in Robotics
Robotics systems often process streams of information continuously.
A generator can represent a sequence of sensor readings.
def sensor_data():
for value in [20, 21, 22, 23, 24]:
yield value
for reading in sensor_data():
print("Sensor reading:", reading)
In a real robot, the values could instead come from sensors such as temperature, distance, light or soil-moisture sensors.
This is one reason iterators and generators are worth understanding if you are interested in automation, robotics or data processing.
Common Mistakes
1. Calling next() after the iterator is exhausted
Once an iterator has no more values, calling next() can raise
StopIteration.
2. Expecting a generator to behave exactly like a list
A generator produces values as needed. It does not provide the same indexing and repeated-access behavior as a list.
3. Accidentally consuming a generator
numbers = (number for number in range(5))
print(list(numbers))
print(list(numbers))
The second result will be empty because the generator has already been exhausted.
4. Creating an uncontrolled infinite loop
Infinite generators can be useful, but you must control how many values you consume.
5. Using generators when you actually need a reusable collection
If you need to repeatedly access all the values, a list may be a better choice.
Practice Exercises
Exercise 1: Use iter()
Create a list of three fruits and use iter() to create an
iterator.
Exercise 2: Use next()
Use next() to retrieve each fruit from your iterator.
Exercise 3: Create a Generator
Write a generator that produces the numbers 1 through 5.
Exercise 4: Even Numbers
Create a generator that produces only even numbers from 1 to 20.
Exercise 5: Squares
Create a generator that produces the square of each number from 1 to 10.
Exercise 6: Countdown
Create a generator that counts backward from a number supplied by the user.
Exercise 7: Temperature Filter
Create a generator that receives temperature readings and yields only readings above 30 degrees.
Mini Project: Sensor Data Processor
Let's create a small generator that processes sensor readings and produces only readings above a chosen threshold.
def high_temperature_readings(readings, threshold):
for reading in readings:
if reading > threshold:
yield reading
temperatures = [
27.5,
31.2,
29.8,
33.4,
30.1,
26.9
]
for temperature in high_temperature_readings(
temperatures,
30
):
print("High temperature:", temperature)
Output:
High temperature: 31.2
High temperature: 33.4
High temperature: 30.1
The program processes each reading and yields only the values that satisfy the condition.
Later, the same idea could be connected to real sensor data instead of a hard-coded list.
Python Iterators & Generators Quiz
Iterators & Generators Summary
Iterators and generators allow Python to process sequences one item at a time.
You learned how to:
- Understand iteration.
- Identify iterables.
- Create iterators using
iter(). - Retrieve values using
next(). - Understand
StopIteration. - Understand the iterator protocol.
- Create custom iterators using classes.
- Create generators using
yield. - Understand the difference between
returnandyield. - Create generator expressions.
- Use generators for large datasets.
- Build simple data-processing pipelines.
yield. Generators are
particularly useful when you do not want to load an entire dataset into
memory at once.
20. Python Decorators
Decorators are one of Python's most powerful features. They allow you to modify or extend the behavior of a function without changing the function's original code.
That may sound complicated, but the basic idea is surprisingly simple:
Decorators are commonly used in web applications, authentication systems, logging, performance measurement, validation and many other areas of software development.
Before learning decorators, you need to understand two important Python concepts:
- Functions can be stored in variables.
- Functions can be passed to other functions.
What Is a Decorator?
Suppose you have a function:
def greet():
print("Hello!")
Imagine that you want to print a message before and after the function runs.
You could change the function itself:
def greet():
print("Starting function...")
print("Hello!")
print("Function finished.")
But what if you have many functions and want to add the same behavior to all of them?
A decorator can solve this problem without modifying each function directly.
Functions Are Objects
In Python, functions are objects. This means you can assign a function to a variable.
def greet():
print("Hello!")
message = greet
message()
Output:
Hello!
Both greet and message refer to the same function.
Notice that we used greet without parentheses when assigning
it.
message = greet
If you wrote greet(), you would be calling the function
immediately instead.
Passing a Function to Another Function
Because functions are objects, you can pass one function into another function.
def greet():
print("Hello!")
def run_function(function):
function()
run_function(greet)
Output:
Hello!
The function greet was passed into run_function().
This concept is fundamental to understanding decorators.
Returning a Function
A function can also return another function.
def create_greeting():
def greet():
print("Hello!")
return greet
message = create_greeting()
message()
Output:
Hello!
The inner function was returned by the outer function.
Inner Functions
A function defined inside another function is called an inner function or nested function.
def outer():
def inner():
print("Inside the inner function.")
inner()
outer()
The inner function can be used by the outer function.
Decorators commonly use inner functions because the inner function acts as a wrapper around the original function.
Creating Your First Decorator
Let's build a simple decorator.
def decorator(function):
def wrapper():
print("Before the function.")
function()
print("After the function.")
return wrapper
This decorator receives a function, creates a new function called
wrapper, and returns the wrapper.
Now let's create a normal function:
def greet():
print("Hello!")
We can manually decorate it:
greet = decorator(greet)
greet()
Output:
Before the function.
Hello!
After the function.
The original greet() function was wrapped with additional
behavior.
The @ Syntax
Python provides a cleaner way to apply decorators using the
@ symbol.
Instead of:
def greet():
print("Hello!")
greet = decorator(greet)
You can write:
@decorator
def greet():
print("Hello!")
Python effectively applies the decorator to the function.
Now:
greet()
produces:
Before the function.
Hello!
After the function.
@decorator line is not a comment or special decoration
for appearance. It changes how Python creates the function.
Decorators and Function Arguments
What if the function we want to decorate accepts arguments?
def greet(name):
print("Hello", name)
Our previous wrapper does not accept any arguments.
We can fix this using *args and **kwargs.
def decorator(function):
def wrapper(*args, **kwargs):
print("Before function")
result = function(*args, **kwargs)
print("After function")
return result
return wrapper
Now it can work with functions that receive different numbers and types of arguments.
@decorator
def greet(name):
print("Hello", name)
greet("Olivia")
Output:
Before function
Hello Olivia
After function
Decorators and Return Values
A decorator should not accidentally remove the result returned by the original function.
Consider:
def add(a, b):
return a + b
If a wrapper calls this function but does not return the result, the caller
may receive None.
A good decorator preserves the result:
def decorator(function):
def wrapper(*args, **kwargs):
result = function(*args, **kwargs)
return result
return wrapper
@decorator
def add(a, b):
return a + b
answer = add(5, 3)
print(answer)
Output:
8
Understanding the Wrapper
The wrapper is the function that receives the call before the original function does.
Think of the structure like this:
decorated function call
↓
wrapper
↓
original function
↓
result
↓
wrapper
↓
caller
The wrapper gives you a place to perform additional actions before or after the original function.
Practical Example: Logging
One common use of decorators is logging.
Suppose you want to know whenever a function is called.
def log_function(function):
def wrapper(*args, **kwargs):
print("Function called:", function.__name__)
result = function(*args, **kwargs)
return result
return wrapper
@log_function
def calculate_total(price, quantity):
return price * quantity
total = calculate_total(500, 3)
print("Total:", total)
Output:
Function called: calculate_total
Total: 1500
This can be useful when debugging larger applications.
Practical Example: Measuring Execution Time
Decorators can also be used to measure how long a function takes to run.
import time
def timer(function):
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = function(*args, **kwargs)
end = time.perf_counter()
print(
function.__name__,
"took",
end - start,
"seconds"
)
return result
return wrapper
@timer
def calculate():
total = 0
for number in range(1000000):
total += number
return total
calculate()
The exact execution time depends on the computer and what else is running.
The important lesson is that the decorator can measure what happens around the function without changing the function's main calculation.
Practical Example: Access Control
Decorators are also commonly used to control whether a function is allowed to execute.
A simplified example might look like this:
def requires_login(function):
def wrapper(logged_in):
if not logged_in:
print("Please log in first.")
return
return function(logged_in)
return wrapper
@requires_login
def dashboard(logged_in):
print("Welcome to your dashboard.")
dashboard(False)
dashboard(True)
The decorator checks a condition before allowing the function to continue.
Real authentication systems are more complicated, but this demonstrates the basic principle.
functools.wraps
There is an important improvement you should make when writing reusable decorators.
Python provides functools.wraps to preserve information about
the original function.
from functools import wraps
def decorator(function):
@wraps(function)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
Without wraps, Python may report information about the wrapper
instead of the original function.
When writing decorators that other people may use, functools.wraps
is a good practice.
Preserving Function Information
Consider a function with a docstring:
def greet():
"""Say hello to the user."""
print("Hello!")
When a decorator wraps the function, metadata such as the function's name and documentation can be affected.
Using @wraps(function) helps preserve this information.
from functools import wraps
def decorator(function):
@wraps(function)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
Using Multiple Decorators
Python allows you to apply more than one decorator to a function.
@decorator_one
@decorator_two
def greet():
print("Hello!")
The decorators are applied from the bottom upward.
Conceptually, this is similar to:
greet = decorator_one(
decorator_two(greet)
)
When using multiple decorators, remember that their order can affect the final behavior.
Decorators That Accept Arguments
Sometimes you want to configure a decorator.
This requires another level of function nesting.
def repeat(times):
def decorator(function):
def wrapper(*args, **kwargs):
for _ in range(times):
function(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet():
print("Hello!")
greet()
Output:
Hello!
Hello!
Hello!
Notice that repeat(3) first creates the decorator, and that
decorator is then applied to greet().
Understanding the Three Layers
Decorators that accept their own arguments can initially look confusing because there are several nested functions.
The structure is:
def outer(decorator_arguments):
def decorator(function):
def wrapper(function_arguments):
# additional behavior
return function(function_arguments)
return wrapper
return decorator
Think of it as:
- Outer function: receives settings for the decorator.
- Decorator: receives the function being decorated.
- Wrapper: receives the function's normal arguments.
Decorators and Classes
Decorators are not limited to ordinary functions. Python also supports decorators for methods and classes.
You have already learned classes and objects. As you progress into larger Python applications, you will encounter decorators such as:
@property
@classmethod
@staticmethod
These are built-in Python decorators.
You do not need to master all of them at once. The important thing is to recognize that decorators are used throughout Python itself.
The @property Decorator
You have already seen that Python classes can contain methods.
The @property decorator allows a method to be accessed like an
attribute.
class Person:
def __init__(self, name):
self.name = name
@property
def description(self):
return "Person: " + self.name
person = Person("Ada")
print(person.description)
Notice that we use person.description rather than
person.description().
This makes the method behave like a calculated attribute.
The @staticmethod Decorator
A static method belongs to a class but does not require access to the
instance through self.
class Calculator:
@staticmethod
def add(a, b):
return a + b
print(Calculator.add(5, 3))
Result:
8
The @classmethod Decorator
A class method receives the class itself as its first argument, commonly
named cls.
class Student:
school = "Gabbywall Academy"
@classmethod
def show_school(cls):
return cls.school
print(Student.show_school())
Class methods are useful when the operation relates to the class rather than a particular object.
Decorators in Agricultural Software
Imagine you are building an agricultural monitoring system.
You might have many functions that process sensor readings.
def process_temperature():
print("Processing temperature...")
def process_moisture():
print("Processing soil moisture...")
def process_light():
print("Processing light level...")
Suppose you want to log whenever a sensor-processing function runs.
from functools import wraps
def log_sensor(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Running sensor:", function.__name__)
return function(*args, **kwargs)
return wrapper
@log_sensor
def process_temperature():
print("Processing temperature...")
@log_sensor
def process_moisture():
print("Processing soil moisture...")
process_temperature()
process_moisture()
Instead of adding the logging code separately to every function, the decorator provides a reusable solution.
Decorators in Robotics
In robotics software, you may eventually have functions responsible for reading sensors, controlling motors or processing data.
A decorator could be used to log when an operation starts and finishes.
from functools import wraps
def log_operation(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Starting:", function.__name__)
result = function(*args, **kwargs)
print("Finished:", function.__name__)
return result
return wrapper
@log_operation
def read_sensor():
print("Reading sensor data.")
read_sensor()
As your robotics programs become larger, reusable patterns such as this can help keep your code organized.
When Should You Use Decorators?
Decorators are useful when you want to apply the same behavior to multiple functions without duplicating code.
Common examples include:
- Logging
- Authentication
- Authorization
- Performance measurement
- Input validation
- Caching
- Error handling
- Access control
The key question to ask is:
If the answer is yes, a decorator may be a good solution.
Common Decorator Mistakes
1. Forgetting to return the wrapper
def decorator(function):
def wrapper():
function()
# Missing:
# return wrapper
Without returning the wrapper, the decorated function may no longer behave as expected.
2. Forgetting function arguments
If the original function accepts arguments, the wrapper should generally
use *args and **kwargs when the decorator needs to
support arbitrary functions.
3. Forgetting the return value
If the original function returns something, the wrapper should normally return that result.
4. Forgetting functools.wraps
For reusable decorators, @wraps helps preserve the original
function's metadata.
5. Using decorators when they make the code harder to understand
Decorators are powerful, but they are not required everywhere. Simple code is often better when a decorator does not provide a clear benefit.
Practice Exercises
Exercise 1: Basic Decorator
Create a decorator that prints "Starting..." before a function runs.
Exercise 2: Before and After
Create a decorator that prints a message before and after the decorated function executes.
Exercise 3: Arguments
Create a decorator that works with a function accepting two arguments.
Exercise 4: Return Values
Create a decorator for an addition function and make sure the result is still returned correctly.
Exercise 5: Logging
Create a decorator that prints the name of the function being called.
Exercise 6: Timing
Create a decorator that measures approximately how long a function takes to execute.
Exercise 7: Authentication
Create a decorator that allows a function to execute only when a user is logged in.
Mini Project: Function Logger
Let's create a reusable function logger.
from functools import wraps
def logger(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Calling:", function.__name__)
result = function(*args, **kwargs)
print("Result:", result)
return result
return wrapper
@logger
def multiply(a, b):
return a * b
answer = multiply(6, 7)
print("Final answer:", answer)
Output will look similar to:
Calling: multiply
Result: 42
Final answer: 42
This small project demonstrates the core decorator pattern:
- Receive the original function.
- Create a wrapper.
- Perform additional behavior.
- Call the original function.
- Return its result.
Python Decorators Quiz
Python Decorators Summary
Decorators allow you to add or modify behavior around existing functions without changing their original code.
You learned how to:
- Understand functions as objects.
- Pass functions to other functions.
- Return functions from functions.
- Create inner functions.
- Build a basic decorator.
- Use the
@decorator syntax. - Handle function arguments with
*argsand**kwargs. - Preserve function return values.
- Use
functools.wraps. - Create logging decorators.
- Measure function execution time.
- Create simple access-control decorators.
- Use multiple decorators.
- Create configurable decorators.
- Recognize built-in decorators such as
@property,@staticmethodand@classmethod.
@ syntax,
decorators become much easier to reason about.
21. Python Environments & Packages
So far, you have mostly worked with Python's built-in features and standard library. But real-world Python development often requires additional libraries.
For example, you might eventually want to use libraries for:
- Data analysis
- Artificial intelligence
- Machine learning
- Computer vision
- Web development
- Robotics
- Scientific computing
- Working with databases
Python has a huge ecosystem of packages that provide functionality you don't have to build yourself.
What Is a Python Package?
A package is a collection of Python code that can be installed and reused in your projects.
For example, suppose you want to perform advanced numerical calculations. Instead of building every mathematical operation yourself, you can use a package such as NumPy.
Another example is OpenCV, which provides tools for computer vision and image processing.
A package can contain:
- Functions
- Classes
- Modules
- Data
- Other supporting files
Library vs Package
You will often hear the words library and package used in Python.
They are related, but they are not always technically identical.
A package is a particular way of organizing and distributing Python code. The word library is often used more generally to describe reusable functionality.
In everyday Python discussions, people may use the terms interchangeably. Don't worry too much about the distinction at this stage.
What Is pip?
pip is the standard package installer commonly used with
Python.
It allows you to install packages from the Python Package Index and other package sources.
For example:
pip install requests
This tells pip to install the requests package.
Depending on your computer and Python installation, you may instead use:
python -m pip install requests
On some systems, especially when multiple Python versions are installed, you may use:
python3 -m pip install requests
python -m pip helps make it clear which Python
installation is being used to run pip.
Installing a Package
Let's install a package called requests.
Open your terminal and run:
python -m pip install requests
pip will download the package and install it into the Python environment you are currently using.
After installation, you can import it into your program.
import requests
print(requests.__version__)
If the package is installed correctly, Python will be able to import it.
Uninstalling a Package
You can remove an installed package using:
python -m pip uninstall requests
pip will normally ask you to confirm the removal.
If you no longer need a package, uninstalling it can help keep an environment clean.
Viewing Installed Packages
To see packages installed in your current environment, use:
python -m pip list
You will see information such as package names and installed versions.
This is useful when troubleshooting projects.
Viewing Package Information
You can inspect information about a particular package with:
python -m pip show requests
This can display information such as the installed version and installation location.
Why Package Versions Matter
Imagine that you build a Python application today and install version 2 of a package.
Six months later, someone installs the same project but receives version 3 of that package.
If the newer version changed something important, your program might stop working.
This is why Python projects commonly record their dependencies and their versions.
What Is a Virtual Environment?
A virtual environment is an isolated Python environment created for a particular project.
This allows different projects to use different package versions without interfering with each other.
Imagine you have two projects:
- Project A requires one version of a package.
- Project B requires another version.
Installing everything globally can create conflicts.
Virtual environments solve this by giving each project its own isolated collection of installed packages.
Creating a Virtual Environment
First create a folder for your project:
mkdir my_project
Move into the folder:
cd my_project
Then create a virtual environment:
python -m venv .venv
The .venv directory will contain the environment.
The name .venv is a common convention, but you could use
another name.
Activating a Virtual Environment on macOS or Linux
On macOS or Linux, use:
source .venv/bin/activate
Once activated, your terminal will usually show the environment name near the beginning of the command prompt.
You can then install packages and work on the project.
Activating a Virtual Environment on Windows
In Windows Command Prompt:
.venv\Scripts\activate
In PowerShell:
.venv\Scripts\Activate.ps1
The exact command can depend on your shell configuration.
Deactivating a Virtual Environment
When you are finished working with the environment, run:
deactivate
Your terminal will return to the normal Python environment.
Checking Which Python You Are Using
When working with virtual environments, it is useful to know which Python executable is active.
On macOS or Linux:
which python
On Windows:
where python
You can also ask Python directly where it is installed:
import sys
print(sys.executable)
This is particularly useful when you think a package has been installed but Python cannot find it.
Installing Packages Inside a Virtual Environment
Activate your virtual environment first.
source .venv/bin/activate
Then install your package:
python -m pip install requests
The package will be installed into that environment rather than your system-wide Python environment.
requirements.txt
A Python project may depend on several external packages.
Instead of telling someone to install each package manually, you can
create a file called requirements.txt.
For example:
requests==2.32.3
numpy==2.1.0
The file records packages that the project needs.
You can then install them with:
python -m pip install -r requirements.txt
This is especially useful when sharing projects with other developers.
Generating requirements.txt with pip freeze
You can use pip freeze to display installed packages and
their versions.
python -m pip freeze
You can save the result to a requirements file:
python -m pip freeze > requirements.txt
This creates a snapshot of the packages installed in the current environment.
pip freeze records installed packages. For larger projects,
you should still think carefully about which dependencies your application
actually needs.
Updating a Package
You can upgrade a package using:
python -m pip install --upgrade requests
Be careful when upgrading dependencies in an existing project. A newer version can sometimes introduce changes that require code modifications.
What Is PyPI?
PyPI stands for the Python Package Index.
It is a major repository for Python packages.
When you run a command such as:
python -m pip install requests
pip can retrieve the package from PyPI.
Before installing a package, however, you should consider whether it is trustworthy and whether it is actually necessary for your project.
Importing Third-Party Packages
Once a package has been installed, you can normally import it just like other Python modules.
For example:
import requests
You can then use the functionality provided by the package.
Installation and importing are two different steps:
Installation
↓
pip install package
Import
↓
import package
Installing a package does not automatically import it into every Python program.
ModuleNotFoundError
One common problem beginners encounter is:
ModuleNotFoundError
For example:
import requests
If the package is not available in the Python environment running your program, Python may produce an error similar to:
ModuleNotFoundError: No module named 'requests'
A common solution is to install the package into the correct environment:
python -m pip install requests
If the error continues, check which Python executable is running your program.
Virtual Environments and Your IDE
Modern Python IDEs can usually detect virtual environments.
However, sometimes your editor may be using a different Python interpreter from the one where you installed your package.
This can create a confusing situation:
"I installed the package, but Python says it doesn't exist."
In many cases, the problem is not the package itself. The IDE and terminal are using different Python environments.
Environment Variables
Some applications need configuration values such as API keys, database credentials or application settings.
These values should generally not be hard-coded directly into your source code.
For example, avoid writing:
API_KEY = "my-secret-key"
in a project that will be shared publicly.
Instead, applications often use environment variables or a secure secrets system.
You will encounter this concept frequently when working with APIs, web applications and cloud services.
.env Files and python-dotenv
A popular approach in local development is to store configuration values
in a .env file.
A simplified example might look like:
API_KEY=my-secret-key
A package such as python-dotenv can load these values into the
application's environment.
python -m pip install python-dotenv
Then:
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("API_KEY")
print(api_key)
.env files are excluded
from version control when appropriate.
.gitignore
When using Git, you can create a .gitignore file to tell Git
which files should not be tracked.
A Python project might include entries such as:
.venv/
__pycache__/
.env
This helps prevent virtual-environment files, Python cache files and local secrets from accidentally being committed.
Basic Python Project Structure
A simple project might eventually look like this:
my_project/
│
├── .venv/
├── .env
├── .gitignore
├── requirements.txt
├── main.py
└── utils.py
You do not need every file in every project. The structure depends on what you are building.
The important thing is to understand that a project can contain both your own code and external dependencies.
Standard Library vs Third-Party Packages
Python comes with a large standard library.
For example:
import math
import random
import datetime
import os
import json
These modules are generally available as part of Python itself.
Third-party packages are installed separately.
For example:
import numpy
import requests
import cv2
The exact package you need depends on your project.
Example: NumPy
NumPy is widely used for numerical and scientific computing in Python.
Install it with:
python -m pip install numpy
Then:
import numpy as np
numbers = np.array([10, 20, 30, 40])
print(numbers)
The as np syntax gives the imported module a shorter alias.
Example: OpenCV
OpenCV is a computer vision library.
This becomes particularly interesting if you want to work with images, cameras or object detection.
The package is commonly installed using:
python -m pip install opencv-python
But the import name is:
import cv2
Notice that the package installation name and the import name do not always have to be identical.
Packages and Robotics
Packages become extremely important when you begin building robotics applications.
Depending on your hardware and project, you may encounter packages for:
- GPIO control
- Serial communication
- Computer vision
- Numerical calculations
- Sensor data processing
- Machine learning
- Robotics frameworks
For example, a future agricultural robot could use Python packages to process camera images, analyze sensor readings and communicate with other components.
Packages and Agricultural AI
If you eventually build a crop-and-weed detection system, you will likely work with several specialized libraries.
A project could potentially involve tools for:
- Numerical arrays
- Image processing
- Data preparation
- Machine learning
- Deep learning
- Visualization
This is one reason understanding environments and package management is important before you move into advanced AI development.
Common Mistakes
1. Installing packages globally for every project
This can eventually create dependency conflicts. Virtual environments are usually a better approach for project-specific dependencies.
2. Installing the package into the wrong Python
You may have multiple Python installations. Using
python -m pip can help ensure pip is connected to the Python
interpreter you intend to use.
3. Forgetting to activate the environment
If you intended to install a package into a virtual environment but the environment wasn't active, the package may have been installed somewhere else.
4. Committing .env files
Never casually commit files containing real secrets.
5. Installing packages without understanding what they do
Don't install a package simply because you saw it in someone else's code. Understand why your project needs it.
6. Installing unnecessary packages
More dependencies can mean more complexity. Install what your project actually requires.
Practice Exercises
Exercise 1: Create an Environment
Create a new folder called python_practice and create a
virtual environment named .venv.
Exercise 2: Activate It
Activate the environment using the command appropriate for your operating system.
Exercise 3: Install a Package
Install the requests package.
Exercise 4: Check Your Packages
Use pip to display the packages installed in your environment.
Exercise 5: Create requirements.txt
Generate a requirements.txt file containing your environment's
installed packages.
Exercise 6: Check Your Python
Write a Python program that prints the location of the Python executable currently running your program.
Exercise 7: Project Structure
Create a small Python project containing:
main.pyutils.pyrequirements.txt.gitignore
Mini Project: A Clean Python Project
Let's combine the concepts from this module into a small project structure.
student_app/
│
├── .venv/
├── .gitignore
├── requirements.txt
├── main.py
└── utils.py
In utils.py:
def calculate_average(scores):
if not scores:
return 0
return sum(scores) / len(scores)
In main.py:
from utils import calculate_average
scores = [80, 75, 90, 85]
average = calculate_average(scores)
print("Average:", average)
This project does not require an external package, and that is an important lesson too: you should not install a package when Python's built-in features are enough.
Python Environments & Packages Quiz
Python Environments & Packages Summary
Python's ecosystem contains thousands of reusable packages. Understanding how to install and manage them is an essential skill for real-world development.
You learned:
- What Python packages are.
- What pip does.
- How to install and uninstall packages.
- How to inspect installed packages.
- Why package versions matter.
- What virtual environments are.
- How to create and activate a virtual environment.
- How to deactivate an environment.
- How to create and use requirements.txt.
- How to use pip freeze.
- How third-party packages are imported.
- How to troubleshoot ModuleNotFoundError.
- Why IDEs sometimes use the wrong interpreter.
- What environment variables are.
- Why secrets should not be hard-coded or publicly committed.
- How packages can support robotics and agricultural AI projects.
22. Python Projects
Congratulations! You have reached the project section of the Python course.
You have learned variables, data types, operators, conditions, loops, strings, lists, tuples, sets, dictionaries, functions, modules, file handling, exceptions, classes, dates, regular expressions, iterators, generators, decorators and package management.
Now it is time to combine those skills.
How to Learn From These Projects
Don't immediately copy the complete solution.
First read the problem and try to design your own solution.
A useful process is:
- Understand the problem.
- Break it into smaller tasks.
- Write pseudocode.
- Write the Python code.
- Run the program.
- Find and fix errors.
- Improve the program.
If you get stuck, look at the hints before looking at a complete solution.
Project 1: Calculator
Our first project is a simple calculator that allows the user to perform basic arithmetic operations.
What You Will Practice
- Variables
- Input
- Conditions
- Functions
- Operators
Requirements
Your calculator should allow the user to:
- Add two numbers
- Subtract two numbers
- Multiply two numbers
- Divide two numbers
Starter Version
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
return "Cannot divide by zero."
return a / b
print("Python Calculator")
first = float(input("Enter first number: "))
operator = input("Enter operator (+, -, *, /): ")
second = float(input("Enter second number: "))
if operator == "+":
print(add(first, second))
elif operator == "-":
print(subtract(first, second))
elif operator == "*":
print(multiply(first, second))
elif operator == "/":
print(divide(first, second))
else:
print("Invalid operator.")
Challenge
Improve the calculator so that it continues running until the user chooses to exit.
You can also add exponentiation using ** and a remainder
operation using %.
Project 2: Number Guessing Game
In this project, the computer chooses a secret number and the player tries to guess it.
What You Will Practice
- Variables
- Input
- Conditions
- while loops
- Random numbers
- Counters
Basic Version
import random
secret_number = random.randint(1, 100)
attempts = 0
print("Guess the number between 1 and 100.")
while True:
guess = int(input("Enter your guess: "))
attempts += 1
if guess < secret_number:
print("Too low.")
elif guess > secret_number:
print("Too high.")
else:
print("Correct!")
print("Attempts:", attempts)
break
Challenge
Improve the game by:
- Limiting the player to a certain number of attempts.
- Adding difficulty levels.
- Giving the player another round.
- Keeping track of the best score.
Project 3: Currency Converter
This project is particularly useful for practicing input, calculations, dictionaries and functions.
To keep the project simple, we'll use fixed example exchange rates.
Example
rates = {
"USD": 1,
"EUR": 0.92,
"GBP": 0.79,
"NGN": 1500
}
def convert(amount, from_currency, to_currency):
usd_amount = amount / rates[from_currency]
result = usd_amount * rates[to_currency]
return result
print("Currency Converter")
amount = float(input("Enter amount: "))
from_currency = input(
"From currency (USD/EUR/GBP/NGN): "
).upper()
to_currency = input(
"To currency (USD/EUR/GBP/NGN): "
).upper()
if from_currency in rates and to_currency in rates:
result = convert(
amount,
from_currency,
to_currency
)
print(
f"{amount:.2f} {from_currency} = "
f"{result:.2f} {to_currency}"
)
else:
print("Unsupported currency.")
Challenge
Add more currencies and allow the user to perform multiple conversions without restarting the program.
Project 4: Student Score Calculator
Now let's build something similar to the type of program you may encounter while learning Python: a student score analyzer.
Requirements
The program should collect scores and calculate:
- Total
- Average
- Highest score
- Lowest score
Example
scores = []
for subject in ["Biology", "Chemistry", "English", "Physics"]:
score = float(
input(f"Enter {subject} score: ")
)
scores.append(score)
total = sum(scores)
average = total / len(scores)
highest = max(scores)
lowest = min(scores)
print("Total:", total)
print("Average:", average)
print("Highest:", highest)
print("Lowest:", lowest)
Challenge
Turn the program into a menu-driven application.
For example:
1. Enter scores
2. Show total
3. Show average
4. Show highest score
5. Show lowest score
6. Exit
This will give you practice combining loops, functions, conditions and lists.
Project 5: To-Do List
Now we are going to build something closer to a small application.
A to-do list allows users to add, view and remove tasks.
What You Will Practice
- Lists
- Functions
- while loops
- Conditions
- User input
Example
tasks = []
def show_tasks():
if not tasks:
print("No tasks yet.")
return
for number, task in enumerate(tasks, start=1):
print(number, task)
while True:
print("\n1. Add task")
print("2. View tasks")
print("3. Remove task")
print("4. Exit")
choice = input("Choose an option: ")
if choice == "1":
task = input("Enter task: ")
tasks.append(task)
print("Task added.")
elif choice == "2":
show_tasks()
elif choice == "3":
show_tasks()
if tasks:
number = int(
input("Enter task number: ")
)
if 1 <= number <= len(tasks):
removed = tasks.pop(number - 1)
print("Removed:", removed)
else:
print("Invalid task number.")
elif choice == "4":
print("Goodbye!")
break
else:
print("Invalid option.")
Challenge
Add the ability to mark tasks as completed.
Then improve the project by saving tasks to a file so they are still available after the program closes.
Project 6: Quiz Application
A quiz application is an excellent project for combining dictionaries, lists, loops, conditions and functions.
Example
questions = [
{
"question": "What keyword creates a function?",
"answer": "def"
},
{
"question": "What data type stores True or False?",
"answer": "bool"
},
{
"question": "What keyword creates a loop that repeats while a condition is true?",
"answer": "while"
}
]
score = 0
for item in questions:
print(item["question"])
answer = input("Your answer: ").strip().lower()
if answer == item["answer"].lower():
print("Correct!")
score += 1
else:
print("Incorrect.")
print(
f"You scored {score} out of {len(questions)}."
)
Challenge
Add multiple-choice questions.
Then add:
- Different categories
- Difficulty levels
- A timer
- High scores
- Questions loaded from a JSON file
Project 7: Contact Book
Build a program that stores people's names and contact information.
A dictionary is a natural structure for this type of application.
Requirements
- Add a contact
- View contacts
- Search for a contact
- Update a contact
- Delete a contact
Starting Structure
contacts = {
"Ada": {
"phone": "08000000000",
"email": "ada@example.com"
}
}
Your challenge is to build the menu and functions around this data.
Project 8: Text File Analyzer
This project combines file handling with strings and basic statistics.
The program should open a text file and calculate:
- Number of characters
- Number of words
- Number of lines
Example
with open(
"notes.txt",
"r",
encoding="utf-8"
) as file:
content = file.read()
characters = len(content)
words = content.split()
lines = content.splitlines()
print("Characters:", characters)
print("Words:", len(words))
print("Lines:", len(lines))
Challenge
Add a word-frequency counter that shows how many times each word appears.
Final Python Project
Now it is time to build something larger.
Your final project should combine several concepts from this course rather than testing only one Python feature.
Recommended Final Project: Agricultural Field Monitor
Since Python can be used for agriculture, robotics and AI, an excellent project is a simple agricultural field monitoring application.
The first version does not need artificial intelligence or physical hardware.
Start with a software simulation.
Project Idea
Create a Python application that stores information about agricultural plots and monitors simulated environmental readings.
The application could record:
- Field name
- Crop planted
- Temperature
- Soil moisture
- Humidity
- Plant growth observations
Example Data
field = {
"name": "North Field",
"crop": "Maize",
"temperature": 29.5,
"soil_moisture": 42,
"humidity": 70
}
Possible Rules
Your program could check whether the soil moisture is too low.
if field["soil_moisture"] < 30:
print("Warning: Soil may need irrigation.")
else:
print("Soil moisture is acceptable.")
Turn It Into an Application
Add a menu such as:
================================
AGRICULTURAL FIELD MONITOR
================================
1. Add field
2. View fields
3. Record sensor reading
4. Check field status
5. View reports
6. Save data
7. Exit
Concepts You Can Use
- Variables
- Data types
- Conditions
- Loops
- Lists
- Dictionaries
- Functions
- Modules
- File handling
- JSON
- Exception handling
- Classes
This is much closer to how real software is developed: several Python concepts working together rather than one isolated feature.
Taking the Project Further With Classes
Once your procedural version works, you can redesign it using classes.
class Field:
def __init__(
self,
name,
crop,
temperature,
soil_moisture,
humidity
):
self.name = name
self.crop = crop
self.temperature = temperature
self.soil_moisture = soil_moisture
self.humidity = humidity
def check_status(self):
if self.soil_moisture < 30:
return "Needs irrigation"
return "Healthy"
field = Field(
"North Field",
"Maize",
29.5,
42,
70
)
print(field.name)
print(field.check_status())
Now your project is using object-oriented programming as well.
Saving the Project Data
You can save field information using JSON.
import json
field = {
"name": "North Field",
"crop": "Maize",
"temperature": 29.5,
"soil_moisture": 42,
"humidity": 70
}
with open(
"field.json",
"w",
encoding="utf-8"
) as file:
json.dump(field, file, indent=4)
Later, your program can load the data again.
with open(
"field.json",
"r",
encoding="utf-8"
) as file:
field = json.load(file)
print(field["crop"])
Taking the Project to the Next Level
Once the software simulation works, you can gradually make the project more realistic.
For example:
- Use real sensor data.
- Connect an Arduino or Raspberry Pi.
- Store readings over time.
- Display the data in charts.
- Add a camera.
- Process images with OpenCV.
- Train an object-detection model.
- Detect crops or weeds.
- Connect the system to an agricultural robot.
Notice the progression:
Python basics
↓
Python application
↓
File/data storage
↓
Sensors
↓
Computer vision
↓
AI
↓
Robotics
This is how a simple programming project can eventually become the foundation for a much larger engineering system.
Good Project Habits
As your programs become larger, start developing professional habits.
1. Use Functions
Don't put your entire program inside one enormous block of code.
2. Use Meaningful Names
student_scores = [80, 90, 75]
is easier to understand than:
x = [80, 90, 75]
3. Handle Errors
Assume users will enter unexpected information.
4. Save Data Carefully
If your application stores important information, make sure data is not accidentally overwritten or lost.
5. Test Small Pieces
Test individual functions before combining everything.
6. Use Version Control
Git can help you track changes and return to earlier versions of your project.
7. Read Error Messages
An error message is not simply Python telling you that you failed. It is information about what Python encountered.
Final Challenge
Build your own Python application without following a complete tutorial.
Choose a problem you care about and design a solution.
For example:
- Expense tracker
- Inventory manager
- Study planner
- Weather information tool
- Farm record manager
- Plant observation tracker
- Sensor monitoring simulator
- Simple robotics control simulator
You Have Completed the Python Course
You have now moved through the major foundations of Python.
More importantly, you have reached the point where you can begin building your own programs instead of only following examples.
You Can Now Work With:
- Variables and data types
- Operators
- Conditions
- Loops
- Strings
- Lists
- Tuples
- Sets
- Dictionaries
- Functions
- Modules
- Files
- Exceptions
- Classes and objects
- Dates and times
- Regular expressions
- Iterators and generators
- Decorators
- Packages and virtual environments
But completing a Python course does not mean you are finished learning Python.
It means you now have a foundation from which you can explore more specialized areas.
What Should You Learn Next?
Your next step should depend on what you want to build.
For Web Development
Explore frameworks such as Flask or Django.
For Data Science
Explore NumPy, pandas, Matplotlib and related tools.
For Artificial Intelligence
Learn NumPy, data processing, machine learning and deep learning.
For Computer Vision
Learn OpenCV and image processing before moving deeper into object detection.
For Robotics
Continue with Python while learning electronics, sensors, control systems, embedded programming and robotics frameworks.
For Agricultural Technology
Combine programming with agriculture, sensors, computer vision, data analysis and eventually robotics.
Python Projects Quiz
Python Projects Summary
Projects are where your Python knowledge starts becoming practical.
In this module you worked through projects involving:
- Calculators
- Games
- Currency conversion
- Student score analysis
- To-do lists
- Quiz applications
- Contact books
- File analysis
- Agricultural field monitoring
You also learned how a simple Python application can gradually evolve into a larger system involving files, sensors, computer vision, AI and robotics.
22. Python Projects
Congratulations! You have reached the project section of the Python course.
You have learned variables, data types, operators, conditions, loops, strings, lists, tuples, sets, dictionaries, functions, modules, file handling, exceptions, classes, dates, regular expressions, iterators, generators, decorators and package management.
Now it is time to combine those skills.
How to Learn From These Projects
Don't immediately copy the complete solution.
First read the problem and try to design your own solution.
A useful process is:
- Understand the problem.
- Break it into smaller tasks.
- Write pseudocode.
- Write the Python code.
- Run the program.
- Find and fix errors.
- Improve the program.
If you get stuck, look at the hints before looking at a complete solution.
Project 1: Calculator
Our first project is a simple calculator that allows the user to perform basic arithmetic operations.
What You Will Practice
- Variables
- Input
- Conditions
- Functions
- Operators
Requirements
Your calculator should allow the user to:
- Add two numbers
- Subtract two numbers
- Multiply two numbers
- Divide two numbers
Starter Version
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
return "Cannot divide by zero."
return a / b
print("Python Calculator")
first = float(input("Enter first number: "))
operator = input("Enter operator (+, -, *, /): ")
second = float(input("Enter second number: "))
if operator == "+":
print(add(first, second))
elif operator == "-":
print(subtract(first, second))
elif operator == "*":
print(multiply(first, second))
elif operator == "/":
print(divide(first, second))
else:
print("Invalid operator.")
Challenge
Improve the calculator so that it continues running until the user chooses to exit.
You can also add exponentiation using ** and a remainder
operation using %.
Project 2: Number Guessing Game
In this project, the computer chooses a secret number and the player tries to guess it.
What You Will Practice
- Variables
- Input
- Conditions
- while loops
- Random numbers
- Counters
Basic Version
import random
secret_number = random.randint(1, 100)
attempts = 0
print("Guess the number between 1 and 100.")
while True:
guess = int(input("Enter your guess: "))
attempts += 1
if guess < secret_number:
print("Too low.")
elif guess > secret_number:
print("Too high.")
else:
print("Correct!")
print("Attempts:", attempts)
break
Challenge
Improve the game by:
- Limiting the player to a certain number of attempts.
- Adding difficulty levels.
- Giving the player another round.
- Keeping track of the best score.
Project 3: Currency Converter
This project is particularly useful for practicing input, calculations, dictionaries and functions.
To keep the project simple, we'll use fixed example exchange rates.
Example
rates = {
"USD": 1,
"EUR": 0.92,
"GBP": 0.79,
"NGN": 1500
}
def convert(amount, from_currency, to_currency):
usd_amount = amount / rates[from_currency]
result = usd_amount * rates[to_currency]
return result
print("Currency Converter")
amount = float(input("Enter amount: "))
from_currency = input(
"From currency (USD/EUR/GBP/NGN): "
).upper()
to_currency = input(
"To currency (USD/EUR/GBP/NGN): "
).upper()
if from_currency in rates and to_currency in rates:
result = convert(
amount,
from_currency,
to_currency
)
print(
f"{amount:.2f} {from_currency} = "
f"{result:.2f} {to_currency}"
)
else:
print("Unsupported currency.")
Challenge
Add more currencies and allow the user to perform multiple conversions without restarting the program.
Project 4: Student Score Calculator
Now let's build something similar to the type of program you may encounter while learning Python: a student score analyzer.
Requirements
The program should collect scores and calculate:
- Total
- Average
- Highest score
- Lowest score
Example
scores = []
for subject in ["Biology", "Chemistry", "English", "Physics"]:
score = float(
input(f"Enter {subject} score: ")
)
scores.append(score)
total = sum(scores)
average = total / len(scores)
highest = max(scores)
lowest = min(scores)
print("Total:", total)
print("Average:", average)
print("Highest:", highest)
print("Lowest:", lowest)
Challenge
Turn the program into a menu-driven application.
For example:
1. Enter scores
2. Show total
3. Show average
4. Show highest score
5. Show lowest score
6. Exit
This will give you practice combining loops, functions, conditions and lists.
Project 5: To-Do List
Now we are going to build something closer to a small application.
A to-do list allows users to add, view and remove tasks.
What You Will Practice
- Lists
- Functions
- while loops
- Conditions
- User input
Example
tasks = []
def show_tasks():
if not tasks:
print("No tasks yet.")
return
for number, task in enumerate(tasks, start=1):
print(number, task)
while True:
print("\n1. Add task")
print("2. View tasks")
print("3. Remove task")
print("4. Exit")
choice = input("Choose an option: ")
if choice == "1":
task = input("Enter task: ")
tasks.append(task)
print("Task added.")
elif choice == "2":
show_tasks()
elif choice == "3":
show_tasks()
if tasks:
number = int(
input("Enter task number: ")
)
if 1 <= number <= len(tasks):
removed = tasks.pop(number - 1)
print("Removed:", removed)
else:
print("Invalid task number.")
elif choice == "4":
print("Goodbye!")
break
else:
print("Invalid option.")
Challenge
Add the ability to mark tasks as completed.
Then improve the project by saving tasks to a file so they are still available after the program closes.
Project 6: Quiz Application
A quiz application is an excellent project for combining dictionaries, lists, loops, conditions and functions.
Example
questions = [
{
"question": "What keyword creates a function?",
"answer": "def"
},
{
"question": "What data type stores True or False?",
"answer": "bool"
},
{
"question": "What keyword creates a loop that repeats while a condition is true?",
"answer": "while"
}
]
score = 0
for item in questions:
print(item["question"])
answer = input("Your answer: ").strip().lower()
if answer == item["answer"].lower():
print("Correct!")
score += 1
else:
print("Incorrect.")
print(
f"You scored {score} out of {len(questions)}."
)
Challenge
Add multiple-choice questions.
Then add:
- Different categories
- Difficulty levels
- A timer
- High scores
- Questions loaded from a JSON file
Project 7: Contact Book
Build a program that stores people's names and contact information.
A dictionary is a natural structure for this type of application.
Requirements
- Add a contact
- View contacts
- Search for a contact
- Update a contact
- Delete a contact
Starting Structure
contacts = {
"Ada": {
"phone": "08000000000",
"email": "ada@example.com"
}
}
Your challenge is to build the menu and functions around this data.
Project 8: Text File Analyzer
This project combines file handling with strings and basic statistics.
The program should open a text file and calculate:
- Number of characters
- Number of words
- Number of lines
Example
with open(
"notes.txt",
"r",
encoding="utf-8"
) as file:
content = file.read()
characters = len(content)
words = content.split()
lines = content.splitlines()
print("Characters:", characters)
print("Words:", len(words))
print("Lines:", len(lines))
Challenge
Add a word-frequency counter that shows how many times each word appears.
Final Python Project
Now it is time to build something larger.
Your final project should combine several concepts from this course rather than testing only one Python feature.
Recommended Final Project: Agricultural Field Monitor
Since Python can be used for agriculture, robotics and AI, an excellent project is a simple agricultural field monitoring application.
The first version does not need artificial intelligence or physical hardware.
Start with a software simulation.
Project Idea
Create a Python application that stores information about agricultural plots and monitors simulated environmental readings.
The application could record:
- Field name
- Crop planted
- Temperature
- Soil moisture
- Humidity
- Plant growth observations
Example Data
field = {
"name": "North Field",
"crop": "Maize",
"temperature": 29.5,
"soil_moisture": 42,
"humidity": 70
}
Possible Rules
Your program could check whether the soil moisture is too low.
if field["soil_moisture"] < 30:
print("Warning: Soil may need irrigation.")
else:
print("Soil moisture is acceptable.")
Turn It Into an Application
Add a menu such as:
================================
AGRICULTURAL FIELD MONITOR
================================
1. Add field
2. View fields
3. Record sensor reading
4. Check field status
5. View reports
6. Save data
7. Exit
Concepts You Can Use
- Variables
- Data types
- Conditions
- Loops
- Lists
- Dictionaries
- Functions
- Modules
- File handling
- JSON
- Exception handling
- Classes
This is much closer to how real software is developed: several Python concepts working together rather than one isolated feature.
Taking the Project Further With Classes
Once your procedural version works, you can redesign it using classes.
class Field:
def __init__(
self,
name,
crop,
temperature,
soil_moisture,
humidity
):
self.name = name
self.crop = crop
self.temperature = temperature
self.soil_moisture = soil_moisture
self.humidity = humidity
def check_status(self):
if self.soil_moisture < 30:
return "Needs irrigation"
return "Healthy"
field = Field(
"North Field",
"Maize",
29.5,
42,
70
)
print(field.name)
print(field.check_status())
Now your project is using object-oriented programming as well.
Saving the Project Data
You can save field information using JSON.
import json
field = {
"name": "North Field",
"crop": "Maize",
"temperature": 29.5,
"soil_moisture": 42,
"humidity": 70
}
with open(
"field.json",
"w",
encoding="utf-8"
) as file:
json.dump(field, file, indent=4)
Later, your program can load the data again.
with open(
"field.json",
"r",
encoding="utf-8"
) as file:
field = json.load(file)
print(field["crop"])
Taking the Project to the Next Level
Once the software simulation works, you can gradually make the project more realistic.
For example:
- Use real sensor data.
- Connect an Arduino or Raspberry Pi.
- Store readings over time.
- Display the data in charts.
- Add a camera.
- Process images with OpenCV.
- Train an object-detection model.
- Detect crops or weeds.
- Connect the system to an agricultural robot.
Notice the progression:
Python basics
↓
Python application
↓
File/data storage
↓
Sensors
↓
Computer vision
↓
AI
↓
Robotics
This is how a simple programming project can eventually become the foundation for a much larger engineering system.
Good Project Habits
As your programs become larger, start developing professional habits.
1. Use Functions
Don't put your entire program inside one enormous block of code.
2. Use Meaningful Names
student_scores = [80, 90, 75]
is easier to understand than:
x = [80, 90, 75]
3. Handle Errors
Assume users will enter unexpected information.
4. Save Data Carefully
If your application stores important information, make sure data is not accidentally overwritten or lost.
5. Test Small Pieces
Test individual functions before combining everything.
6. Use Version Control
Git can help you track changes and return to earlier versions of your project.
7. Read Error Messages
An error message is not simply Python telling you that you failed. It is information about what Python encountered.
Final Challenge
Build your own Python application without following a complete tutorial.
Choose a problem you care about and design a solution.
For example:
- Expense tracker
- Inventory manager
- Study planner
- Weather information tool
- Farm record manager
- Plant observation tracker
- Sensor monitoring simulator
- Simple robotics control simulator
You Have Completed the Python Course
You have now moved through the major foundations of Python.
More importantly, you have reached the point where you can begin building your own programs instead of only following examples.
You Can Now Work With:
- Variables and data types
- Operators
- Conditions
- Loops
- Strings
- Lists
- Tuples
- Sets
- Dictionaries
- Functions
- Modules
- Files
- Exceptions
- Classes and objects
- Dates and times
- Regular expressions
- Iterators and generators
- Decorators
- Packages and virtual environments
But completing a Python course does not mean you are finished learning Python.
It means you now have a foundation from which you can explore more specialized areas.
What Should You Learn Next?
Your next step should depend on what you want to build.
For Web Development
Explore frameworks such as Flask or Django.
For Data Science
Explore NumPy, pandas, Matplotlib and related tools.
For Artificial Intelligence
Learn NumPy, data processing, machine learning and deep learning.
For Computer Vision
Learn OpenCV and image processing before moving deeper into object detection.
For Robotics
Continue with Python while learning electronics, sensors, control systems, embedded programming and robotics frameworks.
For Agricultural Technology
Combine programming with agriculture, sensors, computer vision, data analysis and eventually robotics.
Python Projects Quiz
Python Projects Summary
Projects are where your Python knowledge starts becoming practical.
In this module you worked through projects involving:
- Calculators
- Games
- Currency conversion
- Student score analysis
- To-do lists
- Quiz applications
- Contact books
- File analysis
- Agricultural field monitoring
You also learned how a simple Python application can gradually evolve into a larger system involving files, sensors, computer vision, AI and robotics.

0 Comments