Python by Example Book 1 (Fundamentals and Basics)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 57

Python by Example

Book 1

(Fundamentals and Basics)


(First Draft)

Compiled & Edited


by
Muhammad Nadeem Khokhar
([email protected])

July 2023
Disclaimer
This book has been created using various tools, including AI tools,
development tools, and other services. While the book's development
has involved the utilization of these tools, it is important to note that
the content has been planned and organized by the author.

Efforts have been made to ensure the accuracy and completeness


of the information presented. However, absolute correctness or
suitability for specific purposes cannot be guaranteed. Readers are
advised to exercise their own judgment and discretion when applying
the information contained in this book and are requested to share
their comments and suggestions with the author through email.

Thank you for your understanding and support.


Contents
Chapter 1: Introduction to Python ................................................................ 1
1.1 What is Python? .................................................................................. 1
1.2 Setting up Python environment .......................................................... 2
1.3 Running Python code .......................................................................... 6
Chapter 2: Variables and Data Types ............................................................ 8
2.1 Working with numbers ....................................................................... 8
2.2 Strings and text manipulation ........................................................... 10
2.3 Boolean values and logical operations.............................................. 13
Chapter 3: Control Flow .............................................................................. 16
3.1 Conditional statements (if, else, elif) ................................................ 16
3.2 Looping with while and for ............................................................... 19
3.3 Break and continue statements ........................................................ 21
Chapter 4: Functions ................................................................................... 23
4.1 Creating and using functions............................................................. 23
4.2 Parameters and return values........................................................... 24
4.3 Function scope and global variables ................................................. 26
Chapter 5: Input and Output....................................................................... 29
5.1 Reading input from the user ............................................................. 29
5.2 Writing data to files........................................................................... 30
5.3 Formatting output ............................................................................. 34
Chapter 6: Exception Handling.................................................................... 37
6.1 Handling errors with try-except ........................................................ 37
6.2 Custom exceptions ............................................................................ 39
Chapter 7: Mini Projects and Exercises ....................................................... 42
7.1 Simple projects put the acquired knowledge into practice .............. 42
7.2 Coding exercises to reinforce knowledge ......................................... 48
Python by Example (Book 1: Fundamentals and Basics)

Chapter 1: Introduction to Python


In this chapter, we'll introduce you to the key aspects of Python, from
understanding what Python is to setting up your Python environment and running
your first lines of Python code. Python's charm lies in its ability to empower you to
create powerful and elegant solutions to a vast array of problems.

1.1 What is Python?

Python is a high-level, versatile, and easy-to-learn programming language that


has gained tremendous popularity among developers and learners worldwide.
Created by Guido van Rossum and first released in 1991, Python's design philosophy
emphasizes code readability and simplicity, making it an excellent choice for
beginners and experienced programmers alike.

Python's wide adoption and popularity can be attributed to several key factors:

 Easy to Read and Write: Python's clean and straightforward syntax


resembles English-like commands, making it highly readable. This readability
reduces the complexity of code and facilitates easy maintenance and
collaboration.
 Highly Versatile: Python can be used for a wide range of applications, from
web development and data analysis to scientific computing, artificial
intelligence, and automation. Its flexibility makes it a go-to language for
various industries and domains.
 Vast Standard Library: Python comes with an extensive standard library that
offers pre-built modules and functions for various tasks, saving developers
time and effort. This vast collection of modules provides solutions for tasks
like file handling, networking, and working with different data formats.
 Strong Community Support: Python boasts a vibrant and supportive
community of developers, making it easier for newcomers to seek help,
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 1|P a g e
Python by Example (Book 1: Fundamentals and Basics)

share knowledge, and find numerous online resources, tutorials, and


documentation.
 Cross-Platform Compatibility: Python is a cross-platform language, which
means that code written on one operating system can run seamlessly on
other platforms without modifications, including Windows, macOS, and
Linux.
 Rapid Prototyping: Python's ease of use and quick development cycle make
it an ideal language for rapid prototyping. It allows developers to test ideas
and concepts efficiently, leading to faster project iterations.
 Open Source: Python is an open-source language, which means the source
code is freely available and can be modified and distributed. This fosters a
collaborative development environment, driving continuous improvement
and innovation.

Python 2 vs. Python 3: It's essential to note that there are two major versions of
Python: Python 2 and Python 3. Python 2 was widely used in the past, but its
development and support officially ended on January 1, 2020. Python 3, with its
numerous improvements, is the current and recommended version for all new
projects. In this book, we will focus on Python 3 as it is the modern and more
actively maintained version of the language.

Getting Started: To begin your Python journey, you'll need to install Python on
your computer. Python can be downloaded for free from the official Python website
(www.python.org) and is available for all major operating systems. The installation
process is straightforward, and once Python is installed, you can start writing and
executing Python code.

1.2 Setting up Python environment

Before we embark on our Python journey, it's crucial to set up the Python
environment on your computer. In this section, we'll guide you through the
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 2|P a g e
Python by Example (Book 1: Fundamentals and Basics)

installation process, ensuring you have everything you need to start writing and
executing Python code.

Downloading Python: To get started, head over to the official Python website
(www.python.org) and navigate to the "Downloads" section. Here, you'll find the
latest version of Python available for various operating systems, including Windows,
macOS, and Linux.

Choosing the Right Version: Python has two major versions: Python 2 and
Python 3. While Python 2 was widely used in the past, it is no longer supported, and
its development has ceased. Therefore, it's essential to choose Python 3 for all new
projects. The website will likely highlight the latest Python 3 version, making it easier
for you to make the right choice.

Installing Python: Once you've downloaded the Python installer for your
operating system, run the installation program. The installation process is
straightforward and typically involves accepting the license agreement, choosing the
installation location, and selecting the optional features you want to include.

Adding Python to Path (Windows Users): For Windows users, there is an


essential step to ensure Python is accessible from the command line. During the
installation process, you'll have the option to "Add Python [version] to PATH."
Enabling this option allows you to run Python commands from the Command
Prompt or PowerShell without specifying the full path to the Python executable.

Verifying the Installation: Once the installation is complete, you can verify
whether Python is successfully installed on your system. Open the Command Prompt
or Terminal and type "python --version" (without quotes) and press Enter. If Python
is installed correctly, the version number will be displayed in the output.

Accessing the Python Interpreter: Python comes with an interactive interpreter,


which allows you to execute Python code line by line. To access the Python
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 3|P a g e
Python by Example (Book 1: Fundamentals and Basics)

interpreter, open the Command Prompt or Terminal and type "python" (without
quotes). Press Enter, and you should see the Python prompt (">>>"), indicating that
you are now in the Python interactive mode.

Writing Your First Python Program: Congratulations! You have set up the Python
environment, and you're ready to write your first Python program. You can use any
text editor or an Integrated Development Environment (IDE) to write Python code.
Popular text editors like Visual Studio Code, Sublime Text, or Atom have Python
support, while dedicated Python IDEs like PyCharm offer a full suite of development
tools.

Anaconda

Anaconda is a popular distribution of Python and other essential data science


libraries. It is widely used by data scientists, researchers, and developers who work
extensively with data analysis, machine learning, and scientific computing. Anaconda
simplifies the installation and management of Python and related libraries, making it
a powerful tool for data-driven tasks.

Key Features of Anaconda:

 Package Management: Anaconda comes with its package manager called


"conda," which allows users to easily install, update, and manage Python
libraries and dependencies. Conda ensures that all libraries and packages are
compatible with each other, preventing version conflicts.
 Data Science Libraries: Anaconda includes a comprehensive set of data
science libraries, such as NumPy, Pandas, SciPy, scikit-learn, Matplotlib,
Jupyter, and more. These libraries provide robust tools for data
manipulation, analysis, visualization, and machine learning.
 Jupyter Notebooks: Anaconda comes bundled with Jupyter Notebook, an
interactive web-based interface that allows users to create and share

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 4|P a g e


Python by Example (Book 1: Fundamentals and Basics)

documents containing live code, visualizations, and explanatory text. Jupyter


Notebooks are widely used for data exploration, prototyping, and presenting
data analysis.
 Cross-Platform Compatibility: Anaconda is available for Windows, macOS,
and Linux, making it a cross-platform solution that ensures consistent
performance and behavior across different operating systems.
 Conda Environments: One of the most significant advantages of Anaconda is
the ability to create isolated environments for different projects. Conda
environments allow users to have separate Python and library installations
for each project, ensuring project-specific dependencies and avoiding
conflicts.
 Data Visualization Tools: Alongside its data science libraries, Anaconda
includes data visualization tools like Matplotlib, Seaborn, and Plotly, allowing
users to create interactive and visually appealing plots and graphs.

Anaconda Navigator: Anaconda Navigator is a user-friendly graphical interface


that comes with Anaconda, making it easier for users to navigate and manage their
Python environments and packages. It provides a central hub where users can
launch Jupyter Notebook, access their installed packages, and create and manage
conda environments, all through a simple and intuitive graphical interface.

When to Use Anaconda: Anaconda is an excellent choice for data scientists,


researchers, and developers working in data-intensive domains. If your work
involves data analysis, machine learning, scientific computing, or any data-related
tasks, Anaconda can streamline your workflow and provide a seamless experience. If
you're new to Python and want to dive into data science and machine learning,
Anaconda can save you time and effort by providing a pre-configured environment
with all the necessary libraries readily available.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 5|P a g e


Python by Example (Book 1: Fundamentals and Basics)

1.3 Running Python code

Congratulations on setting up your Python environment! Now that you have


Python installed on your computer, it's time to dive into the exciting world of Python
programming. In this section, we'll explore various methods of running Python code,
from the interactive Python interpreter to executing scripts from the command line.

The Interactive Python Interpreter: The Python interpreter provides an


interactive environment where you can write and execute Python code line by line.
To access the Python interpreter, open the Command Prompt (Windows) or
Terminal (macOS and Linux) and type "python" (without quotes). Press Enter, and
you should see the Python prompt, represented by ">>>".

In the interactive mode, you can enter Python expressions and statements
directly, and Python will execute them immediately, displaying the output right
away. This allows you to experiment with Python syntax and test code snippets
quickly.

To exit the interactive mode, type "exit()" (without quotes) and press Enter.

Executing Python Scripts: While the interactive interpreter is useful for testing
small code snippets, most Python projects involve writing larger scripts or programs.
Python scripts are files with a ".py" extension that contain a sequence of Python
statements. These scripts can be executed from the command line or within an
Integrated Development Environment (IDE).

To run a Python script from the command line, navigate to the directory where
the script is saved using the "cd" command (Change Directory), and then type
"python script_name.py" (without quotes). Press Enter, and Python will execute the
script, displaying the output in the command line.

For example, if you have a script named "hello.py", you can run it by typing:

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 6|P a g e


Python by Example (Book 1: Fundamentals and Basics)

python hello.py

Integrated Development Environments (IDEs): An Integrated Development


Environment (IDE) provides a comprehensive set of tools to facilitate code
development, debugging, and execution. IDEs offer features like code highlighting,
code completion, debugging, and project management, enhancing the overall
development experience.

Popular Python IDEs include PyCharm, Visual Studio Code (with Python
extension), and IDLE (Python's built-in IDE). These IDEs allow you to write Python
code, run scripts, and manage projects seamlessly, all within a single interface.

Jupyter Notebooks: As mentioned earlier, Anaconda comes with Jupyter


Notebook, which provides an interactive environment for creating and sharing
documents containing live Python code, visualizations, and explanatory text. Jupyter
Notebooks are widely used for data exploration, prototyping, and presenting data
analysis.

To start Jupyter Notebook, open the Command Prompt (Windows) or Terminal


(macOS and Linux) and type "jupyter notebook" (without quotes). Press Enter, and
your default web browser will open, displaying the Jupyter Notebook interface. From
here, you can create new notebooks and execute code cells interactively.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 7|P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 2: Variables and Data Types


In the world of programming, variables are like containers that hold valuable
information. Imagine them as labeled boxes storing data that our programs need to
work with. Understanding how to define and manipulate variables and work with
different data types is fundamental to solving real-world problems with code. So,
let's unlock the power of Python's variables and data types, and learn how to
unleash their potential in our programs!

2.1 Working with numbers

In Python, numbers play a crucial role as they allow us to perform a wide range
of mathematical operations and computations. Whether it's basic arithmetic,
complex mathematical algorithms, or data analysis, Python's versatility with
numbers makes it an exceptional choice for various applications.

Python supports several numeric data types to represent different kinds of


numbers. The main numeric data types are:

Integers (int): Integers are whole numbers, positive or negative, without any
fractional parts. For example, 5, -20, and 0 are all integers in Python.

Floating-Point Numbers (float): Floating-point numbers represent real numbers


with fractional parts. They are written with a decimal point or in scientific notation,
such as 3.14, -2.5, or 2.0e3.

Basic Arithmetic Operations:

Python allows us to perform standard arithmetic operations on numeric data


types:

# Addition
result_add = 5 + 3
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 8|P a g e
Python by Example (Book 1: Fundamentals and Basics)

print(result_add) # Output: 8

# Subtraction
result_sub = 10 - 4
print(result_sub) # Output: 6

# Multiplication
result_mul = 2 * 6
print(result_mul) # Output: 12

# Division
# Note - Division always returns a float
result_div = 10 / 2
print(result_div) # Output: 5.0

# Floor Division
result_floor_div = 10 // 3
print(result_floor_div) # Output: 3

# Modulo (remainder)
result_mod = 10 % 3
print(result_mod) # Output: 1

# Exponentiation
result_exp = 2 ** 3
print(result_exp) # Output: 8

Type Conversion:

Sometimes, we need to convert between numeric data types. Python provides


functions like `int()`, `float()`, and `str()` to perform type conversions:

# Converting float to int


float_num = 3.5
int_num = int(float_num)
print(int_num) # Output: 3

# Converting int to float


int_num = 10
float_num = float(int_num)
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 9|P a g e
Python by Example (Book 1: Fundamentals and Basics)

print(float_num) # Output: 10.0

# Converting int/float to string


num = 5
num_str = str(num)
print(num_str) # Output: "5"

Importing the math Module:


For more advanced mathematical operations, Python provides the `math`
module. You can use it by importing it at the beginning of your script:

import math

# Example: Square root


x = 25
sqrt_x = math.sqrt(x)
print(sqrt_x) # Output: 5.0

2.2 Strings and text manipulation

In Python, strings are a fundamental data type used to represent text. From
simple sentences to complex data parsing, strings play a vital role in handling textual
information in your programs.

Creating Strings:

You can create strings in Python by enclosing text in either single quotes (' '),
double quotes (" "), or triple quotes (''' ''') for multi-line strings.

# Single and double quotes


single_quote_str = 'Hello, World!'
double_quote_str = "Python is amazing!"

# Multi-line strings with triple quotes


multi_line_str = '''This is a multi-line string.
It can span across multiple lines.
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 10 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

Very convenient!'''

String Concatenation and Repetition:

String concatenation involves joining two or more strings together. In Python,


you can achieve this using the `+` operator.

str1 = "Hello"
str2 = "Python"
result_str = str1 + " " + str2
print(result_str) # Output: "Hello Python"

You can also repeat a string by using the `*` operator.

original_str = "Python"
repeated_str = original_str * 3
print(repeated_str) # Output: "PythonPythonPython"

String Indexing and Slicing:

Python allows you to access individual characters in a string using indexing. The
index starts from 0 for the first character, -1 for the last character, -2 for the second
last character, and so on.

text = "Python is fun!"


print(text[0]) # Output: "P"
print(text[-1]) # Output: "!"
print(text[7]) # Output: "i"

You can also extract a portion of a string using slicing.

text = "Python is fun!"


substring = text[7:9]
print(substring) # Output: "is"

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 11 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

String Methods:

Python provides a plethora of built-in string methods that allow you to


manipulate and analyze strings.

text = "Python is fun!"

# Length of the string


length = len(text)
print(length) # Output: 14

# Convert to lowercase and uppercase


lowercase_text = text.lower()
uppercase_text = text.upper()
print(lowercase_text) # Output: "python is fun!"
print(uppercase_text) # Output: "PYTHON IS FUN!"

# Count occurrences of a substring


count_is = text.count("is")
print(count_is) # Output: 1

# Check if a string starts or ends with a specific substring


print(text.startswith("Python")) # Output: True
print(text.endswith("fun")) # Output: True

String Formatting:

String formatting allows you to create dynamic strings by inserting variables or


values into a template string.

name = "Nadeem"
age = 55

# Using f-string (Python 3.6+)


formatted_str = f"My name is {name} and I am {age} years old."
print(formatted_str)
# Output: "My name is Nadeem and I am 55 years old."

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 12 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

2.3 Boolean values and logical operations

In Python, Boolean values are a fundamental concept used for decision-making


and controlling the flow of a program. Boolean data type represents two states:
`True` and `False`, which are used to evaluate conditions and make logical decisions.
Here we'll explore Boolean values, logical operations, and how they enable us to
build more sophisticated and dynamic programs.

Boolean Values:

Boolean values represent the truth of a statement. The values `True` and `False`
are the two Boolean literals in Python. They are essential in control flow, such as if-
statements and loops, where actions depend on whether certain conditions are true
or false.

is_raining = True
is_sunny = False

print(is_raining) # Output: True


print(is_sunny) # Output: False

Comparison Operators:

Comparison operators are used to compare values and evaluate conditions. The
result of a comparison is a Boolean value (`True` or `False`). Here are the comparison
operators:

 `==`: Equal to
 `!=`: Not equal to
 `>`: Greater than
 `<`: Less than
 `>=`: Greater than or equal to
 `<=`: Less than or equal to
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 13 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

Example:

x = 10
y = 5

print(x == y) # Output: False


print(x != y) # Output: True
print(x > y) # Output: True
print(x < y) # Output: False
print(x >= y) # Output: True
print(x <= y) # Output: False

Logical Operators:

Logical operators allow us to combine multiple Boolean expressions and evaluate


the truth value. Python supports three main logical operators: `and`, `or`, and `not`.

 `and`: Returns `True` if both expressions are `True`.


 `or`: Returns `True` if at least one of the expressions is `True`.
 `not`: Returns the opposite Boolean value of the expression following it.

Example:

x = 10
y = 5

print(x > 0 and y < 10) # Output: True (both conditions are True)
print(x > 10 or y < 5) # Output: False (both conditions are False)
print(not x > y) # Output: True (opposite of the expression)

Short-Circuit Evaluation:

Python uses short-circuit evaluation for logical operators. In `and` operations, if


the first expression is `False`, the second expression is not evaluated, as the entire
expression will be `False`. Similarly, in `or` operations, if the first expression is `True`,
the second expression is not evaluated, as the entire expression will be `True`.
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 14 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

Example:

a = 5
b = 0

# In the 'and' operation, the second expression is not evaluated.


# Since a is greater than 0, b / a is not executed.
result_and = a > 0 and b / a
print(result_and) # Output: False

# In the 'or' operation, the second expression is not evaluated.


# Since a is not less than 0, b / a is not executed.
result_or = a < 0 or b / a
print(result_or) # Output: True

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 15 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 3: Control Flow


Control flow is the art of guiding the execution of our code, allowing us to make
decisions, repeat tasks, and create intelligent, dynamic programs. As we delve into
this chapter, you'll discover how to wield conditional statements and loops,
mastering the art of directing your Python programs down the right path.

3.1 Conditional statements (if, else, elif)

Control flow in programming is all about making decisions, and conditional


statements are the fundamental building blocks for this decision-making process.
The conditional statements allow us to execute specific blocks of code based on
certain conditions. The most common conditional statements are "if," "else," and
"elif" (short for "else if").

The "if" Statement:

The "if" statement is the simplest form of a conditional statement. It allows us to


execute a block of code if a given condition evaluates to True. The basic syntax of an
"if" statement is as follows:

if condition:
# Code to be executed if the condition is True

Let's take an example where we want to check if a given number is positive:

# Example: Checking if a number is positive


num = 10

if num > 0:
print("The number is positive.")

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 16 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

In this example, the condition `num > 0` is evaluated. If the value of `num` is
greater than 0, the code inside the "if" block will be executed, and the message "The
number is positive." will be printed.

You can include multiple statements inside the "if" block by indenting them
appropriately. For example:

# Example: Multiple statements in the "if" block


num = 10

if num > 0:
print("The number is positive.")
print("This is a positive number.")
num_squared = num ** 2
print("The square of the number is:", num_squared)

In this example, all the statements inside the "if" block are executed if the
condition `num > 0` evaluates to True.

The "if-else" Statement:

The "if-else" statement expands on the "if" statement by allowing us to specify a


block of code to be executed when the condition is True and another block to be
executed when the condition is False. The syntax of the "if-else" statement is as
follows:

if condition:
# Code to be executed if the condition is True
else:
# Code to be executed if the condition is False

Let's use the previous example and add an "else" statement to handle the case
when the number is not positive:

# Example: Checking if a number is positive or not


num = -5

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 17 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

if num > 0:
print("The number is positive.")
else:
print("The number is not positive.")

In this case, since `num` is -5, the condition `num > 0` evaluates to False, and the
code inside the "else" block will be executed, printing "The number is not positive."

You can include multiple statements inside the "else" block by indenting them
correctly. For example:

# Example: Multiple statements in the "else" block


num = -5

if num > 0:
print("The number is positive.")
else:
print("The number is not positive.")
num_abs = abs(num)
print("The absolute value of the number is:", num_abs)

In this example, all the statements inside the "else" block will be executed if the
condition `num > 0` evaluates to False.

The "if-elif-else" Statement:

The "if-elif-else" statement allows us to check multiple conditions in sequence


and execute the code block corresponding to the first condition that evaluates to
True. The syntax of the "if-elif-else" statement is as follows:

if condition1:
# Code to be executed if condition1 is True
elif condition2:
# Code to be executed if condition2 is True
elif condition3:
# Code to be executed if condition3 is True

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 18 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

...
else:
# Code to be executed if none of the conditions are True

Let's consider an example where we want to determine the grade of a student


based on their score:

# Example: Determining the grade based on the score


score = 85

if score >= 90:


print("Grade: A")
elif score >= 80:
print("Grade: B")
elif score >= 70:
print("Grade: C")
elif score >= 60:
print("Grade: D")
else:
print("Grade: F")

In this case, since `score` is 85, the first condition `score >= 90` is False, the
second condition `score >= 80` is True, and the code inside the "elif" block for B
grade will be executed, printing "Grade: B."

3.2 Looping with while and for

Loops are essential tools in programming that enable us to repeat a block of code
multiple times. Python provides two primary loop constructs: the "while" loop and
the "for" loop. Here we will explore both loop types and learn how to leverage them
effectively to streamline repetitive tasks and solve complex problems.

The While Loop:

The "while" loop allows us to repeat a block of code as long as a specified


condition remains true. The loop continues iterating until the condition evaluates to

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 19 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

false. This looping structure is ideal when the exact number of iterations is
uncertain, and the loop depends on a dynamically changing condition.

Let's take a simple example to understand the "while" loop. Suppose we want to
print the first five even numbers. We can achieve this using a "while" loop:

print("Printing first five even numbers:")


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

In this example, we initialize the variable `count` to 1. The loop will continue as
long as `count` is less than or equal to 10. Within the loop, we use the "if" statement
to check if the current value of `count` is even. If it is, we print the number. Finally,
we increment `count` by 1 in each iteration to move to the next number.

The For Loop:

The "for" loop, on the other hand, is designed to iterate over a sequence (such as
a list, tuple, or string) and execute the block of code for each element in the
sequence. Unlike the "while" loop, the "for" loop has a predetermined number of
iterations based on the length of the sequence. Let's use a "for" loop to print the
elements of a list:

fruits = ["apple", "banana", "orange", "grape", "kiwi"]


print("Printing fruits:")
for fruit in fruits:
print(fruit)

In this example, we have a list called `fruits`, containing several fruits. The "for"
loop iterates over each element in the list, and in each iteration, the variable `fruit`
holds the current element. The loop then prints each fruit's name, giving us the
complete list of fruits.
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 20 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

Nested Loops:

Loops can also be nested inside each other, allowing us to perform complex
tasks. Let's consider a scenario where we want to create a multiplication table:

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

In this example, we have two "for" loops nested inside each other. The outer
loop iterates from 1 to 10, representing the multiplicand. The inner loop iterates
from 1 to 10, representing the multiplier. In each iteration, the code prints the
product of `i` and `j`, creating the multiplication table.

3.3 Break and continue statements

In this section, we will explore two essential control flow statements: `break` and
`continue`. These statements allow us to have more control over loops, enabling us
to fine-tune the flow of our programs based on specific conditions. Understanding
how to use `break` and `continue` will enhance your ability to create efficient and
flexible Python code.

The Break Statement:

The `break` statement provides a way to prematurely exit a loop when a certain
condition is met. It is commonly used when you want to stop a loop's execution
early, even before the loop's normal termination conditions are satisfied.

Let's illustrate the usage of `break` with an example. Consider a scenario where
we want to find the first occurrence of a target number in a list and stop the loop as
soon as we find it:

numbers = [3, 8, 12, 5, 10, 7, 15]

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 21 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

target = 10

for num in numbers:


if num == target:
print(f"Target {target} found!")
break
else:
print("Target not found in the list.")

In this example, the loop iterates through the `numbers` list, and when it
encounters the value `10`, it executes the `if` block, printing the message "Target 10
found!" and then breaks out of the loop. Since the `break` statement is triggered,
the `else` block will not execute.

The Continue Statement:

The `continue` statement is used to skip the rest of the current iteration of a loop
and proceed to the next iteration. It is particularly useful when you want to skip
certain elements in a loop and continue processing the remaining elements.

Let's demonstrate the use of `continue` with an example. Suppose we want to


print all even numbers from a list and skip odd numbers:

numbers = [1, 5, 8, 10, 7, 12, 15]

for num in numbers:


if num % 2 != 0:
continue
print(num)

In this example, the loop iterates through the `numbers` list. When an odd
number is encountered, the `if` block executes the `continue` statement, skipping
the odd number, and proceeding to the next iteration. The even numbers are
printed as a result.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 22 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 4: Functions
Functions are the building blocks of efficient and organized programming. They
allow us to break down complex tasks into smaller, manageable pieces, making our
programs easier to understand and maintain. As we delve into the world of
functions, you'll discover how they enhance code readability, promote code reuse,
and enable you to create elegant solutions to a wide range of problems.

4.1 Creating and using functions

To define a function in Python, we use the "def" keyword followed by the


function name and parentheses containing optional parameters. The function
definition is followed by a colon (:), and the indented block of code represents the
function body.

def greet():
print("Hello! Welcome to our Python program.")

# Calling the function


greet()

In this example, the function is called with `greet()`. It executes the `print()`
statement, displaying the message "Hello! Welcome to our Python program." on the
screen.

Functions like these can be useful for displaying messages, performing setup
tasks, or executing specific operations that don't rely on external input. They
contribute to organizing code and making it more modular, even if they don't
explicitly require parameters or return values.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 23 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

4.2 Parameters and return values

Functions become even more powerful when we introduce parameters and


return values. Parameters allow us to pass data to a function, and return values
enable functions to provide output back to the calling code. Understanding how to
use parameters and return values effectively is essential for building versatile and
reusable functions.

Function Parameters:

Function parameters act as placeholders for data that a function needs to


perform its task. These parameters are specified within the parentheses when
defining the function. When calling the function, we provide actual values, known as
arguments, that will be assigned to the parameters.

Let's dive into an example to understand this concept better. Suppose we want
to create a function that calculates the area of a rectangle. The function will take
two parameters: length and width.

def calculate_rectangle_area(length, width):


area = length * width
return area

In this example, the function `calculate_rectangle_area` has two parameters,


`length` and `width`. Inside the function, we calculate the area by multiplying
`length` and `width` and then return the result using the `return` keyword. Now, let's
call the function with specific values for `length` and `width`:

result = calculate_rectangle_area(5, 10)


print("The area of the rectangle is:", result)
# Output: The area of the rectangle is: 50

In this case, we call the `calculate_rectangle_area` function with arguments `5`


for `length` and `10` for `width`. The function calculates the area and returns `50`,
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 24 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

which we store in the variable `result`. The print statement displays the calculated
area of the rectangle.

Default Parameters:

Python allows us to set default values for function parameters. If a default value
is provided, the parameter becomes optional when calling the function. If the caller
does not provide a value for that parameter, the default value is used. Let's modify
our previous example to include default parameters for `length` and `width`:

def calculate_rectangle_area(length=1, width=1):


area = length * width
return area

In this updated function, if no arguments are provided when calling


`calculate_rectangle_area`, the function will assume default values of `1` for both
`length` and `width`. This means that if we call the function without arguments, it
will calculate the area of a rectangle with sides of length `1` and width `1`.

result1 = calculate_rectangle_area()
result2 = calculate_rectangle_area(5, 10)
print("The area of the default rectangle is:", result1)
# Output: The area of the default rectangle is: 1
print("The area of the rectangle is:", result2)
# Output: The area of the rectangle is: 50

In this example, we see that `result1` holds the area of a default rectangle with
sides of length `1` and width `1`, while `result2` holds the area of a rectangle with
sides of length `5` and width `10`.

Return Values:

Return values allow functions to provide outputs that can be used in the calling
code. When a function encounters a `return` statement, it immediately exits the

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 25 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

function and passes the specified value back to the caller. Let's consider a function
that calculates the sum of two numbers:

def calculate_sum(a, b):


result = a + b
return result

In this function, `calculate_sum`, we take two parameters, `a` and `b`, and
calculate their sum, which we store in the variable `result`. We then use the `return`
statement to provide this sum as the output of the function. Now, let's call the
function and store the result in a variable:

sum_result = calculate_sum(10, 20)


print("The sum is:", sum_result) # Output: The sum is: 30

In this example, we call the function `calculate_sum` with arguments `10` and
`20`. The function calculates their sum, which is `30`, and returns it. The returned
value, `30`, is then stored in the variable `sum_result`, which we print to display the
final result.

4.3 Function scope and global variables

Functions also introduce a concept known as "scope," which refers to the region
of a program where a particular variable can be accessed. Understanding scope is
crucial for writing bug-free and efficient code, as it determines the visibility and
lifetime of variables within different parts of the program.

Local Scope:

When you define a variable inside a function, it is said to have "local scope." This
means the variable is only accessible within that specific function and cannot be
accessed from outside. Once the function completes its execution, the local variables
are destroyed, and their values are no longer available. Let's look at an example to
illustrate local scope:
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 26 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

def my_function():
x = 10
print("Inside the function: x =", x)

my_function()
# Output: Inside the function: x = 10

# The following line will raise a NameError


$ because 'x' is not defined outside the function.
print("Outside the function: x =", x)

In this example, the variable `x` is defined inside the `my_function()`. It has local
scope, and hence, it is accessible only within the function. Attempting to access `x`
outside the function will result in a `NameError`.

Global Scope:

Variables declared outside of any function, i.e., in the main body of the program,
have "global scope." These variables are accessible throughout the entire program,
including inside functions. Let's see an example of using a global variable:

global_var = 100

def my_function():
print("Inside the function: global_var =", global_var)

my_function()
# Output: Inside the function: global_var = 100

print("Outside the function: global_var =", global_var)


# Output: Outside the function: global_var = 100

In this example, `global_var` is declared outside the function and has global
scope. Therefore, it can be accessed both inside and outside the function.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 27 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Modifying Global Variables Inside Functions:

While you can access global variables inside functions, modifying them requires a
special declaration. By default, when you assign a value to a variable inside a
function, Python assumes it's a local variable. To modify a global variable inside a
function, you need to explicitly declare it as `global` using the `global` keyword:

global_var = 100

def modify_global():
global global_var
global_var += 50

modify_global()
print("Modified global_var =", global_var)
# Output: Modified global_var = 150

In this example, we use the `global` keyword inside the `modify_global()`


function to inform Python that we want to modify the global variable `global_var`. As
a result, the value of `global_var` is increased by 50.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 28 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 5: Input and Output


Input and Output (I/O) are the gateways through which a program communicates
with the user and the external world. Understanding how to interact with users,
read data from external sources, and display information is fundamental to building
interactive and practical applications. Whether you're creating simple command-line
tools or sophisticated graphical interfaces, mastering input and output operations in
Python will open up endless possibilities for your coding endeavors.

5.1 Reading input from the user

One of the essential tasks in any interactive program is to receive input from the
user. In Python, this can be achieved using the built-in function `input()`.

The `input()` function is a powerful tool for gathering user input during program
execution. It prompts the user to enter a value or string and waits for the user's
response. Once the user enters the input and presses the "Enter" key, the `input()`
function returns the input as a string.

Example: Basic `input()` Usage

# Get the user's name as input and display a greeting


name = input("Enter your name: ")
print(f"Hello, {name}! Welcome to Python by Example.")

In this example, we prompt the user to enter their name using `input()`. The
entered name is then stored in the variable `name`, and we use string interpolation
(using an f-string) to display a personalized greeting.

Example: Converting Input to Numeric Data

# Get the user's age as input and calculate the year of birth
age = int(input("Enter your age: "))
current_year = 2023

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 29 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

birth_year = current_year - age


print(f"You were born in {birth_year}.")

In this example, we receive the user's age as input. However, since `input()`
returns a string, we need to convert it to an integer using the `int()` function to
perform numerical operations. We then calculate user's birth year and display it.

Handling User Input:

When using `input()`, it's essential to consider user input validation to ensure
that the program can handle various input scenarios without encountering errors.
For example, if the program expects a numeric input but the user enters a non-
numeric value, it may cause a `ValueError`. We can use techniques like `try-except`
blocks to handle such situations gracefully.

Example: Handling Invalid Input

# Handling invalid input with try-except


try:
age = int(input("Enter your age: "))
current_year = 2023
birth_year = current_year - age
print(f"You were born in {birth_year}.")
except ValueError:
print("Invalid input. Please enter a valid numeric age.")

In this example, we wrap the input and subsequent calculations in a `try-except`


block. If the user enters a non-numeric value, Python raises a `ValueError`, and the
program gracefully handles it by displaying a friendly error message.

5.2 Writing data to files

Writing data to files is a fundamental and indispensable operation in


programming, enabling us to preserve valuable information generated by our
programs for future use or sharing with others. It forms a crucial part of any data
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 30 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

handling process, where we manipulate and persistently store data for various
purposes. The process of file handling encompasses multiple steps, such as opening
files to access their content, reading from them, writing new data, or appending to
existing files, and finally, closing the files after the required operations are
performed. Mastering these file handling techniques empowers us to create robust
and efficient applications that can seamlessly interact with external files, facilitating
data storage and retrieval with ease.

Opening and Writing to Files:

Python provides a simple and intuitive way to write data to files. To begin, we
need to open a file in write mode using the `open()` function. The syntax for opening
a file for writing is as follows:

file = open("filename.txt", "w")

In the above code, `"filename.txt"` represents the name of the file we want to
create or open, and `"w"` denotes that we are opening the file in write mode. If the
specified file does not exist, Python will create a new file with the given name.

Writing Data:

Once the file is open in write mode, we can use the `write()` method to write
data to the file. The `write()` method takes a string as an argument and writes it to
the file. Here's an example of writing data to a file:

# Open the file in write mode


file = open("output.txt", "w")

# Writing data to the file


file.write("Hello, this is some text written to a file.\n")
file.write("Writing data to files is easy and efficient!\n")

# Close the file

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 31 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

file.close()

In this example, we first open a file named "output.txt" in write mode. We then
use the `write()` method to write two lines of text to the file. Note that each call to
`write()` appends the text to the file, so multiple calls can be used to write different
pieces of information.

Appending Data to Files:

If we want to add data to an existing file without overwriting its contents, we can
open the file in append mode (`"a"`) instead of write mode (`"w"`). Here's an
example:

# Open the file in append mode


file = open("output.txt", "a")

# Appending data to the file


file.write("This text is appended to the file.\n")

# Close the file


file.close()

In this case, the new text will be added to the end of the existing content in the
"output.txt" file.

Using the `with` Statement:

When working with files, it's good practice to use the `with` statement, which
automatically handles the file closing for us. The `with` statement creates a context
manager that opens the file, allows us to perform operations on it, and automatically
closes it when we're done. Here's an example:

# Writing data to a file using the with statement


with open("output.txt", "w") as file:
file.write("This data is written using the with statement.\n")
file.write("Using with ensures file is automatically closed.\n")
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 32 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

The above code achieves the same result as the earlier example but with the
added benefit of automatic file closure.

Reading Data from Files:


Mastering the art of reading data from files is a crucial and foundational skill that
opens up a world of opportunities for data analysis, processing, and manipulation.
The subsequent example illustrates how data can be extracted from files.

# Writing data to a file


with open("output.txt", "w") as file:
file.write("Hello, this is some text written to a file.\n")
file.write("Writing data to files is easy and efficient!\n")

# Appending data to the file


with open("output.txt", "a") as file:
file.write("This text is appended to the file.\n")

# Reading data from the file


with open("output.txt", "r") as file:
contents = file.read()

# Printing the contents of the file


print("Contents of 'output.txt':")
print(contents)

In this example, we first open the file "output.txt" in write mode and write two
lines of text to it. Then, we open the file again in append mode and add another line
of text to the end of the existing content.

Next, we open the file in read mode (`"r"`) using the `with` statement, which
automatically closes the file after reading its contents. We use the `read()` method
to read the entire contents of the file and store it in the variable `contents`.

Finally, we print the contents of the file to the console, displaying the text we
previously wrote and appended.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 33 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

When you run this code, the Contents of 'output.txt' be as follows:

Hello, this is some text written to a file.


Writing data to files is easy and efficient!
This text is appended to the file.

As you can see, we successfully wrote data to the file, appended new data, and
then read and displayed the entire content of the file using Python's file handling
capabilities. This powerful combination of reading and writing to files allows us to
create applications that can efficiently interact with external data sources and
manipulate data for various purposes.

5.3 Formatting output

Formatting output allows us to present data in a structured and visually


appealing manner. Properly formatted output enhances the readability of our
programs and makes the information presented to users more comprehensible.

String Concatenation:

One of the most basic methods of formatting output is through string


concatenation. We can combine strings and variables using the `+` operator to
create informative messages. However, this approach may become cumbersome
when dealing with multiple variables and data types.

name = "Nadeem"
age = 55
print("Name is " + name + ", I am " + str(age) + " years old.")

Using `str.format()`:

The `str.format()` method provides a more structured way to format output by


using placeholder curly braces `{}` to represent variables or values that will be

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 34 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

inserted into the string. This method is especially useful when dealing with multiple
variables.

name = "Nadeem"
age = 55
print("Name is {} and I am {} years old.".format(name, age))

f-strings (Formatted Strings):

Introduced in Python 3.6, f-strings offer a concise and efficient way to format
output. F-strings allow us to embed expressions and variables directly within curly
braces `{}` preceded by the letter 'f'. The expressions inside the braces are evaluated
at runtime, making f-strings a powerful tool for dynamic output formatting.

name = "Nadeem"
age = 55
print(f"Hello, my name is {name} and I am {age} years old.")

Specifying Format Specifiers:

We can also use format specifiers to control the appearance of the output
further. Format specifiers define how data should be displayed, such as setting a
fixed width for numbers or specifying the number of decimal places.

pi = 3.14159265359
print("The value of pi is {:.2f}".format(pi))
# Output: "The value of pi is 3.14"

Using Alignment and Fill Characters:

Format specifiers also allow us to align the output and fill spaces with specific
characters.

name = "Nadeem"
age = 55
print(f"{name:<10} is {age} years old.")
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 35 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

In this example, `name` is left-aligned within a field of width 10, and the extra
spaces are filled with a default space character. By changing `<` to `>`, we can right-
align the text, and by using `^`, we can center it.

Formatting Numbers and Dates:

Python offers various format specifiers for numbers and dates to control their
appearance. For example:

number = 12345.6789
date = datetime.now()
print(f"Formatted number: {number:,.2f}")
# Output: "Formatted number: 12,345.68"
print(f"Formatted date: {date:%Y-%m-%d}")
# Output: "Formatted date: 2023-07-20"

In this example, `,` is used to add commas for thousands separators in numbers,
and `%Y-%m-%d` represents the date format as year-month-day.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 36 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 6: Exception Handling


Encountering errors is an inevitable part of the process. However, fear not, for
Python provides a robust mechanism to handle these errors gracefully and continue
the execution of our programs. In this chapter, we will delve into the art of exception
handling in Python. You will learn how to anticipate and catch errors using try-except
blocks, enabling your programs to handle unexpected situations without crashing.

6.1 Handling errors with try-except

When an unexpected situation occurs during the execution of a program, an


error, also known as an exception, is raised. These exceptions could be caused by
various factors, such as invalid input, division by zero, or accessing non-existent
elements in a list. When left unhandled, exceptions can cause the program to
terminate abruptly, leading to a poor user experience. With the try-except block, we
can gracefully catch and manage exceptions, allowing our programs to recover from
errors and continue execution.

The try-except block is a structured way to handle exceptions. The "try" block
contains the code that may raise an exception. If an exception occurs within the try
block, Python immediately jumps to the corresponding "except" block, allowing us to
manage the exception. The program then continues executing from the point after
the except block, avoiding a complete program crash. Syntax:

try:
# Code that may raise an exception
# ...
except ExceptionType:
# Code to handle the exception
# ...

In the syntax above, `ExceptionType` refers to the type of exception we want to


catch. For example, if we want to catch a ValueError, we use `except ValueError:`. If

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 37 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

we want to catch any type of exception, we can use a general `except:` block without
specifying the type.

Example: Handling Division by Zero

Let's consider a simple example where we want to perform division and handle
the case of division by zero. Without exception handling, the program would raise a
"ZeroDivisionError" and terminate.

def divide(a, b):


try:
result = a / b
print(f"The result of {a} divided by {b} is {result}.")
except ZeroDivisionError:
print("Error: Division by zero is not allowed.")

# Test cases
divide(10, 2) # Output: The result of 10 divided by 2 is 5.0.
divide(8, 0) # Output: Error: Division by zero is not allowed.

In the above example, the try block attempts to perform the division. If the
divisor is zero, a ZeroDivisionError is raised, and the except block handles the error
gracefully.

Example: Handling Invalid Input

In this example, we want to convert user input to an integer. If the input is not a
valid integer, a ValueError will be raised. We will use the try-except block to handle
this situation.

def get_integer_input():
try:

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 38 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

user_input = input("Enter an integer: ")


number = int(user_input)
print(f"Your input as an integer: {number}.")
except ValueError:
print("Error: Invalid input. Please enter a valid integer.")

# Test cases
get_integer_input()
# Input: 42
# Output: Your input as an integer: 42.
get_integer_input()
# Input: abc
# Output: Error: Invalid input. Please enter a valid integer.

In this case, the try block attempts to convert the user input to an integer. If the
input is not a valid integer, a ValueError is raised, and the except block handles the
error message appropriately.

6.2 Custom exceptions

While Python provides a wide range of built-in exceptions to cover most common
error scenarios, there are instances where we may encounter specific situations that
require a more specialized approach. This is where custom exceptions come into
play.

Custom exceptions, also known as user-defined exceptions, are exceptions


created by the programmer to handle specific error conditions that are not covered
by the standard Python exceptions. By defining our own custom exceptions, we can
provide more informative and meaningful error messages, making it easier for
ourselves and other developers to understand and debug our code.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 39 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Defining a Custom Exception:

To create a custom exception, we define a new class that inherits from the built-
in `Exception` class or any of its subclasses. This custom class will represent our
custom exception. Let's see an example:

class CustomError(Exception):
def __init__(self, message):
self.message = message

def __str__(self):
return f'Custom Error: {self.message}'

In this example, we define a new custom exception named `CustomError`. The


`__init__` method allows us to pass a custom error message when raising the
exception. The `__str__` method provides a string representation of the exception,
which will be displayed when the exception is raised.

Raising a Custom Exception:

Now that we have our custom exception, we can raise it in our code when a
specific error condition occurs. Let's illustrate this with a simple function that
calculates the area of a rectangle, but we want to handle the scenario where the
width or height is negative:

def calculate_rectangle_area(width, height):


if width <= 0 or height <= 0:
raise CustomError("Width and height must be positive.")
return width * height

In this example, if the `width` or `height` is less than or equal to zero, we raise
our custom `CustomError` exception with a meaningful error message.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 40 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Handling the Custom Exception:

Now that we have raised our custom exception, we need to handle it


appropriately in our code. To catch and handle a custom exception, we use the `try-
except` block just like we do with built-in exceptions:

try:
width = -5
height = 10
area = calculate_rectangle_area(width, height)
print("Area:", area)
except CustomError as e:
print(e)

In this example, we call the `calculate_rectangle_area` function with a negative


`width`. As a result, the `CustomError` exception will be raised, and the `except`
block will catch it. The error message "Custom Error: Width and height must be
positive." will be displayed, indicating the exact cause of the exception.

Benefits of Custom Exceptions:

Creating custom exceptions allows us to add clarity and precision to our error
handling. It enhances code readability and makes troubleshooting and debugging
easier, as the exception messages are more descriptive and relevant to the specific
error scenarios we encounter in our applications.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 41 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

Chapter 7: Mini Projects and Exercises


Congratulations on making it this far in your Python journey! In this
chapter, you'll take on exciting mini projects and exercises that reinforce your
Python skills and unleash your creativity.

7.1 Simple projects put the acquired knowledge into practice

We present two engaging projects that will put your newfound Python
knowledge into action. These projects serve as practical exercises, allowing you to
implement the concepts learned throughout the book in real-world scenarios. Each
project provides a unique opportunity to explore Python's features, including
variables, control flow, functions, and more. By completing these projects, you'll
reinforce your understanding and gain confidence in your ability to tackle coding
challenges.

Project 1: Guess the Number

Create a Python program that generates a random number between a specified


range and prompts the user to guess the number. Provide hints to guide the user
towards the correct answer, and congratulate them when they guess correctly. This
project will involve using variables, conditionals, and loops.

import random

def guess_the_number():
secret_number = random.randint(1, 100)

print("Welcome to Guess the Number!")


print("I am thinking of a number between 1 and 100.")
print("Can you guess it?")

attempts = 0
while True:

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 42 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

try:
user_guess = int(input("Enter your guess: "))
attempts += 1

if user_guess == secret_number:
print(f"Congratulations! Guessed: {secret_number}")
print(f"in {attempts} attempts.")
break
elif user_guess < secret_number:
print("Too low! Try a higher number.")
else:
print("Too high! Try a lower number.")
except ValueError:
print("Invalid input. Please enter a valid integer.")

if __name__ == "__main__":
guess_the_number()

Step by step Description:

1. The program begins by importing the `random` module to


generate random numbers.
2. It defines a function called `guess_the_number()` to
implement the "Guess the Number" game logic.
3. Inside the function, a random number between 1 and 100 is
generated and stored as `secret_number`.
4. The program displays a welcoming message, prompting the
user to participate in the "Guess the Number" game.
5. It informs the user that the target number lies within the
range of 1 to 100, and asks them to make a guess.
6. A variable called `attempts` is initialized to keep track
of the number of attempts made by the user.
7. The program enters a `while` loop, which will continue
until the user correctly guesses the `secret_number`.
8. Within the loop, the user's input is obtained using the
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 43 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

`input()` function, and the input is converted to an


integer using `int()`.
9. The program increments the `attempts` variable with each
guess made by the user.
10. Inside the loop, the user's guess is compared to the
`secret_number` using conditional statements.
11. If the user's guess matches the `secret_number`, the
program congratulates the user on guessing the correct
number and displays the `secret_number`.
12. Additionally, the program provides feedback to the user
about the number of attempts it took to guess correctly.
13. If the user's guess is lower than the `secret_number`, the
program informs the user that the guess is too low and
suggests trying a higher number.
14. Similarly, if the user's guess is higher than the
`secret_number`, the program informs the user that the
guess is too high and suggests trying a lower number.
15. In case the user enters a non-integer value as input, the
program catches the `ValueError` using a `try-except` block
and informs the user to enter a valid integer.
16. Once the user guesses the correct number, the program exits
the loop, and the game ends.
17. The "Guess the Number" game demonstrates an interactive and
enjoyable experience, applying the concepts of variables,
conditionals, and loops in Python.

Project 2: To-Do List Manager

Build a to-do list manager where users can add, view, and remove tasks.
Implement options to mark tasks as completed and display completed tasks

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 44 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

separately. This project will allow you to apply your knowledge of lists, functions,
and basic input/output operations.

def show_menu():
print("Todo List Manager")
print("1. Add task")
print("2. View tasks")
print("3. Remove task")
print("4. Mark task as completed")
print("5. View completed tasks")
print("6. Exit")

def add_task(todo_list):
task = input("Enter the task: ")
todo_list.append({"task": task, "completed": False})
print("Task added successfully.")

def view_tasks(todo_list):
print("Tasks:")
for index, task in enumerate(todo_list, start=1):
status = "✓" if task["completed"] else " "
print(f"{index}. [{status}] {task['task']}")

def remove_task(todo_list):
view_tasks(todo_list)
try:
choice = int(input("Enter the task number to remove: "))
if 1 <= choice <= len(todo_list):
todo_list.pop(choice - 1)
print("Task removed successfully.")
else:
print("Invalid task number.")
except ValueError:
print("Invalid input. Please enter a valid task number.")

def mark_completed(todo_list):
view_tasks(todo_list)
try:
choice = int(input("Task number to mark as completed: "))
if 1 <= choice <= len(todo_list):

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 45 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

todo_list[choice - 1]["completed"] = True


print("Task marked as completed.")
else:
print("Invalid task number.")
except ValueError:
print("Invalid input. Please enter a valid task number.")

def view_completed_tasks(todo_list):
completed_tasks = [task for task in todo_list if
task["completed"]]
if not completed_tasks:
print("No completed tasks.")
else:
print("Completed tasks:")
for index, task in enumerate(completed_tasks, start=1):
print(f"{index}. {task['task']}")

def main():
todo_list = []
while True:
show_menu()
try:
choice = int(input("Enter your choice: "))
if choice == 1:
add_task(todo_list)
elif choice == 2:
view_tasks(todo_list)
elif choice == 3:
remove_task(todo_list)
elif choice == 4:
mark_completed(todo_list)
elif choice == 5:
view_completed_tasks(todo_list)
elif choice == 6:
print("Goodbye!")
break
else:
print("Invalid choice. Please select again.")
except ValueError:
print("Invalid input. Please enter a valid choice.")

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 46 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

if __name__ == "__main__":
main()

Step by step Description:

1. The program starts with defining a function called


`show_menu()` to display the menu options for the To-Do
List Manager.
2. Another function, `add_task(todo_list)`, is defined to
allow users to add tasks to the To-Do list. The function
prompts the user to enter the task and appends it to the
`todo_list` as a dictionary with a "task" key and a
"completed" key set to `False`.
3. The function `view_tasks(todo_list)` is created to display
all the tasks in the `todo_list`. It iterates through the
list and prints each task's index, status (if completed or
not), and task description.
4. For removing a task, the function `remove_task(todo_list)`
is defined. It first calls `view_tasks(todo_list)` to
display the tasks and prompts the user to enter the task
number they wish to remove. If a valid task number is
provided, the corresponding task is removed from the
`todo_list`.
5. To mark a task as completed, the function
`mark_completed(todo_list)` is implemented. Similar to
removing a task, this function calls
`view_tasks(todo_list)` to display the tasks and asks the
user to enter the task number they want to mark as
completed. If a valid task number is provided, the
"completed" key for that task in the `todo_list` is set to
`True`.
6. The function `view_completed_tasks(todo_list)` is created
Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 47 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

to display only the completed tasks. It filters the


`todo_list` to find tasks with "completed" set to `True`
and prints the description of those tasks.
7. The main function, `main()`, is defined to manage the flow
of the To-Do List Manager. It initializes an empty
`todo_list` and runs an infinite loop to display the menu
options and prompt the user for their choice.
8. Inside the loop, the user's choice is obtained using
`input()`. Based on the choice, the program executes the
corresponding function to perform the desired operation
(add, view, remove, mark as completed, view completed
tasks, or exit).
9. The program continues to loop until the user chooses to
exit the To-Do List Manager.
10. If the user provides an invalid choice or non-integer
input, the program catches the `ValueError` using a `try-
except` block and informs the user to enter a valid choice
or task number.
11. If the user chooses to exit the To-Do List Manager by
entering "6," the program prints "Goodbye!" and breaks out
of the loop, ending the program.
12. The "To-Do List Manager" program effectively applies the
concepts of lists, functions, and basic input/output
operations in Python, allowing users to manage their tasks
efficiently.

7.2 Coding exercises to reinforce knowledge

The exercises in this section are designed to provide hands-on practice and
deepen your understanding of the concepts covered in the book. By engaging with

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 48 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

these exercises, you'll sharpen your coding abilities and gain confidence in your
Python proficiency.

Problem 1: Pattern Matcher

Write a Python function that takes two strings as input, `text` and `pattern`, and
determines if the pattern exists in the text. The pattern can contain both letters and
wildcards represented by asterisks (*), which can match zero or more characters in
the text. Your function should return `True` if the pattern is found in the text,
considering the wildcard matching, and `False` otherwise.

def pattern_matcher(text, pattern):


# Function to match the pattern in the text
def match(text_idx, pattern_idx):
if text_idx == len(text) and pattern_idx == len(pattern):
return True
if pattern_idx == len(pattern):
return False

if pattern[pattern_idx] == '*':
for i in range(text_idx, len(text) + 1):
if match(i, pattern_idx + 1):
return True
elif (text_idx < len(text) and
(text[text_idx] == pattern[pattern_idx] or
pattern[pattern_idx] == '?')):
return match(text_idx + 1, pattern_idx + 1)
return False

return match(0, 0)

# Test cases
print(pattern_matcher("hello_world", "h*o_w*d")) # Output: True
print(pattern_matcher("programming", "pr*g")) # Output: False

Step by step Description:

1. The program starts by defining the `pattern_matcher`


Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 49 | P a g e
Python by Example (Book 1: Fundamentals and Basics)

function, which takes two input arguments: `text` and


`pattern`.
2. Inside the `pattern_matcher` function, a nested helper
function called `match` is defined to perform the actual
pattern matching.
3. The `match` function takes two arguments, `text_idx` and
`pattern_idx`, representing the current index in the
`text` and `pattern`, respectively.
4. The `match` function implements a recursive approach to
check if the given `pattern` exists in the `text`,
considering the wildcard matching with asterisks (*) and
question marks (?).
5. The `match` function first handles the base cases: if both
`text_idx` and `pattern_idx` have reached the end of the
text and pattern, respectively, it returns `True`,
indicating a successful match. If only `pattern_idx` has
reached the end, it returns `False`.
6. If the current character in the `pattern` is an asterisk
(*), the function uses a loop to try matching the
remaining text from the current index to the end of the
`text` with the rest of the pattern after the asterisk. If
a match is found, it returns `True`.
7. If the current character in the `pattern` is not an
asterisk (*), the function checks if the current
characters in the `text` and `pattern` match, or if the
pattern character is a question mark (?). If so, it moves
to the next characters in the `text` and `pattern` and
recursively calls itself.
8. If none of the conditions above match, the function
returns `False`, indicating that the pattern cannot be

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 50 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

matched with the remaining text.


9. Back in the `pattern_matcher` function, the `match`
function is called with the initial indices set to 0 to
begin the pattern matching process.
10. The `pattern_matcher` function returns the result of the
`match` function, which is either `True` if the pattern is
found in the text or `False` otherwise.
11. After defining the `pattern_matcher` function, the program
includes main test statements to check the function's
correctness.
12. Test cases are created using the `pattern_matcher`
function with different inputs for `text` and `pattern`.
13. The program calls the `pattern_matcher` function with the
provided test cases and displays the results.
14. The output of the test cases shows whether the pattern is
successfully matched with the text, taking wildcard
matching into account.
15. By running the main test statements, the program verifies
the functionality of the `pattern_matcher` function and
ensures it provides accurate results for different pattern
and text combinations.

Problem 2: File Similarity Checker

Create a Python program that takes two text files as input and measures their
similarity using the Jaccard similarity coefficient. The Jaccard similarity coefficient
compares the similarity between two sets by calculating the size of their intersection
divided by the size of their union. In this case, each set represents the unique words
in each text file. Your program should read the files, tokenize the words, and
calculate and display the Jaccard similarity coefficient between the two files.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 51 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

def jaccard_similarity(file1, file2):


# Function to calculate Jaccard similarity
def calculate_similarity(set1, set2):
intersection = len(set1.intersection(set2))
union = len(set1.union(set2))
similarity_coefficient = intersection / union
return similarity_coefficient

# Read contents of file1.txt and file2.txt


with open(file1, 'r') as file1:
text1 = file1.read()

with open(file2, 'r') as file2:


text2 = file2.read()

# Tokenize words in each file and create sets


words_set1 = set(text1.split())
words_set2 = set(text2.split())

# Calculate Jaccard similarity coefficient


jaccard_similarity_coefficient = calculate_similarity(
words_set1,
words_set2
)
# Display the Jaccard similarity coefficient
print(f"Similarity: {jaccard_similarity_coefficient:.2f}")

# Test the function with the example files


file1_path = "file1.txt"
file2_path = "file2.txt"
jaccard_similarity(file1_path, file2_path)

Step by step Description:

1. The program begins by defining the `jaccard_similarity`


function, responsible for calculating the Jaccard
similarity coefficient between two text files.
2. Within the `jaccard_similarity` function, a nested helper

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 52 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

function named `calculate_similarity` is defined. This


inner function will compute the Jaccard similarity
coefficient based on the intersection and union of two
sets.
3. The `jaccard_similarity` function receives two file paths,
`file1` and `file2`, as input parameters.
4. The program reads the contents of `file1` and `file2` using
`open()` and `read()` functions within separate `with`
blocks. This ensures that the files are properly closed
after their contents are read.
5. The text content from each file is tokenized into
individual words using the `split()` method and stored as
sets. Each set represents the unique words in the
respective files.
6. The program then calls the `calculate_similarity` function,
passing the sets of unique words from `file1` and `file2`
as arguments.
7. Inside the `calculate_similarity` function, the
intersection and union of the two sets are computed using
the `intersection()` and `union()` methods, respectively.
8. The Jaccard similarity coefficient is calculated by
dividing the size of the intersection by the size of the
union.
9. The computed Jaccard similarity coefficient is returned
from the `calculate_similarity` function.
10. Back in the `jaccard_similarity` function, the result
returned by `calculate_similarity` is assigned to the
variable `jaccard_similarity_coefficient`.
11. The program then proceeds to print the result using the
`print()` function, displaying the Jaccard similarity

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 53 | P a g e


Python by Example (Book 1: Fundamentals and Basics)

coefficient with two decimal places using the f-string


formatting.
12. Finally, the program includes a test scenario where it
calls the `jaccard_similarity` function with example file
paths, "file1.txt" and "file2.txt", to demonstrate the
calculation and display of the Jaccard similarity
coefficient for the given input files.
13. When executed, the program will read the contents of the
two files, calculate the Jaccard similarity, and output the
result to the console. The output will be formatted as "The
Jaccard similarity coefficient is: <value>", where
`<value>` represents the similarity coefficient with two
decimal places.

Compiled & Edited by Muhammad Nadeem Khokhar ([email protected]) 54 | P a g e

You might also like