[go: up one dir, main page]

0% found this document useful (0 votes)
46 views227 pages

Python HandBook

Python handbook which made be the students of addis abeba university in order to reach out for a person who may looking for a guider or free lesson book to develop and build in technology particularly website and app developer.

Uploaded by

kalebmekonen.kb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views227 pages

Python HandBook

Python handbook which made be the students of addis abeba university in order to reach out for a person who may looking for a guider or free lesson book to develop and build in technology particularly website and app developer.

Uploaded by

kalebmekonen.kb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 227

Python HandBook

by : Muhammed Teshome

Learn with us :
Telegram: https://t.me/EmmersiveLearning

Youtube: https://www.youtube.com/@EmmersiveLearning/
1. Python Roadmap

ng
ni
ar
Le
This is the complete roadmap to mastering Python. it will guide you
ve
step-by-step, from beginner concepts to advanced topics, ensuring you build a
solid foundation in Python programming and its practical applicatio
si
er

1. Introduction to Python
m

● Goal: Familiarize yourself with the Python language and environment.


● Topics:
Em

○ What is Python?
○ Installing Python and setting up IDE (e.g., PyCharm, VS Code,
Jupyter Notebooks)
○ Running your first Python program (Hello, World!)
○ Python syntax, keywords, comments, and indentation

1
2. Python Basics

● Goal: Understand Python's core programming concepts.


● Topics:
○ Variables and data types
○ Basic operators (arithmetic, comparison, logical, etc.)
○ Input and output functions

ng
○ Type conversion and casting
○ String operations and formatting

ni
ar
3. Control Flow (Decision Making and Loops)
Le
● Goal: Learn how to control the flow of your programs.
● Topics:
ve
○ If-else conditions
○ Nested conditions
si

○ Loops (for, while)


○ Break, continue, and pass statements
er

○ Looping with range(), iterating through lists, strings, and other


sequences
m
Em

4. Functions and Modules

● Goal: Master reusable code through functions and modules.


● Topics:
○ Defining and calling functions
○ Function arguments (positional, keyword, default, arbitrary)

2
○ Return values and multiple return values
○ Lambda functions (anonymous functions)
○ Scope and lifetime of variables
○ Built-in functions vs. custom functions
○ Python modules and import statement
○ Creating and using custom modules

ng
○ math, random, os, and other essential modules

ni
5. Python Data Structures

ar
● Goal: Learn how to store and manipulate data using Python’s core data
structures.
● Topics:
Le
○ Lists
ve

○ Tuples
○ Sets
si

○ Dictionaries
er

○ List comprehensions
○ Dictionary comprehensions
m

○ Operations on data structures (adding, removing, iterating, slicing,


etc.)
Em

6. Object-Oriented Programming (OOP) in Python

● Goal: Understand the principles of OOP and how to apply them in Python.
● Topics:
○ Classes and objects

3
○ Constructors (__init__ method)
○ Instance variables vs. class variables
○ Methods (instance methods, class methods, static methods)
○ Inheritance (single and multiple)
○ Encapsulation
○ Polymorphism

ng
○ Abstraction
○ Special methods (__str__, __repr__, etc.)

ni
○ OOP design principles

ar
7. File Handling
Le
● Goal: Learn how to work with files in Python.
● Topics:
ve

○ Reading and writing text files


○ File modes (r, w, a, r+)
si

○ Working with directories


er

○ Handling exceptions while working with files


○ Working with JSON files
m
Em

8. Exception Handling

● Goal: Understand how to handle runtime errors gracefully.


● Topics:
○ Try-except blocks
○ Multiple exceptions
○ Finally block

4
○ Raising exceptions
○ Custom exceptions

9. Python Libraries and Modules

● Goal: Explore the most commonly used Python libraries.

ng
● Topics:
○ Working with third-party libraries

ni
○ Installing libraries using pip

ar
○ Exploring popular libraries:
■ NumPy (for numerical computing)
Le
■ Pandas (for data analysis)
■ Matplotlib and Seaborn (for data visualization)
■ Requests (for web scraping)
ve
■ Datetime (for handling dates and times)
■ Tkinter (for GUI applications)
si

■ Pillow (for image manipulation)


er
m

10. Working with Databases


Em

● Goal: Learn how to connect and interact with databases using Python.
● Topics:
○ Introduction to databases and SQL
○ Connecting Python with databases (SQLite, MySQL, PostgreSQL)
○ CRUD operations (Create, Read, Update, Delete)
○ Executing SQL queries from Python
○ Using SQLite3 module

5
11. Web Development with Python

● Goal: Build web applications using Python frameworks.


● Topics:
○ Flask Framework (micro-framework)

ng
■ Setting up Flask
■ Creating routes and views

ni
■ Handling templates with Jinja2
■ Working with forms and sessions

ar
○ Django Framework (full-stack framework)
■ Introduction to Django
Le
■ Setting up a Django project
■ Models, views, and templates (MVT architecture)
■ Working with forms, authentication, and database
ve

○ REST APIs with Flask/Django


○ Consuming APIs using requests
si
er

12. Advanced Python Concepts


m

● Goal: Dive into advanced Python features.


Em

● Topics:
○ Generators and yield
○ Decorators
○ Iterators and iterables
○ Context managers (with statement)
○ Regular expressions (re module)

6
○ Concurrent programming (threading, multiprocessing,
asyncio)

13. Testing and Debugging

ng
● Goal: Learn how to write test cases and debug Python code.
● Topics:

ni
○ Debugging tools in Python
○ Writing unit tests with unittest

ar
○ Test-driven development (TDD)
○ Using pytest for more advanced testing
○ Mocking and patching
Le
ve

14. Data Science with Python


si

● Goal: Understand the basics of data science and machine learning using
er

Python.
● Topics:
m

○ Introduction to Data Science


○ Working with datasets using Pandas
Em

○ Data visualization with Matplotlib and Seaborn


○ Basics of machine learning using Scikit-learn
○ Training and testing models
○ Introduction to deep learning with TensorFlow or PyTorch

7
15. Deployment and Production

● Goal: Learn how to deploy Python applications.


● Topics:
○ Deploying a Flask or Django app on Heroku
○ Setting up a virtual environment
○ Working with Docker for containerization

ng
○ Introduction to cloud services (AWS, Google Cloud, Azure)

ni
ar
16. Final Projects

Le
● Goal: Apply everything you've learned by building real-world projects.
● Projects Ideas:
○ Web scraper
ve
○ To-do list app (using Flask or Django)
○ RESTful API for a book database
si

○ Machine learning model for predicting housing prices


○ Personal finance tracker
er

○ Blog platform with user authentication


m
Em

17. Bonus Topics

● Goal: Explore more Python applications and extend your learning.


● Topics:
○ Python for Automation (using Selenium and BeautifulSoup)
○ Python for Game Development (using Pygame)
○ Python for IoT (Raspberry Pi integration)

8
○ Python for Cybersecurity and Ethical Hacking

This roadmap ensures a comprehensive understanding of Python from basic


syntax and operations to advanced topics like machine learning and web
development. By the end, you will have both theoretical knowledge and practical

ng
experience to work on real-world projects.

Let’s Explore Each Section…

ni
ar
--------------------------------------------------------------------------------------------

2. Introduction to Python
Le
ve
si
er
m
Em

Python is a high-level, interpreted programming language known for its simplicity


and readability. It was created by Guido van Rossum and first released in 1991.
Python is widely used in web development, data analysis, artificial intelligence,
scientific computing, automation, and more.

9
Let’s break down the key components in the Introduction to Python:

1. What is Python?

Python is a general-purpose programming language that supports multiple


programming paradigms, such as procedural, object-oriented, and functional

ng
programming.

ni
● Readable and Maintainable Code: Python's syntax is simple and easy to
read, making it ideal for beginners. Its structure makes code maintainable

ar
and scalable.
● Interpreted Language: Python is executed line by line, which means it is
Le
interpreted rather than compiled. This simplifies the debugging process.
● Cross-Platform Language: Python is platform-independent, meaning that
Python programs can run on various operating systems like Windows,
ve

macOS, and Linux.


● Extensive Libraries: Python has a rich set of libraries and frameworks
si

that simplify many tasks (e.g., NumPy for numerical computing, Pandas for
er

data analysis, Flask/Django for web development).


m

Key Features:

● Open-source and free to use


Em

● Dynamically typed (no need to declare variable types)


● Large community support
● Comprehensive libraries and frameworks for various applications

2. Why Learn Python?

10
Python is popular because of its flexibility and a wide range of applications, from
beginners writing simple scripts to professionals developing large-scale
applications.

● Ease of Learning: Python has a clear and straightforward syntax that is


easy for beginners.
● Versatility: Python can be used for web development, machine learning,

ng
artificial intelligence, data analysis, automation, and more.
● Job Opportunities: Python is in high demand in fields like data science,

ni
web development, and automation.

ar
Le
ve
si
er
m
Em

3. Installing Python

Before you can start writing Python code, you need to have Python installed on
your system. You can download Python from the official Python website. Python

11
comes with a package manager called pip, which allows you to install third-party
libraries.

Steps to Install Python:

1. Go to the official website: https://www.python.org/downloads/


2. Download the installer: Choose the version for your operating system

ng
(Windows, macOS, or Linux).
3. Run the installer: Follow the installation steps. Make sure to check the
box that says “Add Python to PATH” to ensure you can run Python from the

ni
command line.

ar
4. Verify installation: Open the command line and type python
--version or python3 --version. You should see the installed
version of Python.
Le
ve

4. Setting Up an IDE for Python Development


si

An IDE (Integrated Development Environment) makes it easier to write, debug,


er

and execute Python code.

Popular IDEs for Python:


m

● PyCharm: A full-featured Python IDE with powerful tools for professional


Em

developers.
● VS Code: A lightweight editor with Python extension support.
● Jupyter Notebooks: An excellent tool for data science and machine
learning, which allows for interactive coding.
● IDLE: The default Python IDE, which comes with Python installations.

Installing VS Code (for example):

12
1. Download Visual Studio Code from the official site.
2. Install the Python extension from the VS Code marketplace to get support
for Python syntax, autocompletion, and debugging.

5. Writing and Running Your First Python Program

ng
Now that Python is installed, let’s write a simple Python program. We’ll start with
the classic:

ni
print("Hello, World!")

ar
Running Your Program:
Le
1. Using the Command Line/Terminal:
ve
○ Save the above code in a file named hello.py.
○ Open your terminal/command prompt and navigate to the folder
si

where the file is saved.


er

Run the program using the following command:


m

python hello.py
Em

2. Using an IDE:
○ Open your IDE (e.g., VS Code or PyCharm).
○ Create a new file and save it with a .py extension (e.g., hello.py).
○ Write the print("Hello, World!") code.

13
○ Run the program by pressing the "Run" button or using the shortcut
(usually F5).

You should see Hello, World! printed as output.

6. Python Syntax

ng
Python syntax defines how Python code should be written. Python emphasizes

ni
readability and uses indentation rather than curly braces or keywords to define
code blocks.

ar
Key Points about Python Syntax:

Le
Indentation: Indentation is critical in Python. It defines the structure and scope of

loops, functions, and conditions.


ve

if True:
print("This is indented") # This line is part of the if
si

block
er

● Case Sensitivity: Python is case-sensitive, meaning Variable and


m

variable are two different identifiers.


Em

7. Python Keywords

Python has a set of reserved keywords that cannot be used as variable names,
function names, or identifiers. Examples include:

14
● if, else, elif
● for, while
● try, except, finally
● def, class
● import, from, as

ng
ni
ar
Le
ve
si
er

You can get a list of all keywords in Python by importing the keyword module:
m

import keyword
Em

print(keyword.kwlist)

8. Python Comments

15
In Python, comments are used to describe code and make it easier for humans
to understand. They are ignored during execution.

● Single-line comments: Use the # symbol.


● Multi-line comments: Python doesn’t have a distinct syntax for multi-line
comments. You can use multiple # or a string literal (triple quotes) that is
not assigned to any variable.

ng
# This is a single-line comment

ni
"""

ar
This is a multi-line comment.
It spans multiple lines.

"""
Le
ve
si
er

9. Python Indentation

Indentation refers to the spaces at the beginning of a code line. Unlike other
m

programming languages, Python uses indentation to define the blocks of code.


Em

● 4 spaces or a tab is the typical indentation style. Consistency in


indentation is important.

if True:
print("Indented block")
if True:
print("Nested indented block")

16
10. Python Code Style (PEP 8)

PEP 8 is the style guide for Python code. It defines how Python code should be
formatted for readability.

ng
Some key guidelines from PEP 8:

ni
● Indentation: Use 4 spaces per indentation level.

ar
● Line length: Limit lines to 79 characters.
● Blank lines: Use blank lines to separate functions and classes, and large
blocks of code inside functions. Le
● Import rules: Imports should be on separate lines and at the top of the file.

Example:
ve

import os
si

import sys
er
m
Em

Conclusion

In this introduction to Python, you have learned what Python is, how to install it,
how to write and run your first program, and an overview of its syntax and
essential components. Now, you are ready to dive into Python Basics and
explore Python’s fundamental concepts in detail!

17
3. Python Basics
The basics of Python cover essential concepts that form the foundation for
understanding and writing Python programs. In this section, we'll cover:

1. Variables and Data Types

ng
2. Operators
3. Input/Output

ni
4. Type Conversion
5. Comments

ar
6. Indentation and Block Structures
7. Conditional Statements
8. Loops
Le
9. Functions
ve
si

4. Variables and Data Types


er

1. Variables
m
Em

1. What is a Variable?

A variable in Python is a symbolic name that is a reference or pointer to an


object. Once an object is assigned to a variable, you can refer to the object by
that name. Variables are created by assigning a value to a name.

2. Assigning Values to Variables

18
In Python, you can assign values to variables using the = operator.

# Assigning an integer to a variable


age = 25

# Assigning a floating-point number to a variable


height = 5.9

ng
# Assigning a string to a variable
name = "John"

ni
# Assigning a boolean to a variable

ar
is_student = True

3. Variable Types (Data Types)


Le
Python is a dynamically typed language, meaning you don’t have to declare the
ve

type of a variable when you create one. The type is inferred from the value you
assign to it. Here are some common data types in Python:
si

Integer (int)
er

age = 25
m

Floating-point number (float)


Em

height = 5.9

String (str)

name = "John"

Boolean (bool)

19
is_student = True

List (list)

fruits = ["apple", "banana", "cherry"]

Tuple (tuple)

ng
coordinates = (10.0, 20.0)

ni
Dictionary (dict)

ar
person = {"name": "John", "age": 25} Le
Set (set)
ve

unique_numbers = {1, 2, 3, 4, 5}
si

4. Multiple Assignment
er

Python allows you to assign values to multiple variables in a single statement.


m

# Assigning multiple variables in one line


Em

x, y, z = 10, 20, 30
print(x, y, z)

# Swapping variables
a, b = b, a

5. Variable Naming Conventions

20
● Variable names can contain letters, numbers, and underscores.
○ Examples: age, height, name, is_student
● Variable names must start with a letter or an underscore (_), but not a
number.
○ Valid: _name, height
○ Invalid: 1age

ng
● Variable names are case-sensitive.
○ name and Name are different variables.

ni
● Use descriptive names to make your code more readable.
○ Prefer: total_price over tp

ar
6. Constants
Le
By convention, constant names are written in all uppercase letters. Constants are
variables whose value should not change throughout the program.
ve

PI = 3.14159
si

GRAVITY = 9.8
er

7. Variable Scope
m

The scope of a variable determines where in the program a variable is


Em

accessible. In Python, there are two types of variable scope:

Global Scope: Variables declared outside of any function or block. They can be
accessed anywhere in the code.

x = 10 # Global variable

def func():

21
print(x) # Accessing global variable

func()

Local Scope: Variables declared within a function or block. They can only be
accessed within that function or block.

def func():

ng
y = 5 # Local variable
print(y)

ni
func()

ar
# print(y) # This would cause an error as y is not accessible
outside the function

8. Global and Local Variables


Le
ve
You can use the global keyword to modify a global variable inside a function.
si

x = 10
er

def func():
global x
x = 20
m

func()
Em

print(x) # Output: 20

9. Deleting Variables

You can delete a variable using the del keyword.

22
name = "John"
print(name)

del name
# print(name) # This would cause an error as the variable is
deleted

ng
10. Variable Type Checking and Conversion
Checking the Type:

ni
x = 10

ar
print(type(x)) # Output: <class 'int'>

Type Conversion (Casting):


Le
x = 10 # Integer
ve
y = 5.5 # Float
z = "123" # String
si

# Converting to float
er

a = float(x)
print(a) # Output: 10.0
m

# Converting to int
b = int(y)
Em

print(b) # Output: 5

# Converting to string
c = str(x)
print(c) # Output: "10"

# Converting string to int


d = int(z)

23
print(d) # Output: 123

Examples and Practice

Here are a few examples to practice and reinforce the concepts:

Basic Variable Assignment and Operations:

ng
ni
# Assigning values
a = 10

ar
b = 20

# Performing arithmetic operations


sum_result = a + b
diff_result = a - b
Le
product_result = a * b
ve
quotient_result = a / b

print("Sum:", sum_result)
si

print("Difference:", diff_result)
print("Product:", product_result)
er

print("Quotient:", quotient_result)
m
Em

Using Different Data Types:

name = "Alice"
age = 30
height = 5.7
is_employed = True
skills = ["Python", "Data Analysis", "Machine Learning"]

print("Name:", name)

24
print("Age:", age)
print("Height:", height)
print("Is Employed:", is_employed)
print("Skills:", skills)

1. Working with Global and Local Variables:

ng
x = 50 # Global variable

ni
def my_function():
x = 10 # Local variable

ar
print("Local x:", x)

my_function()
print("Global x:", x)
Le
2. Variable Type Conversion:
ve
si

# Input is always treated as a string


age = input("Enter your age: ")
er

print("Your age is:", age)


print("Data type of age:", type(age))
m

# Convert age to an integer


Em

age = int(age)
print("Data type of age after conversion:", type(age))

These examples cover a variety of variable-related concepts in Python, helping


you to understand and use variables effectively in your programs.

25
Input/Output

Input:

In Python, the input() function is used to take input from the user.
By default, it reads the input as a string.

ng
Example:

ni
name = input("Enter your name: ")
print("Hello, " + name)

ar
Output:
Le
The print() function is used to display output.
ve

Example:
si
er

age = 25
m

print("I am", age, "years old.") # Output: I am 25


years old.
Em

26
2. Data Types

Python has several built-in data types that allow you to store and manipulate
different kinds of data. Let's go through the most common data types in Python.

ng
1. Numeric Types

ni
a. Integer (int)

ar
Integers are whole numbers, positive or negative, without decimals.

age = 25
year = 2024
negative_number = -10
Le
print(type(age)) # Output: <class 'int'>
ve
si

b. Floating-point Number (float)


er

Floats are numbers that contain decimal points.


m

height = 5.9
Em

pi = 3.14159
negative_float = -7.3
print(type(height)) # Output: <class 'float'>

c. Complex Number (complex)

27
Complex numbers are in the form of a + bj, where a is the real part and b is
the imaginary part.

complex_number = 2 + 3j
print(type(complex_number)) # Output: <class 'complex'>

ng
2. Sequence Types

ni
a. String (str)

ar
Strings are sequences of characters, enclosed in single or double quotes.

name = "Alice"
greeting = 'Hello, world!'
Le
multiline_string = """This is a
ve
multiline string"""
print(type(name)) # Output: <class 'str'>
si
er

Strings are immutable, meaning you cannot change their content once created.
However, you can create new strings based on existing ones.
m

# Concatenation
Em

full_greeting = greeting + " " + name


print(full_greeting) # Output: Hello, world! Alice

# Repetition
repeated_string = name * 3
print(repeated_string) # Output: AliceAliceAlice

28
b. List (list)

Lists are ordered, mutable collections of items. Items can be of different types.

fruits = ["apple", "banana", "cherry"]


mixed_list = [1, "Hello", 3.14, True]
print(type(fruits)) # Output: <class 'list'>

ng
# Accessing list items
print(fruits[0]) # Output: apple

ni
# Modifying list items

ar
fruits[1] = "blueberry"
print(fruits) # Output: ['apple', 'blueberry', 'cherry']

# Adding items to a list


fruits.append("orange")
Le
print(fruits) # Output: ['apple', 'blueberry', 'cherry',
ve
'orange']
si

c. Tuple (tuple)
er

Tuples are ordered, immutable collections of items.


m

coordinates = (10.0, 20.0)


Em

print(type(coordinates)) # Output: <class 'tuple'>

# Accessing tuple items


print(coordinates[1]) # Output: 20.0

# Tuples are immutable


# coordinates[1] = 30.0 # This would cause an error

29
d. Range (range)

Ranges represent an immutable sequence of numbers and are often used for
looping a specific number of times.

numbers = range(10)
print(type(numbers)) # Output: <class 'range'>

ng
# Convert to list to see the range values
print(list(numbers)) # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ni
ar
3. Mapping Type

Dictionary (dict)
Le
Dictionaries are unordered, mutable collections of key-value pairs.
ve

person = {"name": "Alice", "age": 25, "is_student": True}


si

print(type(person)) # Output: <class 'dict'>


er

# Accessing dictionary items


print(person["name"]) # Output: Alice
m

# Modifying dictionary items


Em

person["age"] = 26
print(person) # Output: {'name': 'Alice', 'age': 26,
'is_student': True}

# Adding new key-value pairs


person["height"] = 5.7
print(person) # Output: {'name': 'Alice', 'age': 26,
'is_student': True, 'height': 5.7}

30
4. Set Types

Set (set)

Sets are unordered collections of unique items.

ng
unique_numbers = {1, 2, 3, 4, 5}
print(type(unique_numbers)) # Output: <class 'set'>

ni
# Sets automatically remove duplicates

ar
unique_numbers = {1, 2, 2, 3, 3, 4, 5}
print(unique_numbers) # Output: {1, 2, 3, 4, 5}

# Adding items to a set


unique_numbers.add(6)
Le
print(unique_numbers) # Output: {1, 2, 3, 4, 5, 6}
ve

# Removing items from a set


unique_numbers.remove(2)
si

print(unique_numbers) # Output: {1, 3, 4, 5, 6}


er
m

Frozen Set (frozenset)


Em

Frozen sets are immutable sets.

frozen_numbers = frozenset([1, 2, 3, 4, 5])


print(type(frozen_numbers)) # Output: <class 'frozenset'>

# Frozen sets are immutable


# frozen_numbers.add(6) # This would cause an error

31
5. Boolean Type

Boolean (bool)

Booleans represent one of two values: True or False.

is_sunny = True

ng
is_raining = False
print(type(is_sunny)) # Output: <class 'bool'>

ni
# Boolean expressions
print(5 > 3) # Output: True

ar
print(3 > 5) # Output: False

6. None Type
Le
ve
NoneType

None represents the absence of a value or a null value.


si
er

nothing = None
print(type(nothing)) # Output: <class 'NoneType'>
m
Em

Type Conversion

You can convert between data types using various functions:

# Converting to integer
int_value = int("123")
print(int_value) # Output: 123

32
# Converting to float
float_value = float("123.45")
print(float_value) # Output: 123.45

# Converting to string
str_value = str(123)
print(str_value) # Output: "123"

ng
# Converting to list
list_value = list(range(5))

ni
print(list_value) # Output: [0, 1, 2, 3, 4]

ar
# Converting to tuple
tuple_value = tuple(range(5))
Le
print(tuple_value) # Output: (0, 1, 2, 3, 4)

# Converting to set
ve
set_value = set([1, 2, 3, 4, 4, 5])
print(set_value) # Output: {1, 2, 3, 4, 5}
si
er

These are the core data types in Python. Understanding these will help you work
with data effectively in your programs. If you have any questions or need further
m

clarification on any specific data type, feel free to ask!


Em

5. Operators
operators are special symbols or keywords that carry out operations on values
and python variables.

33
ng
ni
ar
Le
ve

1. Arithmetic Operations
si

Arithmetic operations are used to perform mathematical calculations.


er
m
Em

34
ng
ni
ar
Addition (+)
result = 5 + 3
Le
print(result) # Output: 8
ve

Subtraction (-)
si
er

result = 5 - 3
print(result) # Output: 2
m

Multiplication (*)
Em

result = 5 * 3
print(result) # Output: 15

Division (/)

result = 5 / 3

35
print(result) # Output: 1.6666666666666667

Floor Division (//)

result = 5 // 3

ng
print(result) # Output: 1

ni
Modulus (%)

ar
result = 5 % 3
print(result) # Output: 2
Le
ve

Exponentiation (**)
si

result = 5 ** 3
print(result) # Output: 125
er
m

2. Comparison Operations
Em

Comparison operations are used to compare two values. They return a boolean
value (True or False).

36
ng
ni
ar
Equal to (==)

result = (5 == 3)
print(result) # Output: False
Le
ve

Not equal to (!=)


si
er

result = (5 != 3)
print(result) # Output: True
m

Greater than (>)


Em

result = (5 > 3)
print(result) # Output: True

Less than (<)

result = (5 < 3)

37
print(result) # Output: False

Greater than or equal to (>=)

result = (5 >= 3)
print(result) # Output: True

ng
Less than or equal to (<=)

ni
ar
result = (5 <= 3)
print(result) # Output: False

Le
3. Logical Operations
ve
Logical operations are used to combine conditional statements. They also return
a boolean value (True or False).
si
er
m
Em

Logical AND (and)

result = (5 > 3) and (3 > 2)

38
print(result) # Output: True

Logical OR (or)

result = (5 > 3) or (3 < 2)


print(result) # Output: True

ng
Logical NOT (not)

ni
result = not (5 > 3)
print(result) # Output: False

ar
4. String Operations Le
Python provides various operations to manipulate strings.
ve
Concatenation (+)
si

greeting = "Hello, " + "world!"


print(greeting) # Output: Hello, world!
er

Repetition (*)
m
Em

repeated_string = "Hello" * 3
print(repeated_string) # Output: HelloHelloHello

String Length (len())

length = len("Hello, world!")


print(length) # Output: 13

39
String Indexing

string = "Hello, world!"


first_char = string[0]
last_char = string[-1]

ng
print(first_char) # Output: H
print(last_char) # Output: !

ni
ar
String Slicing

substring = string[0:5]
print(substring) # Output: Hello
Le
ve

String Methods
si

string = "Hello, world!"


upper_string = string.upper()
er

lower_string = string.lower()
replaced_string = string.replace("world", "Python")
m

print(upper_string) # Output: HELLO, WORLD!


print(lower_string) # Output: hello, world!
Em

print(replaced_string) # Output: Hello, Python!

5. Assignment Operations

Assignment operations are used to assign values to variables.

40
ng
ni
ar
Simple Assignment (=)
Le
ve

a = 5
si

Add and Assign (+=)


er
m

a = 5
a = 5
a += 3 # Equivalent to a = a + 3
Em

print(a) # Output: 8

Subtract and Assign (-=)

a = 5
a -= 3 # Equivalent to a = a - 3

41
print(a) # Output: 2

Multiply and Assign (*=)

a = 5
a *= 3 # Equivalent to a = a * 3
print(a) # Output: 15

ng
ni
Divide and Assign (/=)

ar
a = 5
a /= 2 # Equivalent to a = a / 2
print(a) # Output: 2.5 Le
Floor Divide and Assign (//=)
ve

a = 5
a //= 2 # Equivalent to a = a // 2
si

print(a) # Output: 2
er
m

Modulus and Assign (%=)


Em

a = 5
a %= 3 # Equivalent to a = a % 3
print(a) # Output: 2

Exponentiate and Assign (**=)

42
a = 5
a **= 3 # Equivalent to a = a ** 3
print(a) # Output: 125

6. Membership Operations

Membership operations are used to test if a value is a member of a sequence,

ng
such as a string, list, or tuple.

ni
ar
Le
ve
In (in)
si

fruits = ["apple", "banana", "cherry"]


result = "apple" in fruits
er

print(result) # Output: True


m

Not In (not in)


Em

result = "grape" not in fruits


print(result) # Output: True

7. Identity Operations

Identity operations compare the memory locations of two objects.

43
ng
Is (is)

ni
a = [1, 2, 3]

ar
b = a
result = a is b
print(result) # Output: True
Le
Is Not (is not)
ve

a = [1, 2, 3]
b = [1, 2, 3]
si

result = a is not b
print(result) # Output: True
er
m

These are the fundamental operations in Python that you will use frequently. If
you have any specific questions or need further clarification on any of these
Em

operations, feel free to ask!

8. Python Bitwise Operators

Bitwise operators are used to compare (binary) numbers:

44
ng
ni
ar
This is all about Operators in python. Le
ve

6. Control Flow
si

Control flow in Python refers to the order in which individual statements,


er

instructions, or function calls are executed or evaluated.


m
Em

45
ng
ni
ar
Le
Python has several control flow tools to manage the execution of code:
conditionals (if, elif, else), loops (for, while), and control flow statements
(break, continue, pass).
ve

Control Flow Statements


si
er

The flow control statements are divided into three categories


m

1. Conditional statements
Em

2. Iterative statements.
3. Transfer statements

46
ng
ni
ar
Le
Let's go through each of these in detail.
ve
1. Conditional Statements

Conditional statements allow you to execute specific blocks of code based on


si

certain conditions.
er

a. if Statement
m

The if statement is used to test a specific condition. If the condition is True, the
Em

block of code inside the if statement is executed.

47
ng
ni
ar
Le
x = 10
ve
if x > 5:
print("x is greater than 5")
si

b. if-else Statement
er

The else statement can be used along with the if statement to execute a block
m

of code if the condition is False.


Em

48
ng
ni
ar
x = 3
if x > 5:
Le
print("x is greater than 5")
ve
else:
print("x is not greater than 5")
si

c. if-elif-else Statement
er

The elif (short for else if) statement allows you to check multiple conditions.
m
Em

49
ng
ni
ar
Le
ve
si

x = 5
er

if x > 5:
print("x is greater than 5")
m

elif x == 5:
print("x is equal to 5")
Em

else:
print("x is less than 5")

2. Loop Statements

Loops are used to execute a block of code repeatedly.

a. for Loop

50
The for loop is used to iterate over a sequence (such as a list, tuple, string, or
range).

ng
ni
ar
Le
ve

# Iterating over a list


fruits = ["apple", "banana", "cherry"]
si

for fruit in fruits:


print(fruit)
er

# Iterating over a range of numbers


m

for i in range(5):
print(i)
Em

b. while Loop

51
The while loop is used to repeat a block of code as long as a condition is True.

ng
ni
ar
Le
count = 0
ve
while count < 5:
print(count)
count += 1
si
er

3. Control Flow Statements


m

Control flow statements can change the execution from its normal sequence.
Em

a. break Statement

The break statement is used to exit a loop prematurely.

for i in range(10):
if i == 5:
break
print(i)

52
b. continue Statement

The continue statement is used to skip the rest of the code inside a loop for the
current iteration only.

ng
for i in range(10):
if i % 2 == 0:
continue

ni
print(i)

ar
c. pass Statement

Le
The pass statement is a null operation; it is used as a placeholder for future
code.
ve

for i in range(5):
if i == 3:
si

pass # Do nothing (placeholder)


else:
er

print(i)
m

4. Nested Control Flow


Em

Control flow statements can be nested within each other.

# Nested if statements
x = 10
y = 5
if x > 5:
if y > 3:

53
print("x is greater than 5 and y is greater than 3")

# Nested loops
for i in range(3):
for j in range(2):
print(f"i = {i}, j = {j}")

ng
5. else Clause with Loops

ni
Loops in Python can have an else clause, which is executed when the loop

ar
completes normally (i.e., not terminated by a break statement).

# `else` with a `for` loop


for i in range(5):
print(i)
Le
else:
ve
print("Loop completed without break")
si

# `else` with a `while` loop


count = 0
er

while count < 5:


print(count)
count += 1
m

else:
print("Loop completed without break")
Em

6. Comprehensions

Comprehensions provide a concise way to create lists, sets, and dictionaries.

a. List Comprehensions

54
squares = [x ** 2 for x in range(10)]
print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

b. Set Comprehensions

unique_squares = {x ** 2 for x in range(10)}


print(unique_squares) # Output: {0, 64, 1, 4, 36, 9, 16, 81,

ng
49, 25}

ni
c. Dictionary Comprehensions

ar
square_dict = {x: x ** 2 for x in range(10)}
Le
print(square_dict) # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5:
25, 6: 36, 7: 49, 8: 64, 9: 81}

Understanding these control flow tools will allow you to write more complex and
ve

flexible Python programs.


si
er

7. Functions
m
Em

Functions are one of the most important aspects of Python programming. They
allow you to group a set of statements so they can be run more than once in a
program. Functions also let you specify parameters and return values.

55
ng
ni
ar
Le
1. What is a Function?
ve

A function is a block of organised, reusable code that performs a single, related


si

action. Functions provide better modularity and a high degree of code reusability.
er
m
Em

56
Em
m
er
si
ve
Le
ar
ni
ng

57
Types of Functions

ng
ni
ar
Le
ve
si
er
m
Em

58
1. Built in functions

ng
ni
ar
Le
ve
2. User Defined Functions
si

User Defined Functions


er

2. Defining a Function
m

In Python, a function is defined using the def keyword, followed by the function
Em

name, parentheses (), and a colon :. The body of the function contains the
code that will be executed when the function is called.

59
ng
ni
ar
def function_name(parameters):
# Function body
pass
Le
ve

Example:
si

def greet():
print("Hello, world!")
er
m

3. Calling a Function
Em

To call a function, simply use its name followed by parentheses.

60
ng
ni
ar
greet() # Output: Hello, world!
Le
ve
si
er
m
Em

4. Function Parameters

Parameters allow you to pass information into a function. You define parameters
within the parentheses in the function definition.

61
ng
ni
ar
Le
ve
si

Python code
er

def greet(name):
print(f"Hello, {name}!")
m
Em

Example:

greet("Alice") # Output: Hello, Alice!

5. Default Parameters

You can provide default values for parameters. If no argument is passed for a
parameter with a default value, the default value is used.

62
def greet(name="World"):
print(f"Hello, {name}!")

Example:

greet() # Output: Hello, World!


greet("Alice") # Output: Hello, Alice!

ng
6. Return Statement

ni
ar
The return statement is used to exit a function and return a value to the caller.

def add(a, b):


return a + b
Le
ve
Example:

result = add(3, 5)
si

print(result) # Output: 8
er

7. Function Annotations
m

Function annotations are a way to attach metadata to function parameters and


Em

return values.

def greet(name: str) -> str:


return f"Hello, {name}!"

8. Variable-Length Arguments

63
*a. args

The *args parameter allows a function to accept any number of positional


arguments.

def add(*args):
return sum(args)

ng
Example:

ni
result = add(1, 2, 3)

ar
print(result) # Output: 6

**b. kwargs
Le
The **kwargs parameter allows a function to accept any number of keyword
ve

arguments.
si

def display_info(**kwargs):
for key, value in kwargs.items():
er

print(f"{key}: {value}")
m

Example:
Em

display_info(name="Alice", age=30) # Output: name: Alice, age:


30

9. Lambda Functions

Lambda functions are small anonymous functions defined using the lambda
keyword.

64
add = lambda a, b: a + b

Example:

result = add(3, 5)
print(result) # Output: 8

ng
10. Higher-Order Functions

ni
A higher-order function is a function that takes another function as an argument

ar
or returns a function as a result.

Example:

def apply_func(func, value):


Le
return func(value)
ve

def square(x):
return x * x
si

result = apply_func(square, 5)
er

print(result) # Output: 25
m

11. Decorators
Em

Decorators are a powerful tool in Python that allows you to modify the behaviour
of a function or method. They are defined using the @ symbol.

def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print("Wrapper executed before

65
{}".format(original_function.__name__))
return original_function(*args, **kwargs)
return wrapper_function

@decorator_function
def display():
print("Display function ran")

ng
display()

ni
Example:

ar
# Output:
# Wrapper executed before display
# Display function ran Le
12. Docstrings
ve

Docstrings provide a convenient way of associating documentation with Python


si

modules, functions, classes, and methods.


er

def greet(name):
"""
m

This function greets the person whose name is passed as a


parameter.
Em

"""
print(f"Hello, {name}!")

Conclusion

Functions are a fundamental part of Python programming. They allow you to


encapsulate code, making it reusable and easier to manage. Understanding how

66
to define, call, and use functions, along with advanced features like decorators
and lambda functions, will significantly enhance your ability to write clean and
efficient code.

ng
8. Data Structures

ni
● Python provides several built-in data structures that allow you to organise

ar
and store data efficiently.
● These include lists, tuples, dictionaries, sets, and more. Let’s go through
each of these in detail. Le
ve
si
er
m
Em

67
ng
ni
ar
Le
ve

Built in Non Primitive


si
er
m
Em

1. Lists

68
Lists are ordered, mutable (changeable), and allow duplicate elements. They are
defined using square brackets [].

ng
ni
ar
1. Creating Lists
Le
ve
A list in Python is created using square brackets [], and elements are separated
by commas.
si

Example:
er

Python code:
m

# Creating a list of strings


Em

fruits = ["apple", "banana", "cherry"]

# Creating a list of integers


numbers = [1, 2, 3, 4, 5]

# Creating a list of mixed data types

69
mixed = [1, "apple", 3.5, True]

2. Accessing List Elements

List elements can be accessed by their index, which starts at 0 for the first

ng
element and -1 for the last element.

Example:

ni
Python code

ar
# Accessing elements
print(fruits[0])
print(fruits[-1])
# Output: apple Le
# Output: cherry
ve

3. Modifying Lists
si

Lists are mutable, meaning their elements can be changed after the list is
er

created.
m

Example:
Em

Python code

# Modifying elements
fruits[1] = "blueberry"
print(fruits) # Output: ['apple', 'blueberry', 'cherry']

70
4. Adding Elements

a. append()

Adds an element to the end of the list.

Python code፡

ng
fruits.append("orange")
print(fruits) # Output: ['apple', 'blueberry', 'cherry',

ni
'orange']

ar
b. insert()

Inserts an element at a specific position.


Le
ve
Python code
si

fruits.insert(1, "kiwi")
print(fruits) # Output: ['apple', 'kiwi', 'blueberry',
er

'cherry', 'orange']
m
Em

5. Removing Elements

a. remove()

Removes the first occurrence of a specified element.

Python code

71
fruits.remove("kiwi")
print(fruits) # Output: ['apple', 'blueberry', 'cherry',
'orange']

b. pop()

ng
Removes and returns the element at a specified index (or the last element if no

ni
index is specified).

ar
Python code

popped_fruit = fruits.pop()
print(popped_fruit)
Le
# Output: orange
print(fruits) # Output: ['apple', 'blueberry', 'cherry']
ve
si

c. del
er

Deletes an element at a specified index.


m

Python code
Em

del fruits[1]
print(fruits) # Output: ['apple', 'cherry']

6. List Operations

a. Concatenation

72
Combines two lists using the + operator.

Python code

list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined_list = list1 + list2

ng
print(combined_list) # Output: [1, 2, 3, 4, 5, 6]

ni
ar
b. Repetition

Repeats the elements of a list using the * operator.

Python code
Le
ve
repeated_list = list1 * 3
print(repeated_list) # Output: [1, 2, 3, 1, 2, 3, 1, 2, 3]
si
er

c. Membership
m

Checks if an element is in the list using the in operator.


Em

Python code

print(1 in list1) # Output: True


print(4 in list1) # Output: False

7. List Slicing

73
Extracts a subset of a list using the slicing syntax list[start:end].

Python code

subset = fruits[0:2]
print(subset) # Output: ['apple', 'cherry']

ng
8. List Methods

ni
ar
Le
ve
si
er
m
Em

a. sort()

Sorts the list in ascending order.

Python code

numbers = [3, 1, 4, 1, 5, 9]

74
numbers.sort()
print(numbers) # Output: [1, 1, 3, 4, 5, 9]

b. reverse()

ng
Reverses the elements of the list.

Python code

ni
numbers.reverse()

ar
print(numbers) # Output: [9, 5, 4, 3, 1, 1]

Le
c. index()
ve

Returns the index of the first occurrence of a specified element.


si

Python code
er

index = fruits.index("cherry")
m

print(index) # Output: 1
Em

d. count()

Returns the number of occurrences of a specified element.

Python code

75
count = numbers.count(1)
print(count) # Output: 2

e. copy()

ng
Returns a shallow copy of the list.

Python code

ni
fruits_copy = fruits.copy()

ar
print(fruits_copy) # Output: ['apple', 'cherry']

Le
f. clear()
ve

Removes all elements from the list.


si

Python code
er

fruits.clear()
m

print(fruits) # Output: []
Em

9. List Comprehensions

A concise way to create lists.

Python code

76
squares = [x**2 for x in range(10)]
print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

10. Nested Lists

ng
Lists within lists.

Python code

ni
ar
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(nested_list[0][1]) # Output: 2

Le
Summary
ve

● Creating lists: Using square brackets [].


si

● Accessing elements: Using indices.


er

● Modifying lists: Changing elements, adding, removing.


● List operations: Concatenation, repetition, membership.
m

● List slicing: Extracting sublists.


● List methods: sort(), reverse(), index(), count(), copy(),
Em

clear().
● List comprehensions: Creating lists concisely.
● Nested lists: Lists within lists.

Lists are a fundamental data structure in Python, providing a versatile way to


store and manipulate collections of items.

77
2. Tuples

Tuples are an important data structure in Python that are similar to lists but have
some key differences. They are immutable, meaning once created, their
elements cannot be changed. Here's a comprehensive guide to understanding

ng
tuples in Python.

ni
ar
Le
ve
si
er
m
Em

78
ng
ni
ar
1. Creating Tuples
Le
Tuples are defined using parentheses () with elements separated by commas.
ve
Example:
si

Python code:
er

# Creating a tuple of strings


m

fruits = ("apple", "banana", "cherry")


Em

# Creating a tuple of integers


numbers = (1, 2, 3, 4, 5)

# Creating a tuple of mixed data types


mixed = (1, "apple", 3.5, True)

79
# Creating an empty tuple
empty_tuple = ()

For a single element tuple, a comma is needed to avoid confusion with


parentheses used for other purposes.

ng
Python code:

ni
single_element_tuple = (42,)

ar
2. Accessing Tuple Elements Le
Like lists, tuple elements can be accessed by their index, which starts at 0.
ve
Example:
Python code:
si
er

# Accessing elements
m

print(fruits[0]) # Output: apple


print(fruits[-1]) # Output: cherry
Em

3. Tuple Immutability

Once a tuple is created, its elements cannot be modified, added, or removed.


Any attempt to do so will result in an error.

80
Example:
Python code:

# Attempting to change an element (will raise an error)


# fruits[1] = "blueberry" # TypeError: 'tuple' object does not
support item assignment

ng
# Attempting to add an element (will raise an error)

ni
# fruits.append("orange") # AttributeError: 'tuple' object has
no attribute 'append'

ar
4. Tuple Operations
Le
a. Concatenation
ve

Combines two or more tuples using the + operator.


si

Python code :
er

#Concatenating tuples
m
Em

tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
combined_tuple = tuple1 + tuple2
print(combined_tuple) # Output: (1, 2, 3, 4, 5, 6)

b. Repetition

81
Repeats the elements of a tuple using the * operator.

Python code :

repeated_tuple = tuple1 * 3
print(repeated_tuple) # Output: (1, 2, 3, 1, 2, 3, 1, 2, 3)

ng
c. Membership

ni
Checks if an element is in the tuple using the in operator.

ar
Python code:

print(1 in tuple1)
Le
# Output: True
print(4 in tuple1) # Output: False
ve
si

5. Tuple Slicing
er

Extracts a subset of a tuple using the slicing syntax tuple[start:end].


m

Python code:
Em

subset = fruits[0:2]
print(subset) # Output: ('apple', 'banana')

6. Tuple Methods

82
Tuples support a limited number of methods compared to lists due to their
immutability.

a. count()

Returns the number of occurrences of a specified element.

Python code:

ng
count = numbers.count(3)

ni
print(count) # Output: 1

ar
b. index() Le
Returns the index of the first occurrence of a specified element.
ve
Python code:
si

index = fruits.index("cherry")
er

print(index) # Output: 2
m

7. Nested Tuples
Em

Tuples can contain other tuples, which is useful for complex data structures.

Python code :

nested_tuple = ((1, 2, 3), ("a", "b", "c"), (True, False, True))


print(nested_tuple[1][2]) # Output: c

83
8. Converting Between Lists and Tuples

You can convert a list to a tuple using the tuple() function and vice versa using
the list() function.

ng
Example:
Python code :

ni
# Converting a list to a tuple
fruits_list = ["apple", "banana", "cherry"]

ar
fruits_tuple = tuple(fruits_list)
print(fruits_tuple)
Le
# Output: ('apple', 'banana', 'cherry')

# Converting a tuple to a list


ve
numbers_list = list(numbers)
print(numbers_list) # Output: [1, 2, 3, 4, 5]
si
er

9. Packing and Unpacking Tuples


m

Packing
Em

Assigning multiple values to a single variable as a tuple.

Python code:

packed_tuple = 1, 2, 3
print(packed_tuple) # Output: (1, 2, 3)

84
Unpacking

Assigning the elements of a tuple to multiple variables.

Python code:

a, b, c = packed_tuple

ng
print(a) # Output: 1
print(b) # Output: 2

ni
print(c) # Output: 3

ar
10. Tuple Use Cases
Le
Due to their immutability, tuples are often used for:
ve
● Fixed collections of data.
● Keys in dictionaries (when the keys are multi-part).
si

● Returning multiple values from a function.


er

Summary
m

● Creating tuples: Using parentheses () or without for single elements.


● Accessing elements: Using indices.
Em

● Immutability: Cannot modify, add, or remove elements.


● Tuple operations: Concatenation, repetition, membership.
● Tuple slicing: Extracting sub-tuples.
● Tuple methods: count() and index().
● Nested tuples: Tuples within tuples.
● Conversion: Between lists and tuples.
● Packing and unpacking: Assigning multiple values to/from tuples.

85
Tuples are a powerful tool in Python, especially when you need a data structure
that should not change.

Difference between Tuple and List

ng
ni
ar
Le
ve
si
er
m

3. Dictionaries
Em

Dictionaries in Python are powerful and flexible data structures that allow you to
store and manage data using key-value pairs. They are particularly useful when
you need to associate values with unique keys.

1. What is a Dictionary?

86
ng
ni
ar
Le
ve

A dictionary is a collection of key-value pairs. Each key is unique, and it maps to


si

a corresponding value. Unlike lists or tuples, dictionaries are unordered, meaning


er

the items are not stored in a specific sequence.


m

2. Creating a Dictionary
Em

Dictionaries are created using curly braces {} with key-value pairs separated by
colons :.

87
ng
ni
ar
Le
ve

Example:
si

Python code :
er

# Creating a dictionary with string keys


m

person = {
Em

"name": "John",
"age": 30,
"city": "New York"
}

# Creating a dictionary with mixed data types

88
student = {
"name": "Alice",
"age": 22,
"grades": [90, 85, 88],
"graduate": False
}

ng
# Creating an empty dictionary

ni
empty_dict = {}

ar
3. Accessing Dictionary Values
Le
You can access dictionary values by referring to their keys.
ve
Example:
Python code:
si

# Accessing values using keys


er

print(person["name"]) # Output: John


m

print(student["grades"]) # Output: [90, 85, 88]


Em

4. Modifying a Dictionary

Dictionaries are mutable, so you can change, add, or remove key-value pairs.

a. Changing Values

You can update the value associated with a specific key.

89
Python code:

person["age"] = 31
print(person["age"]) # Output: 31

ng
b. Adding Key-Value Pairs

You can add new key-value pairs to a dictionary.

ni
Python code:

ar
person["occupation"] = "Engineer"
print(person)
Le
# Output: {'name': 'John', 'age': 31, 'city':
'New York', 'occupation': 'Engineer'}
ve

c. Removing Key-Value Pairs


si

You can remove key-value pairs using the del keyword or the pop() method.
er

Python code:
m
Em

# Using del
del person["city"]
print(person) # Output: {'name': 'John', 'age': 31,
'occupation': 'Engineer'}

# Using pop()

90
age = person.pop("age")
print(age) # Output: 31
print(person) # Output: {'name': 'John', 'occupation':
'Engineer'}

ng
5. Dictionary Methods

ni
ar
Le
ve
si
er
m
Em

a. keys()

Returns a view object containing all the keys in the dictionary.

Python code:

print(person.keys()) # Output: dict_keys(['name',

91
'occupation'])

b. values()

Returns a view object containing all the values in the dictionary.

ng
Python code:

ni
int(person.values()) # Output: dict_values(['John',
'Engineer'])

ar
Le
c. items()
ve

Returns a view object containing all the key-value pairs in the dictionary.
si

Python code
er

print(person.items()) # Output: dict_items([('name', 'John'),


m

('occupation', 'Engineer')])
Em

d. update()

Updates the dictionary with the key-value pairs from another dictionary or from
an iterable of key-value pairs.

Python code:

92
person.update({"age": 32, "city": "Boston"})
print(person) # Output: {'name': 'John', 'occupation':
'Engineer', 'age': 32, 'city': 'Boston'}

e. get()

ng
Returns the value associated with a key. If the key does not exist, it returns None
(or a specified default value).

ni
Python code:

ar
print(person.get("name"))
Le
# Output: John
print(person.get("salary", "Not available")) # Output: Not
available
ve
si

f. clear()
er

Removes all key-value pairs from the dictionary.

Python code:
m
Em

person.clear()
print(person) # Output: {}

6. Looping Through a Dictionary

You can loop through a dictionary to access keys, values, or key-value pairs.

93
Example:
Python code:

# Looping through keys


for key in student:
print(key)

ng
# Looping through values

ni
for value in student.values():
print(value)

ar
# Looping through key-value pairs
for key, value in student.items():
Le
print(f"{key}: {value}")
ve

7. Dictionary Comprehensions
si
er

Similar to list comprehensions, you can create dictionaries using dictionary


comprehensions.
m

Example:
Em

Python code:

squares = {x: x*x for x in range(6)}


print(squares) # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

8. Nesting Dictionaries

94
Dictionaries can contain other dictionaries, allowing you to create complex data
structures.

Example:
Python code:

ng
nested_dict = {
"John": {"age": 30, "city": "New York"},
"Alice": {"age": 25, "city": "London"},

ni
"Bob": {"age": 35, "city": "San Francisco"}

ar
}

print(nested_dict["Alice"]["city"]) Le # Output: London


ve
9. Dictionary Use Cases
si

Dictionaries are often used when you need to:


er

● Associate unique keys with values (e.g., mapping names to phone


numbers).
m

● Store and retrieve data quickly (e.g., using keys as indexes).


● Store configuration settings or parameters.
Em

Summary

● Creating dictionaries: Using curly braces {} with key-value pairs.


● Accessing values: Using keys.
● Modifying dictionaries: Changing, adding, or removing key-value pairs.

95
● Dictionary methods: keys(), values(), items(), update(), get(),
clear().
● Looping through dictionaries: Iterating over keys, values, or key-value
pairs.
● Dictionary comprehensions: Creating dictionaries in a concise way.
● Nesting dictionaries: Storing dictionaries within dictionaries for complex

ng
data structures.

Dictionaries are a fundamental data structure in Python, and they offer great

ni
flexibility and performance for many programming tasks.

ar
4. Sets Le
Sets in Python are a built-in data structure that allows you to store unique
ve
elements in an unordered collection. They are useful when you need to perform
operations like union, intersection, difference, and membership testing with
si

collections of data.
er
m
Em

96
ng
ni
ar
1. What is a Set?
Le
ve
A set is an unordered collection of unique elements. Unlike lists or tuples, sets do
not allow duplicate elements, and they do not maintain any order. Sets are
si

defined using curly braces {} or the set() function.


er

2. Creating a Set
m

You can create a set by placing all the elements within curly braces {} or by
Em

using the set() function.

Example:
Python code:

# Creating a set of integers


numbers = {1, 2, 3, 4, 5}

97
# Creating a set of mixed data types
mixed_set = {1, "apple", 3.5, True}

# Creating an empty set


empty_set = set() # Note: {} creates an empty dictionary, not a

ng
set.

ni
3. Set Characteristics

ar
Le
ve
si
er
m
Em

● Unordered: The elements in a set do not have a specific order.


● Unique: Duplicate elements are automatically removed.

98
Example:
Python code:

# Demonstrating uniqueness
duplicates_set = {1, 2, 2, 3, 4, 4, 5}
print(duplicates_set) # Output: {1, 2, 3, 4, 5}

ng
ni
4. Accessing Set Elements

ar
Since sets are unordered, you cannot access elements by index. However, you
can loop through the elements using a for loop.

Example:
Le
Python code :
ve
for item in numbers:
print(item)
si
er

5. Modifying a Set
m

Sets are mutable, meaning you can add, remove, or modify elements.
Em

a. Adding Elements

You can add a single element using the add() method or multiple elements
using the update() method.

Python code:

99
numbers.add(6)
print(numbers) # Output: {1, 2, 3, 4, 5, 6}

numbers.update([7, 8, 9])
print(numbers) # Output: {1, 2, 3, 4, 5, 6, 7, 8, 9}

ng
b. Removing Elements

ni
You can remove elements using the remove() or discard() method. The

ar
pop() method removes and returns an arbitrary element.

Python code :
Le
numbers.remove(9) # Removes 9 from the set
ve
print(numbers) # Output: {1, 2, 3, 4, 5, 6, 7, 8}
si

numbers.discard(8) # Removes 8 from the set


print(numbers) # Output: {1, 2, 3, 4, 5, 6, 7}
er
m

# Using pop()
removed_item = numbers.pop()
Em

print(removed_item) # Output: (arbitrary item, e.g., 1)


print(numbers) # Output: Set without the popped item

6. Set Operations

100
Sets support several standard operations for mathematical set theory, such as
union, intersection, difference, and symmetric difference.

ng
ni
ar
Le
ve
si
er

a. Union
m

Combines two sets, returning a new set containing all unique elements from both
sets.
Em

Python code:

set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1.union(set2)

101
print(union_set) # Output: {1, 2, 3, 4, 5}

# Alternatively, you can use the '|' operator


union_set = set1 | set2
print(union_set) # Output: {1, 2, 3, 4, 5}

ng
b. Intersection

ni
Returns a new set containing only the elements common to both sets.

ar
Python code:

print(intersection_set)
Le
intersection_set = set1.intersection(set2)
# Output: {3}
ve

# Alternatively, you can use the '&' operator


si

intersection_set = set1 & set2


print(intersection_set) # Output: {3}
er
m

c. Difference
Em

Returns a new set containing elements in the first set but not in the second set.

Python code:

difference_set = set1.difference(set2)
print(difference_set) # Output: {1, 2}

102
# Alternatively, you can use the '-' operator
difference_set = set1 - set2
print(difference_set) # Output: {1, 2}

d. Symmetric Difference

ng
Returns a new set containing elements that are in either of the sets but not in
both.

ni
Python code:

ar
symmetric_difference_set = set1.symmetric_difference(set2)
print(symmetric_difference_set)
Le # Output: {1, 2, 4, 5}
ve
# Alternatively, you can use the '^' operator
symmetric_difference_set = set1 ^ set2
si

print(symmetric_difference_set) # Output: {1, 2, 4, 5}


er

7. Set Methods
m
Em

103
ng
ni
ar
Le
ve
si

a. issubset()
er

Checks if all elements of the first set are in the second set.
m

Python code:
Em

print(set1.issubset(set2)) # Output: False


print({1, 2}.issubset(set1)) # Output: True

b. issuperset()

104
Checks if the first set contains all elements of the second set.

Python code:

print(set1.issuperset(set2)) # Output: False


print(set1.issuperset({1, 2})) # Output: True

ng
c. isdisjoint()

ni
Checks if two sets have no elements in common.

ar
Python code:

print(set1.isdisjoint(set2))
print(set1.isdisjoint({6, 7}))
Le
# Output: False
# Output: True
ve

8. Frozen Sets
si

A frozenset is an immutable version of a set. Once created, you cannot modify its
er

elements, but you can still perform set operations like union, intersection, etc.
m

Example:
Python code :
Em

frozen_set = frozenset([1, 2, 3, 4])


print(frozen_set) # Output: frozenset({1, 2, 3, 4})

# Attempting to add or remove elements will raise an error


# frozen_set.add(5) # AttributeError: 'frozenset' object has no

105
attribute 'add'

9. Use Cases for Sets

● Removing Duplicates: Sets automatically remove duplicates, so they are


great for getting unique items from a list.

ng
● Membership Testing: Checking if an item is in a set is faster than in lists.
● Mathematical Operations: Sets are ideal for operations like union,

ni
intersection, and difference.

ar
Summary

Le
● Creating sets: Using {} or set() with unique elements.
● Accessing elements: Sets are unordered, so no indexing, but you can
loop through.
ve

● Modifying sets: Add or remove elements using add(), remove(),


discard(), or pop().
si

● Set operations: Union, intersection, difference, and symmetric difference.


er

● Set methods: issubset(), issuperset(), isdisjoint().


● Frozen sets: Immutable sets for situations where you need a fixed
m

collection of unique elements.


Em

Sets are a versatile and powerful tool in Python, especially when working with
unique data and performing mathematical set operations. If you have any specific
questions or need further examples, feel free to ask!

5. Strings

106
Although not typically classified as a data structure, strings in Python are
sequences of characters and support various operations.

ng
ni
ar
Le
Strings in Python are sequences of characters enclosed within quotes. They are
one of the most commonly used data types, providing powerful tools for text
manipulation and processing.
ve

1. What is a String?
si

A string is a sequence of characters (letters, digits, symbols, spaces, etc.)


er

enclosed in either single quotes ('), double quotes ("), or triple quotes (''' or
"""). Strings in Python are immutable, meaning once created, they cannot be
m

changed.
Em

Example:

Python code:

# Single quotes
string1 = 'Hello, World!'

107
# Double quotes
string2 = "Python is fun!"

# Triple quotes (used for multi-line strings or docstrings)


string3 = '''This is a

ng
multi-line string'''

ni
print(string1)
print(string2)

ar
print(string3)

Le
2. Accessing Characters in a String
ve

You can access individual characters in a string using indexing, where the index
si

starts from 0 for the first character. Negative indexing can be used to access
characters from the end of the string.
er

Example:
m

Python code:
Em

string = "Python"

# Accessing characters by positive index


print(string[0]) # Output: P
print(string[1]) # Output: y

108
# Accessing characters by negative index
print(string[-1]) # Output: n
print(string[-2]) # Output: o

3. Slicing Strings

ng
Slicing allows you to extract a part of the string by specifying a start and end
index. The syntax is string[start:end], where start is inclusive, and end

ni
is exclusive.

ar
Example:

Python code: Le
string = "Hello, World!"
ve

# Slicing from index 0 to 4 (exclusive)


si

print(string[0:5]) # Output: Hello


er

# Slicing from index 7 to the end


m

print(string[7:]) # Output: World!


Em

# Slicing the entire string


print(string[:]) # Output: Hello, World!

# Slicing with negative indices


print(string[-6:-1]) # Output: World

109
4. String Concatenation and Repetition

You can concatenate strings using the + operator and repeat strings using the *
operator.

Example:

ng
Python code:

# Concatenation

ni
greeting = "Hello"

ar
name = "Alice"
message = greeting + ", " + name + "!"
print(message)
Le
# Output: Hello, Alice!

# Repetition
ve
laugh = "Ha" * 3
print(laugh) # Output: HaHaHa
si
er

5. String Methods
m
Em

110
ng
ni
ar
Le
ve
Python provides a wide range of built-in string methods for various operations
like formatting, searching, replacing, and more.
si

a. lower() and upper()


er

Converts the string to lowercase or uppercase.


m

Python code:
Em

text = "Python Programming"


print(text.lower()) # Output: python programming
print(text.upper()) # Output: PYTHON PROGRAMMING

b. strip(), lstrip(), and rstrip()

111
Removes leading and trailing whitespace (or specified characters).

Python code:

text = " Hello, World! "


print(text.strip()) # Output: Hello, World!
print(text.lstrip()) # Output: "Hello, World! "

ng
print(text.rstrip()) # Output: " Hello, World!"

ni
c. replace()

ar
Replaces occurrences of a substring with another substring.

Python code:
Le
ve
text = "Hello, World!"
new_text = text.replace("World", "Python")
si

print(new_text) # Output: Hello, Python!


er
m

d. find()
Em

Returns the index of the first occurrence of a substring. Returns -1 if the


substring is not found.

Python code:

text = "Hello, World!"


index = text.find("World")

112
print(index) # Output: 7

e. split() and join()

● split(): Splits the string into a list of substrings based on a delimiter.

ng
● join(): Joins a list of strings into a single string with a specified delimiter.

Python code :

ni
ar
text = "Python is fun"
words = text.split() # Splitting by space
print(words) Le
# Output: ['Python', 'is', 'fun']

joined_text = " ".join(words)


ve
print(joined_text) # Output: Python is fun
si
er

f. startswith() and endswith()


m

Checks if the string starts or ends with a specified substring.


Em

Python code:

text = "Hello, World!"


print(text.startswith("Hello")) # Output: True
print(text.endswith("World!")) # Output: True

113
6. String Formatting

Python provides several ways to format strings, allowing you to inject variables
into a string.

a. Using the format() Method

ng
Python code:

name = "Alice"

ni
age = 25

ar
message = "My name is {} and I am {} years old.".format(name,
age)
print(message)
old.
Le
# Output: My name is Alice and I am 25 years
ve

b. Using f-Strings (Python 3.6+)


si

Python code
er

name = "Bob"
m

age = 30
message = f"My name is {name} and I am {age} years old."
Em

print(message) # Output: My name is Bob and I am 30 years old.

c. Using Percent (%) Formatting

Python code

114
name = "Charlie"
age = 28
message = "My name is %s and I am %d years old." % (name, age)
print(message) # Output: My name is Charlie and I am 28 years
old.

ng
7. Escape Characters

ni
Escape characters are used to insert special characters in strings. They are

ar
preceded by a backslash (\).

Common Escape Characters: Le


● \': Single quote
ve
● \": Double quote
● \\: Backslash
si

● \n: Newline
er

● \t: Tab
m

Example:
Em

Python code:

text = "He said, \"Python is awesome!\""


print(text) # Output: He said, "Python is awesome!"

# Newline and tab


multi_line_text = "First Line\nSecond Line\tIndented"

115
print(multi_line_text)
# Output:
# First Line
# Second Line Indented

ng
8. String Immutability

ni
Strings in Python are immutable, meaning that once a string is created, it cannot
be modified. Any operation that modifies a string will create a new string.

ar
Example:

Python code
Le
text = "Hello"
ve

text = text + " World"


print(text) # Output: Hello World
si
er

# The original "Hello" string remains unchanged; a new string


"Hello World" is created.
m
Em

9. Multi-line Strings

You can create multi-line strings using triple quotes (''' or """). They are often
used for documentation strings (docstrings) or when you need to include line
breaks in the string.

Example:

116
Python code:

multi_line_string = """This is a multi-line string.


It can span multiple lines.
You can include line breaks."""

ng
print(multi_line_string)

ni
Summary

ar
● Creating strings: Using single, double, or triple quotes.
Le
● Accessing characters: Via indexing or slicing.
● String methods: lower(), upper(), strip(), replace(), find(),
split(), join(), startswith(), endswith().
ve

● String formatting: Using format(), f-strings, or % formatting.


● Escape characters: Inserting special characters like newlines and tabs.
si

● Immutability: Strings cannot be changed in place; operations create new


er

strings.
● Multi-line strings: Using triple quotes for strings that span multiple lines.
m

Strings are a fundamental part of Python programming, essential for tasks


Em

ranging from simple text processing to complex data manipulation. If you have
more questions or need further examples, feel free to ask!

6. User Defined Data Structures

117
ng
ni
ar
Le
ve

a. Arrays
si

In Python, arrays are not a built-in data type like lists or dictionaries, but you can
er

use lists to achieve similar functionality or use external libraries like array or
numpy for more advanced operations.
m

For numerical operations, you can use arrays from the array module or libraries
Em

like NumPy.

Python code

import array as arr


numbers = arr.array('i', [1, 2, 3, 4, 5])

118
b. Deques

For efficient appends and pops from both ends of a list, use
collections.deque.

Python code

ng
from collections import deque

ni
d = deque([1, 2, 3])

ar
d.append(4)
d.appendleft(0)
print(d) Le
# Output: deque([0, 1, 2, 3, 4])

Learn Data Structure in Python for more on user defined DS.


ve

7. Summary
si

● Lists: Ordered, mutable, allow duplicates.


er

● Tuples: Ordered, immutable, allow duplicates.


m

● Dictionaries: Unordered, mutable, indexed by keys.


● Sets: Unordered, mutable, no duplicates.
Em

● Strings: Immutable sequences of characters.


● Arrays: Efficient numerical operations.
● Deques: Efficient double-ended queue operations.

Understanding these data structures and how to use them effectively is crucial for
efficient and effective Python programming.

119
9. Object-Oriented Programming (OOP)

ng
ni
ar
Le
ve

Procedural Vs Object Oriented.


si
er
m
Em

120
Object Oriented Programming

ng
ni
ar
Le
ve
si

Object-Oriented Programming (OOP) is a programming paradigm that uses


er

"objects" to design applications and programs. It focuses on creating reusable


and modular code through the use of classes and objects. I'll guide you through
m

the concepts of OOP in Python, starting from the basics and gradually moving
towards more advanced topics.
Em

121
ng
ni
ar
Le
ve
si

1. Basics of Object-Oriented Programming


er

1.1 What is Object-Oriented Programming?


m
Em

Object-Oriented Programming is a way of designing and structuring your code


that models real-world entities as objects. It promotes code reusability,
modularity, and organisation by grouping related data and behaviour (functions)
into objects.

Key Concepts:

122
ng
ni
ar
Le
ve

● Objects: Instances of classes that represent entities in the real world with
attributes and methods.
si

● Classes: Blueprints for creating objects. A class defines the properties


er

(attributes) and behaviours (methods) that its objects will have.

1.2 Classes and Objects


m
Em

123
ng
ni
ar
Le
ve
si
er

Defining a Class:
m

1. What is a Class?
Em

A class is a blueprint or a template for creating objects. It defines a set of


attributes (data) and methods (functions) that the objects created from the class
will have.

1.1. Defining a Class

124
In Python, you define a class using the class keyword followed by the class
name and a colon. By convention, class names are written in PascalCase (each
word starts with a capital letter).

Python code

ng
class Dog:
# Class attributes
species = "Canis familiaris"

ni
ar
# Initializer / Instance attributes
def __init__(self, name, age):
self.name = name
self.age = age
Le
ve

# Instance method
def bark(self):
si

return f"{self.name} says woof!"


er
m

In this example:
Em

● Dog is the class.


● species, name, and age are attributes.
● bark is a method, which is a function that belongs to the class.

2. What is an Object?

An object is an instance of a class. When a class is defined, no memory is


allocated until an object of that class is created.

125
ng
2.1. Creating an Object

ni
You create an object by calling the class as if it were a function.

ar
Le
ve
si
er
m
Em

Python code

# Creating an object (instance of the Dog class)


my_dog = Dog("Buddy", 5)

126
print(my_dog.name) # Output: Buddy
print(my_dog.age) # Output: 5
print(my_dog.bark()) # Output: Buddy says woof!

In this example:

ng
● my_dog is an object of the Dog class.
● The name and age attributes are specific to my_dog.

ni
● The bark method can be called on my_dog to perform an action.

ar
3. The __init__ Method

Le
The __init__ method is a special method called a constructor. It is
automatically called when an object is created and is used to initialise the
ve
attributes of the object.

3.1. Example with the __init__ Method


si

Python code
er

class Dog:
m

def __init__(self, name, age):


Em

self.name = name # Instance attribute


self.age = age # Instance attribute

def description(self):
return f"{self.name} is {self.age} years old."

127
When you create a Dog object, the __init__ method is automatically called,
and the name and age attributes are initialised.

Python code

# Creating an object

ng
my_dog = Dog("Bucchu", 5)
print(my_dog.description()) # Output: Bucchu is 5 years old.

ni
ar
4. Instance vs. Class Attributes

Le
● Instance Attributes: Attributes that are specific to each object. Defined in
the __init__ method using self.
● Class Attributes: Attributes that are shared by all objects of the class.
ve
Defined directly within the class.

Python code
si
er

class Dog:
species = "Canis familiaris" # Class attribute
m
Em

def __init__(self, name, age):


self.name = name # Instance attribute
self.age = age # Instance attribute

5. Methods

128
Methods are functions defined inside a class that describe the behaviours of an
object. They can manipulate the object’s attributes.

5.1. Instance Methods

Instance methods operate on the object itself and can access or modify the
object’s attributes.

ng
Python code

class Dog:

ni
def __init__(self, name, age):

ar
self.name = name
self.age = age

def description(self):
Le
return f"{self.name} is {self.age} years old."
ve

def speak(self, sound):


si

return f"{self.name} says {sound}."


er

Python code
m

# Creating an object and calling methods


Em

my_dog = Dog("Buddy", 5)
print(my_dog.description()) # Output: Buddy is 5 years old.
print(my_dog.speak("woof")) # Output: Buddy says woof.

6. The self Parameter

129
● The self parameter refers to the instance of the class and allows access
to the attributes and methods of the class.
● It must be the first parameter of any instance method.

7. Example: Building a Simple Class

Let’s build a simple class to encapsulate the idea of a bank account.

ng
Python code

ni
class BankAccount:
def __init__(self, owner, balance=0):

ar
self.owner = owner
self.balance = balance

def deposit(self, amount):


Le
ve
self.balance += amount
return f"Added {amount}. New balance: {self.balance}"
si

def withdraw(self, amount):


er

if amount > self.balance:


return "Insufficient funds!"
m

self.balance -= amount
Em

return f"Withdrawn {amount}. New balance:


{self.balance}"

def get_balance(self):
return f"Current balance: {self.balance}"

130
Then, Create an instance of BankAccount.

# Creating an object and performing operations


account = BankAccount("John Doe", 1000)
print(account.deposit(500)) # Output: Added 500. New
balance: 1500
print(account.withdraw(200)) # Output: Withdrawn 200. New

ng
balance: 1300
print(account.get_balance()) # Output: Current balance:

ni
1300

ar
8. Summary
Le
● Class: A blueprint for creating objects.
● Object: An instance of a class.
ve
● Attributes: Variables that belong to an object.
● Methods: Functions that belong to an object.
si

● __init__ Method: Initializes an object's attributes.


er

● self: Refers to the instance of the object itself.


m

Understanding classes and objects is crucial for mastering Python's OOP


concepts. Experiment with creating your classes and objects to deepen your
Em

understanding!

131
ng
ni
ar
Le
ve

Class Car and different objects.


si
er
m
Em

132
Class Animal and different Animal Objects.

ng
ni
ar
Le
ve
si
er
m
Em

133
2. Key OOP Principles

ng
ni
ar
Le
ve
si

2.1 Encapsulation
er
m
Em

134
Encapsulation is the bundling of data (attributes) and methods that operate on
the data into a single unit, or class. It restricts direct access to some of an
object's components, which is a means of preventing unintended interference.

Key Concepts of Encapsulation

ng
ni
ar
Le
ve
si
er

1. Public, Protected, and Private Members:


○ Public Members: These are accessible from outside the class. By
m

default, all attributes and methods in Python are public unless


Em

explicitly defined otherwise.


○ Protected Members: These are intended to be accessed only within
the class and its subclasses. In Python, they are indicated by a
single underscore prefix (_).
○ Private Members: These are intended to be accessed only within
the class. They are indicated by a double underscore prefix (__),

135
which results in name mangling, making it harder to access them
from outside the class.
2. Getters and Setters:
○ Getters and setters are methods used to access and modify private
attributes. They provide a controlled way to access or modify the
attributes, adding a layer of protection and validation.

ng
Example of Encapsulation

ni
Let's walk through an example that demonstrates encapsulation in Python.

ar
1. Public Attributes and Methods
Code example:

class Employee:
def __init__(self, name, age):
Le
self.name = name # Public attribute
ve

self.age = age # Public attribute


si

def display_info(self):
er

return f"Name: {self.name}, Age: {self.age}" # Public


method
m

# Creating an object of the Employee class


Em

emp = Employee("John", 30)

# Accessing public attributes


print(emp.name) # Output: John
print(emp.age) # Output: 30

136
# Calling public method
print(emp.display_info()) # Output: Name: John, Age: 30

In the above example, both name and age are public attributes, and
display_info is a public method. They can be accessed directly from outside

ng
the class.

2. Protected Attributes

ni
Code Example:

ar
class Employee:
def __init__(self, name, age):
self._name = name
self._age = age
Le
# Protected attribute
# Protected attribute
ve

def _display_info(self): # Protected method


return f"Name: {self._name}, Age: {self._age}"
si
er

class Manager(Employee):
def display_manager_info(self):
m

return f"Manager: {self._name}, Age: {self._age}"


Em

# Creating an object of the Manager class


mgr = Manager("Alice", 40)

# Accessing protected attributes and methods within the subclass


print(mgr.display_manager_info()) # Output: Manager: Alice,
Age: 40

137
# Note: While it's possible to access protected members from
outside the class,
# it is generally not recommended as it breaks the encapsulation
principle.
print(mgr._name) # Output: Alice

ng
Protected members are intended to be accessed only within the class and its

ni
subclasses, though Python does not enforce this strictly. The convention is to

ar
treat them as internal use only.

3. Private Attributes
Code Example:
Le
class Employee:
ve
def __init__(self, name, age):
self.__name = name # Private attribute
si

self.__age = age # Private attribute


er

def display_info(self):
m

return f"Name: {self.__name}, Age: {self.__age}"


Em

# Creating an object of the Employee class


emp = Employee("John", 30)

# Accessing private attributes directly will result in an error


# print(emp.__name) # This will raise an AttributeError

138
# Instead, use the public method provided
print(emp.display_info()) # Output: Name: John, Age: 30

# Name mangling can still allow access, but it's not recommended
print(emp._Employee__name) # Output: John

ng
Private attributes and methods are meant to be inaccessible from outside the
class. However, Python allows access through a process known as name

ni
mangling (_ClassName__attributeName), though this is generally

ar
discouraged.

4. Getters and Setters Le


Getters and setters provide controlled access to private attributes, ensuring data
integrity and encapsulation.
ve

Code Example :
si

class Employee:
er

def __init__(self, name, age):


self.__name = name # Private attribute
m

self.__age = age # Private attribute


Em

# Getter for name


def get_name(self):
return self.__name

# Setter for name


def set_name(self, new_name):

139
if isinstance(new_name, str) and len(new_name) > 0:
self.__name = new_name
else:
raise ValueError("Name must be a non-empty string")

# Getter for age

ng
def get_age(self):
return self.__age

ni
# Setter for age

ar
def set_age(self, new_age):

Le
if isinstance(new_age, int) and new_age > 0:
self.__age = new_age
else:
ve
raise ValueError("Age must be a positive integer")
si

# Creating an object of the Employee class


emp = Employee("John", 30)
er

# Accessing and modifying attributes via getters and setters


m

print(emp.get_name()) # Output: John


Em

emp.set_name("Alice")
print(emp.get_name()) # Output: Alice

print(emp.get_age()) # Output: 30
emp.set_age(35)
print(emp.get_age()) # Output: 35

140
Getters and setters are useful when you want to add validation or processing
logic around the access and modification of private attributes.

Conclusion

Encapsulation in Python is an essential concept in OOP that promotes the


bundling of data and methods, restricting direct access to some of the object's

ng
components. This ensures that objects maintain control over their data, providing
a clean and modular structure that enhances code maintainability and reusability.

ni
ar
2.2 Inheritance

Le
Inheritance is one of the key concepts of Object-Oriented Programming (OOP). It
allows a class (called the child class or subclass) to inherit attributes and
methods from another class (called the parent class or superclass). This
ve

promotes code reusability and the creation of a hierarchical relationship between


classes.
si
er
m
Em

141
ng
ni
ar
Le
ve
si
er

Defining a Subclass:
m
Em

142
ng
ni
ar
Key Concepts of Inheritance

1. Superclass and Subclass:


Le
○ Superclass (Parent Class): The class from which attributes and
ve

methods are inherited.


○ Subclass (Child Class): The class that inherits from the superclass.
si

2. Single Inheritance:
er

○ In single inheritance, a subclass inherits from a single superclass.


3. Multiple Inheritance:
m

○ In multiple inheritance, a subclass can inherit from more than one


superclass.
Em

4. Method Overriding:
○ A subclass can provide a specific implementation of a method that is
already defined in its superclass.
5. super() Function:
○ The super() function allows you to call methods from the
superclass in the subclass.

143
ng
ni
ar
Le
ve
si

Example of Inheritance
er

Let's walk through some examples that demonstrate inheritance in Python.


m

1. Single Inheritance
Em

In single inheritance, a child class inherits from a single parent class.

Code Example :

# Parent Class
class Animal:
def __init__(self, name):

144
self.name = name

def speak(self):
return f"{self.name} makes a sound."

# Child Class

ng
class Dog(Animal):
def speak(self):

ni
return f"{self.name} barks."

ar
# Creating an object of the Dog class
dog = Dog("Buddy")
Le
# Accessing methods
ve
print(dog.speak()) # Output: Buddy barks.
si

In the above example, the Dog class inherits from the Animal class. The speak
er

method is overridden in the Dog class to provide a specific implementation.


m

2. Multiple Inheritance
Em

In multiple inheritance, a child class can inherit from more than one parent class.

Code Example :

# Parent Class 1
class Animal:
def __init__(self, name):
self.name = name

145
def speak(self):
return f"{self.name} makes a sound."

# Parent Class 2
class Canine:

ng
def run(self):
return f"{self.name} runs fast."

ni
# Child Class

ar
class Dog(Animal, Canine):
def speak(self):
return f"{self.name} barks."
Le
ve
# Creating an object of the Dog class
dog = Dog("Buddy")
si

# Accessing methods from both parent classes


er

print(dog.speak()) # Output: Buddy barks.


print(dog.run()) # Output: Buddy runs fast.
m
Em

In this example, the Dog class inherits from both Animal and Canine classes.
The Dog class has access to the methods from both parent classes.

3. Method Overriding

A subclass can override a method inherited from the parent class to provide a
specific implementation.

146
Code Example :

# Parent Class
class Animal:
def __init__(self, name):
self.name = name

ng
def speak(self):
return f"{self.name} makes a sound."

ni
# Child Class

ar
class Cat(Animal):
def speak(self):
return f"{self.name} meows."
Le
ve
# Creating an object of the Cat class
cat = Cat("Whiskers")
si

# Calling the overridden method


er

print(cat.speak()) # Output: Whiskers meows.


m

In the above example, the Cat class overrides the speak method of the Animal
Em

class to provide a specific implementation.

4. Using super()

The super() function is used to call a method from the superclass. This is
useful when you want to extend the functionality of the superclass's method in
the subclass.

147
Code Example :

# Parent Class
class Animal:
def __init__(self, name):
self.name = name

ng
def speak(self):
return f"{self.name} makes a sound."

ni
# Child Class

ar
class Dog(Animal):
def speak(self):
Le
return f"{super().speak()} And {self.name} barks."
ve
# Creating an object of the Dog class
dog = Dog("Buddy")
si

# Calling the method that uses super()


er

print(dog.speak()) # Output: Buddy makes a sound. And Buddy


barks.
m
Em

In this example, the Dog class extends the functionality of the speak method
from the Animal class using super().

5. Hierarchical Inheritance

Hierarchical inheritance involves multiple subclasses inheriting from the same


parent class.

148
Code Example :

# Parent Class
class Animal:
def __init__(self, name):
self.name = name

ng
def speak(self):
return f"{self.name} makes a sound."

ni
# Child Class 1

ar
class Dog(Animal):
def speak(self):
Le
return f"{self.name} barks."
ve
# Child Class 2
class Cat(Animal):
si

def speak(self):
return f"{self.name} meows."
er

# Creating objects of Dog and Cat classes


m

dog = Dog("Buddy")
Em

cat = Cat("Whiskers")

# Accessing methods
print(dog.speak()) # Output: Buddy barks.
print(cat.speak()) # Output: Whiskers meows.

149
In this example, both Dog and Cat classes inherit from the Animal class, but
each provides its own implementation of the speak method.

Conclusion

Inheritance in Python allows for the creation of a hierarchical relationship


between classes, enabling code reuse and promoting a more organised

ng
structure. By inheriting from a parent class, a child class can access and modify
attributes and methods, as well as introduce new functionality.

ni
ar
2.3 Polymorphism
Le
Polymorphism is one of the core concepts of Object-Oriented Programming
(OOP). The term "polymorphism" means "many forms," and it refers to the ability
ve
of different classes to be treated as instances of the same class through a
common interface. In Python, polymorphism allows methods in different classes
to have the same name but behave differently based on the object that is
si

invoking the method.


er
m
Em

150
ng
ni
ar
Le
ve

Key Concepts of Polymorphism


si
er

1. Method Overriding:
○ Method overriding is a form of polymorphism where a subclass
m

provides a specific implementation of a method that is already


defined in its superclass. This allows the subclass to change or
Em

extend the behavior of the method.


2. Method Overloading (Not Supported Natively in Python):
○ Python does not support method overloading in the traditional sense,
but you can achieve similar functionality using default arguments or
variable-length arguments.
3. Polymorphism with Functions and Methods:

151
○ Python allows functions and methods to use polymorphism by
accepting objects of different classes that share a common method
name. The specific implementation of the method depends on the
object's class.
4. Polymorphism with Classes:
○ Python's dynamic typing allows for polymorphism where the type of

ng
object is determined at runtime, allowing different classes to be used
interchangeably as long as they implement the required methods.

ni
Example of Polymorphism

ar
Let's go through some examples to understand how polymorphism works in
Python.

1. Polymorphism with Method Overriding


Le
Method overriding allows a subclass to provide a specific implementation of a
ve

method that exists in its superclass.


si

Python code
er

# Superclass
class Animal:
m

def speak(self):
return "Animal makes a sound"
Em

# Subclass 1
class Dog(Animal):
def speak(self):
return "Dog barks"

152
# Subclass 2
class Cat(Animal):
def speak(self):
return "Cat meows"

# Function that uses polymorphism

ng
def animal_sound(animal):
print(animal.speak())

ni
# Creating instances of Dog and Cat

ar
dog = Dog()
cat = Cat()
Le
# Passing different objects to the same function
ve
animal_sound(dog) # Output: Dog barks
animal_sound(cat) # Output: Cat meows
si
er

In this example, the speak method is overridden in the Dog and Cat subclasses.
The animal_sound function demonstrates polymorphism by calling the speak
m

method on objects of different classes.


Em

2. Polymorphism with Functions

Polymorphism can be demonstrated with functions that can take objects of


different classes and call a common method on them.

# Superclass
class Shape:

153
def area(self):
pass

# Subclass 1
class Rectangle(Shape):
def __init__(self, width, height):

ng
self.width = width
self.height = height

ni
def area(self):

ar
return self.width * self.height

# Subclass 2
Le
class Circle(Shape):
ve
def __init__(self, radius):
self.radius = radius
si

def area(self):
er

return 3.14 * (self.radius ** 2)


m

# Function that uses polymorphism


Em

def print_area(shape):
print(f"Area: {shape.area()}")

# Creating instances of Rectangle and Circle


rectangle = Rectangle(5, 10)
circle = Circle(7)

154
# Passing different objects to the same function
print_area(rectangle) # Output: Area: 50
print_area(circle) # Output: Area: 153.86

ng
Here, the Shape class has an area method that is implemented differently in the
Rectangle and Circle subclasses. The print_area function demonstrates

ni
polymorphism by working with objects of different shapes.

ar
3. Polymorphism with Classes

Python’s dynamic typing allows objects of different classes to be treated as the


Le
same type if they implement the required methods.

class Bird:
ve

def fly(self):
return "Bird flies"
si
er

class Airplane:
def fly(self):
m

return "Airplane flies"


Em

class Superman:
def fly(self):
return "Superman flies"

# Function that uses polymorphism


def make_it_fly(flying_object):

155
print(flying_object.fly())

# Creating instances of Bird, Airplane, and Superman


bird = Bird()
airplane = Airplane()
superman = Superman()

ng
# Passing different objects to the same function

ni
make_it_fly(bird) # Output: Bird flies
make_it_fly(airplane) # Output: Airplane flies

ar
make_it_fly(superman) # Output: Superman flies

Le
In this example, the fly method is implemented in three different classes (Bird,
ve
Airplane, and Superman). The make_it_fly function demonstrates
polymorphism by calling the fly method on different types of objects.
si

Conclusion
er

Polymorphism in Python is a powerful concept that allows different classes to be


m

treated as instances of the same class through a common interface. It promotes


flexibility and code reusability by allowing objects of different classes to be used
Em

interchangeably, as long as they implement the required methods.

2.4 Abstraction

Abstraction is one of the core concepts of Object-Oriented Programming (OOP),


alongside encapsulation, inheritance, and polymorphism. Abstraction is the

156
process of hiding the implementation details and showing only the essential
features of an object. In simpler terms, abstraction focuses on what an object
does rather than how it does it.

In Python, abstraction can be achieved using abstract classes and abstract


methods, which are typically implemented through the abc (Abstract Base
Classes) module.

ng
ni
1. What is Abstraction?

ar
Abstraction is the concept of simplifying complex systems by modeling classes
appropriate to the problem and working at the level of interaction rather than
implementation.
Le
In Python:
ve

● Abstract class: A class that cannot be instantiated and is meant to be


si

subclassed. It can have abstract methods and concrete (fully implemented)


methods.
er

● Abstract method: A method that is declared but contains no


implementation. It must be overridden in the child class.
m
Em

2. Why Use Abstraction?

● Hide Implementation: Abstraction hides unnecessary details from the


user and exposes only the required functionalities.

157
● Provide Flexibility: Abstract classes allow you to define methods that
must be created within any child classes. This ensures a certain structure
for the program.
● Easier Maintenance: By focusing on the essential features, abstraction
allows for easier updates and changes to code without affecting other parts
of the system.

ng
ni
3. Abstract Classes and Methods in Python

ar
In Python, you can create abstract classes and methods using the abc module.
The abstract class is created by inheriting from the ABC class, and the abstract
Le
method is declared using the @abstractmethod decorator.

3.1 Creating Abstract Classes


ve

To define an abstract class, you inherit from ABC (Abstract Base Class) and use
the @abstractmethod decorator for methods that must be overridden by
si

subclasses.
er

Example:
m

from abc import ABC, abstractmethod


Em

# Abstract class
class Vehicle(ABC):
@abstractmethod
def start_engine(self):
pass

158
@abstractmethod
def stop_engine(self):
pass

def fuel_capacity(self): # Concrete method

ng
print("Fuel capacity is 50 liters.")

ni
3.2 Concrete Classes (Subclasses)

ar
Concrete classes inherit from abstract classes. They must override all abstract

Le
methods; otherwise, they cannot be instantiated.

Example:
ve
python
Copy code
si

class Car(Vehicle):
def start_engine(self):
er

print("Car engine started.")


m

def stop_engine(self):
Em

print("Car engine stopped.")

# Instantiate the subclass


my_car = Car()
my_car.start_engine() # Output: Car engine started.

159
my_car.fuel_capacity() # Output: Fuel capacity is 50
liters.
my_car.stop_engine() # Output: Car engine stopped.

In this example, the Vehicle class is an abstract class with abstract methods

ng
start_engine() and stop_engine(). The Car class inherits from Vehicle
and provides concrete implementations for both abstract methods.

ni
ar
4. Features of Abstract Classes and Methods

Le
● An abstract class cannot be instantiated. You must create a subclass to
use it.
● A subclass must implement all abstract methods from the parent abstract
ve

class.
● You can include concrete methods in an abstract class that provide some
si

functionality.
er
m

5. Example: Abstraction in a Real-World Scenario


Em

Let’s look at a more practical example of abstraction where different types of


accounts (like SavingsAccount and CurrentAccount) inherit from a general
Account class.

Abstract Class: Account

from abc import ABC, abstractmethod

160
class Account(ABC):
@abstractmethod
def account_type(self):
pass

ng
@abstractmethod
def minimum_balance(self):

ni
pass

ar
# Concrete Subclass: SavingsAccount
class SavingsAccount(Account):
def account_type(self):
Le
return "Savings Account"
ve

def minimum_balance(self):
si

return 500
er

# Concrete Subclass: CurrentAccount


class CurrentAccount(Account):
m

def account_type(self):
Em

return "Current Account"

def minimum_balance(self):
return 1000

# Instantiate the subclasses

161
savings = SavingsAccount()
current = CurrentAccount()

print(savings.account_type()) # Output: Savings Account


print(savings.minimum_balance()) # Output: 500

ng
print(current.account_type()) # Output: Current Account
print(current.minimum_balance()) # Output: 1000

ni
ar
Explanation:

Le
● The Account class is an abstract class with abstract methods
account_type() and minimum_balance().
● SavingsAccount and CurrentAccount are concrete subclasses that
ve

provide their own implementations for these methods.


● This allows the abstraction of common properties and functionalities of
si

various account types, while the specific details are left for the subclasses
er

to define.
m

6. Why Use Abstract Classes in Python?


Em

Abstract classes are useful when:

● You want to ensure that a set of subclasses implements certain methods.


● You need a base class that provides some default behavior (via concrete
methods) while forcing subclasses to implement their own specific
behavior (via abstract methods).

162
● You want to prevent the direct instantiation of the base class (because it
makes no sense to instantiate a generic base class without specific
implementations).

7. Practical Use Case: GUI Framework

ng
Let's say you are designing a GUI framework, and you want to ensure that every
widget (e.g., Button, TextBox, Label) must have a draw() method to render

ni
the widget on the screen. Here’s how you can achieve it using abstraction:

ar
from abc import ABC, abstractmethod

# Abstract class
Le
class Widget(ABC):
ve

@abstractmethod
def draw(self):
si

pass
er

# Concrete subclass
m

class Button(Widget):
Em

def draw(self):
print("Drawing a button on the screen")

class TextBox(Widget):
def draw(self):
print("Drawing a text box on the screen")

163
# Instantiate concrete classes
button = Button()
textbox = TextBox()

button.draw() # Output: Drawing a button on the screen

ng
textbox.draw() # Output: Drawing a text box on the screen

ni
Here, Widget is an abstract class with an abstract method draw(). Every

ar
concrete widget class must implement the draw() method, ensuring all widgets
can be rendered on the screen. Le
ve

8. Important Points About Abstraction in Python


si

1. Abstract classes cannot be instantiated. They are meant to be


inherited.
er

2. Abstract methods must be overridden in the child classes, failing which


the subclass cannot be instantiated.
m

3. You can define concrete methods in abstract classes to provide default


Em

behavior.
4. The @abstractmethod decorator is used to mark methods that need to
be overridden.

Summary:

164
● Abstraction in Python helps hide unnecessary details and exposes only
the essential features of an object.
● Abstract classes and methods allow developers to define a common
interface for all subclasses, ensuring that specific methods are
implemented in each subclass.
● Python's abc module allows us to create abstract classes using the ABC

ng
class and the @abstractmethod decorator.

ni
ar
3. Advanced OOP Concepts

3.1 Method Overriding Le


Method overriding allows a subclass to provide a specific implementation of a
ve
method that is already defined in its superclass.

Example:
si
er

class Bird(Animal):
def make_sound(self):
m

return "Chirp!"
Em

class Parrot(Bird):
def make_sound(self):
return "Squawk!"

my_parrot = Parrot("Polly", "Parrot")


print(my_parrot.make_sound()) # Output: Squawk!

165
3.2 Method Overloading (Not Directly Supported in Python)

Python does not support method overloading in the same way as languages like
Java or C++. However, you can achieve similar behavior by using default
arguments or *args and **kwargs.

ng
Example with Default Arguments:

ni
class MathOperations:
def add(self, a, b, c=0):

ar
return a + b + c

math = MathOperations()
Le
print(math.add(2, 3)) # Output: 5
ve
print(math.add(2, 3, 4)) # Output: 9
si

3.3 The super() Function


er

The super() function is used to call a method from the parent class in a child
m

class.
Em

Example:

class Parent:
def __init__(self, name):
self.name = name

def display(self):

166
print(f"Parent: {self.name}")

class Child(Parent):
def __init__(self, name, age):
super().__init__(name)
self.age = age

ng
def display(self):

ni
super().display()
print(f"Child: {self.name}, Age: {self.age}")

ar
child = Child("Alice", 10)
child.display()
Le
# Output:
ve
# Parent: Alice
# Child: Alice, Age: 10
si
er

3.4 Multiple Inheritance


m

Python supports multiple inheritance, allowing a class to inherit from more than
one parent class.
Em

Example:

class Flyer:
def fly(self):
print("Flying high!")

167
class Swimmer:
def swim(self):
print("Swimming fast!")

class FlyingFish(Flyer, Swimmer):


pass

ng
flying_fish = FlyingFish()

ni
flying_fish.fly() # Output: Flying high!
flying_fish.swim() # Output: Swimming fast!

ar
3.5 MRO (Method Resolution Order) Le
In cases of multiple inheritance, Python uses the Method Resolution Order
ve
(MRO) to determine the order in which base classes are searched when calling a
method. The super() function respects the MRO.
si

Checking MRO:
er

print(FlyingFish.__mro__)
m

# Output: (<class '__main__.FlyingFish'>, <class


'__main__.Flyer'>, <class '__main__.Swimmer'>, <class 'object'>)
Em

4. Best Practices in OOP

● Use Encapsulation: Protect the internal state of objects by using private


attributes.

168
● Favor Composition Over Inheritance: Use composition to achieve code
reuse without the complexity of inheritance hierarchies.
● Use Polymorphism: Design interfaces that can be implemented by
different classes, allowing flexibility and scalability.
● Keep It Simple

ng
10. File Handling

ni
ar
Le
ve
si
er
m

File handling is a crucial part of any programming language, and Python provides
Em

a simple and efficient way to work with files. In Python, file handling involves
various operations like creating, reading, writing, and deleting files. Python’s
built-in functions and methods make this process straightforward.

1. Why is File Handling Important?

File handling allows you to:

169
● Save data to files for future use (persistence).
● Read data from external files (e.g., CSV, text files, logs).
● Modify files as per requirement.
● Process large datasets or perform tasks like logging.

2. File Operations in Python

ng
The basic file operations include:

1. Opening a file

ni
2. Reading from a file

ar
3. Writing to a file
4. Closing a file

Le
ve
si
er
m
Em

170
3. Opening a File

To open a file in Python, use the open() function, which returns a file object.

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

ng
The open() function requires two arguments:

● filename: Name of the file you want to open.

ni
● mode: The mode in which the file is to be opened.

ar
3.1 File Modes:

Le
● 'r': Read mode – default mode. It opens the file for reading.
● 'w': Write mode. It opens the file for writing and overwrites the existing
file. If the file doesn't exist, it creates a new one.
ve

● 'a': Append mode. It opens the file for writing but appends the data at the
end of the file.
si

● 'x': Create mode. It creates a new file and fails if the file already exists.
er

● 't': Text mode – default mode. It opens the file in text format.
● 'b': Binary mode. It opens the file in binary format (useful for images,
m

videos, etc.).
Em

● '+': Open a file for both reading and writing.

Example of Opening a File:

# Opening a file in read mode


file = open("sample.txt", "r")

171
4. Reading from a File

You can read data from a file using various methods:

ng
ni
ar
Le
1. read(): Reads the entire content of the file as a string.
2. readline(): Reads one line at a time.
ve
3. readlines(): Reads all lines into a list.

4.1 Example: Reading the Entire File


si

file = open("sample.txt", "r")


er

content = file.read()
print(content)
file.close() # Always close the file after use
m
Em

4.2 Example: Reading Line by Line

file = open("sample.txt", "r")


line = file.readline()
while line:
print(line.strip()) # .strip() removes the newline
character
line = file.readline()

172
file.close()

4.3 Example: Reading All Lines into a List

file = open("sample.txt", "r")


lines = file.readlines()
for line in lines:

ng
print(line.strip())
file.close()

ni
ar
5. Writing to a File
Le
To write to a file, you use the write() method. When opening a file in 'w'
mode, any existing content will be erased, while 'a' mode will append to the file.
ve
si

5.1 Example: Writing to a File


er

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


file.write("Hello, World!\n")
m

file.write("This is a new file.")


file.close()
Em

5.2 Example: Appending to a File

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


file.write("\nAdding this line to the existing file.")
file.close()

173
6. Closing a File

After performing any file operation, it’s a good practice to close the file using the
close() method. This ensures that resources are released and changes are

ng
saved.

ni
file = open("output.txt", "w")
file.write("Hello, World!")

ar
file.close()

Le
Tip: If you don’t close a file explicitly, data might not be saved or the
file might remain locked by the operating system.
ve
si

7. Using with Statement (Context Manager)


er

To avoid explicitly closing a file every time, you can use Python’s with
statement. It ensures that the file is properly closed after its block of code is
m

executed, even if exceptions occur.


Em

7.1 Example: Using with for File Operations

with open("sample.txt", "r") as file:


content = file.read()
print(content) # File is automatically closed after the
block ends

# No need to call file.close(), it's done automatically

174
8. Working with Binary Files

For files like images or video, you need to work in binary mode ('b'). You can
open a file in binary mode by using 'rb' or 'wb' instead of 'r' or 'w'.

ng
8.1 Example: Reading a Binary File

ni
with open("image.png", "rb") as image_file:
data = image_file.read()

ar
print(data) # Prints binary data

8.2 Example: Writing Binary Data


Le
with open("output_image.png", "wb") as image_file:
ve
image_file.write(data)
si
er

9. File Methods
m

Here are some useful methods when working with files:


Em

● file.read(size): Reads at most size bytes.


● file.readline(): Reads a single line from the file.
● file.readlines(): Reads all lines and returns a list.
● file.write(string): Writes the given string to the file.
● file.writelines(list): Writes a list of strings to the file.

175
● file.seek(offset, whence): Moves the file pointer to the specified
position.

10. File Handling in Different Modes

ng
10.1 Example: Read and Write Mode (r+)

with open("sample.txt", "r+") as file:

ni
print(file.read()) # Read the file content
file.write("\nNew Line added.") # Write to the file

ar
10.2 Example: Write and Read Mode (w+)

with open("sample.txt", "w+") as file:


Le
file.write("Writing new data.")
ve
file.seek(0) # Go to the beginning of the file
print(file.read()) # Read the file content
si
er

11. Checking if a File Exists and Deleting Files


m

Python’s os module can be used to check if a file exists and to delete files.
Em

11.1 Check if a File Exists

import os

if os.path.exists("sample.txt"):
print("File exists")
else:
print("File does not exist")

176
11.2 Delete a File

import os

if os.path.exists("sample.txt"):
os.remove("sample.txt")

ng
print("File deleted")
else:
print("File does not exist")

ni
ar
12. Handling Exceptions in File Operations
Le
When performing file operations, errors can occur, such as the file not existing,
permission issues, etc. Python provides exception handling (try-except) to
ve
manage such situations.
si

12.1 Example: Handling File Exceptions


er

try:
file = open("non_existent_file.txt", "r")
except FileNotFoundError:
m

print("File not found!")


except IOError:
Em

print("An I/O error occurred.")


finally:
if file:
file.close()

13. Summary of File Handling

177
1. Opening a file: Using open() function.
2. Reading a file: Using read(), readline(), or readlines().
3. Writing to a file: Using write() or writelines().
4. Closing a file: Using close() method or using with to handle files.
5. File modes: Various modes like 'r', 'w', 'a', 'b', etc., control how files
are opened.

ng
6. Binary files: Files like images are handled in binary mode ('rb', 'wb').
7. Exception handling: Use try-except blocks to handle potential errors

ni
during file operations.

ar
11. Exception Handling in
Le
ve

Python
si

Exception handling in Python is the process of responding to exceptions —


er

unexpected events that occur during program execution. These could be errors
m

such as file not found, division by zero, or type mismatches. Python provides a
robust mechanism to handle such exceptions gracefully, ensuring that the
Em

program doesn’t crash unexpectedly.

178
ng
ni
ar
1. What is an Exception?
Le
ve
An exception is an event that occurs when the interpreter detects an error during
the execution of a program. Exceptions disrupt the normal flow of the program,
and Python stops execution and raises an error message if not handled.
si

Common Types of Exceptions


er

● ZeroDivisionError: Raised when dividing by zero.


m

● FileNotFoundError: Raised when trying to open a non-existent file.


Em

● IndexError: Raised when trying to access an invalid index in a list.


● KeyError: Raised when a key is not found in a dictionary.
● TypeError: Raised when an operation is applied to an object of
inappropriate type.
● ValueError: Raised when a function receives an argument of the correct
type but inappropriate value.

179
ng
ni
ar
Or …to see in more detail…
Le
ve
si
er
m
Em

180
ng
ni
ar
Le
ve
si
er
m
Em

2. Exception Handling Structure

The basic structure to handle exceptions in Python is:

try:
# Code that might raise an exception

181
except SomeException as e:
# Code that runs if exception occurs
finally:
# Code that runs no matter what (optional)

Components:

ng
● try: The block where you write code that might raise exceptions.
● except: The block where you handle the exception. You can specify the

ni
exception type or leave it to catch all exceptions.

ar
● finally: This block is optional. It will always execute, regardless of
whether an exception was raised or not. This is commonly used for
cleanup (like closing files). Le
ve

3. Basic Example
si

Here’s a simple example of handling an exception caused by dividing a number


er

by zero:
m

try:
result = 10 / 0 # This will raise ZeroDivisionError
except ZeroDivisionError as e:
Em

print("Cannot divide by zero!")

Output:

Cannot divide by zero!

182
4. Catching Specific Exceptions

You can catch specific types of exceptions to handle different errors accordingly.
For example, handling a FileNotFoundError when trying to open a
non-existent file:

ng
try:
file = open("nonexistent_file.txt", "r")

ni
except FileNotFoundError as e:
print("File not found! Please check the filename.")

ar
5. Catching Multiple Exceptions
Le
ve
You can handle multiple exceptions in one try-except block by specifying
multiple exception types.
si

try:
er

num = int(input("Enter a number: "))


result = 100 / num
m

except ZeroDivisionError:
print("You cannot divide by zero!")
Em

except ValueError:
print("Invalid input! Please enter a valid number.")

Explanation:

● ZeroDivisionError is caught if the user enters 0.


● ValueError is caught if the user inputs a non-numeric value.

183
6. Catching All Exceptions

You can use a generic except clause to catch all exceptions, but this should be
used cautiously as it may hide bugs.

ng
try:
result = 10 / int(input("Enter a number: "))
except Exception as e:

ni
print(f"An error occurred: {e}")

ar
Output:

Enter a number: 0
Le
An error occurred: division by zero
ve
si

7. Using else Clause


er

The else block runs if no exception occurs in the try block. It’s useful when you
m

want to run code only when no exceptions were raised.


Em

try:
result = 10 / 2
except ZeroDivisionError:
print("Division by zero!")
else:
print("No exceptions! Result is:", result)

184
Output:

No exceptions! Result is: 5.0

8. finally Block

ng
The finally block will always execute, whether an exception was raised or not.

ni
It’s commonly used to release resources, like closing files or network
connections.

ar
try:
file = open("sample.txt", "r")
except FileNotFoundError:
Le
print("File not found.")
ve
finally:
print("Closing file.")
si
er
m
Em

185
9. Raising Exceptions

You can raise exceptions manually in your code using the raise statement. This
is useful for custom error handling.

def check_age(age):
if age < 18:

ng
raise ValueError("You must be 18 or older.")
return "Access granted!"

ni
try:
check_age(16)

ar
except ValueError as e:
print(e)

Output:
Le
ve

You must be 18 or older.


si
er

10. Creating Custom Exceptions


m

You can define your own exceptions by subclassing the built-in Exception
Em

class. This is useful when you need specific error types for your application.

class CustomError(Exception):
pass

def test_value(value):
if value < 0:
raise CustomError("Value cannot be negative!")

186
try:
test_value(-1)
except CustomError as e:
print(e)

ng
11. Best Practices for Exception Handling

ni
● Catch specific exceptions: Catch only the exceptions you expect and can
handle.

ar
● Use finally for cleanup: Ensure that critical code like closing files or

Le
network connections is placed in finally to guarantee execution.
● Avoid catching everything: Catching all exceptions with a generic
except can hide bugs.
ve

● Use custom exceptions when necessary: If you have domain-specific


logic, custom exceptions make your code clearer.
si

● Don't suppress exceptions: Always handle or log exceptions, so you


er

don't lose track of errors in your code.


m

12. Full Example of Exception Handling


Em

Here’s a comprehensive example that demonstrates various aspects of exception


handling, including multiple exceptions, else, and finally:

def divide_numbers(num1, num2):


try:
result = num1 / num2

187
except ZeroDivisionError:
print("Error: You cannot divide by zero!")
except TypeError:
print("Error: Please provide numbers, not strings.")
else:
print("Result is:", result)
finally:
print("Execution completed.")

ng
# Correct input
divide_numbers(10, 2)

ni
# Division by zero

ar
divide_numbers(10, 0)

# Invalid types
divide_numbers(10, "two")
Le
ve

Output:
si

Result is: 5.0


Execution completed.
er

Error: You cannot divide by zero!


Execution completed.
m

Error: Please provide numbers, not strings.


Execution completed.
Em

13. Summary of Exception Handling

1. try-except blocks allow you to catch and handle exceptions.


2. You can specify the exception type to handle specific errors.

188
3. Use else to execute code if no exceptions are raised.
4. Use finally for cleanup, as it always runs, whether an exception was
raised or not.
5. You can raise custom exceptions with raise.
6. Custom exceptions help you define domain-specific errors.

ng
12. Libraries, Modules, Packages, and

ni
ar
Frameworks in Python.
Le
In Python, the concepts of libraries, modules, packages, and frameworks are
important for organizing and reusing code efficiently. Each serves a different
purpose but is related in terms of how Python projects are structured and
ve

maintained.
si
er
m
Em

189
ng
ni
ar
Le
ve
si
er
m

1. Python Modules
Em

A module is a single Python file containing Python code—functions, classes, or


variables—that can be imported into other Python programs.

Creating and Using a Module

Suppose we create a Python file called my_module.py:

# my_module.py

190
def greet(name):
return f"Hello, {name}!"

PI = 3.14159

ng
You can import this module in any Python file and use its functions and variables:

ni
import my_module

ar
print(my_module.greet("Alice")) # Hello, Alice!
print(my_module.PI) # 3.14159
Le
Types of Module Imports
ve

1. Import the entire module:


si

import my_module
er

print(my_module.PI)
m
Em

2. Import specific functions or variables:

from my_module import greet, PI


print(greet("Bob"))

3. Import a module with an alias:

191
import my_module as mm
print(mm.PI)

ng
2. Python Packages

A package is a collection of related modules, stored in a directory that contains

ni
an __init__.py file, which helps Python identify the folder as a package. This

ar
enables code organization at a higher level than a module.

Creating a Package
Le
Imagine you are organizing a set of related modules for a project. The structure
might look like this:
ve
si
er
m
Em

192
ng
ni
ar
Le
ve
my_package/
__init__.py
math_operations.py
si

string_operations.py
er
m

Each file inside my_package is a module, and the package groups them
together.
Em

math_operations.py:

def add(a, b):


return a + b

193
string_operations.py:

def to_upper(s):
return s.upper()

ng
You can import and use these modules like so:

ni
ar
from my_package import math_operations, string_operations

print(math_operations.add(3, 4)) # 7 Le
print(string_operations.to_upper("hello")) # HELLO
ve
si
er
m
Em

194
ng
ni
ar
Le
ve
si
er

3. Python Libraries
m

Python libraries are collections of modules and packages that provide reusable
Em

code to help with specific tasks. These libraries save time by offering predefined
functions and classes that you can use directly, without needing to write
everything from scratch. Python has a rich ecosystem of both standard and
third-party libraries, making it highly versatile for many different types of projects.

195
1. Standard Python Libraries

Python comes with a large standard library that is part of the Python installation.
These libraries provide various functionalities like file handling, mathematical
operations, system operations, etc.

ng
ni
ar
Le
ve
si
er
m

Key Standard Libraries


Em

1. math: Provides mathematical functions.

Example:

import math
print(math.sqrt(16)) # 4.0
print(math.factorial(5)) # 120

196
2. os: Provides functions to interact with the operating system.

Example:

import os
print(os.getcwd()) # Gets the current working directory
os.mkdir('new_folder') # Creates a new folder

ng

3. datetime: Provides functions to manipulate dates and times.

ni
Example:

ar
import datetime
now = datetime.datetime.now()
print(now) # Current date and time
Le
4. random: Provides functions for generating random numbers.
ve

Example:
si

import random
print(random.randint(1, 10)) # Random integer between 1 and 10
er
m

5. sys: Provides access to system-specific parameters and functions.


Em

Example:

import sys
print(sys.version) # Prints Python version

6. re: Provides support for regular expressions (pattern matching).

197
Example:

import re
pattern = r"\bworld\b"
result = re.search(pattern, "Hello, world!")
print(result) # <re.Match object>

ng
7. json: Provides functions to parse and work with JSON data.

ni
Example:

import json

ar
data = '{"name": "Alice", "age": 30}'
parsed = json.loads(data)
print(parsed["name"]) # Alice Le

ve
si

2. Third-Party Python Libraries


er

Python's community has developed many third-party libraries that are not
included in the standard library but can be installed using pip. These libraries
m

are specialized for fields like data science, web development, machine learning,
Em

etc.

Popular Third-Party Libraries

1. NumPy (Numerical Python):


○ A library used for scientific computing and numerical operations,
providing support for large multi-dimensional arrays and matrices.

198
Example:

import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr) # [1 2 3 4]
print(np.mean(arr)) # 2.5

ng
2. Pandas:
○ A data analysis library that provides data structures like DataFrame,
which is similar to a table in SQL or Excel.

ni
Example:

ar
import pandas as pd Le
data = {'Name': ['Alice', 'Bob'], 'Age': [25, 30]}
df = pd.DataFrame(data)
print(df)
ve

Output:
si

Name Age
er

0 Alice 25
1 Bob 30
m

3. Requests:
Em

○ A library for making HTTP requests, used to interact with web APIs.

Example:

import requests
response = requests.get('https://api.github.com')
print(response.status_code) # 200
print(response.json()) # JSON response

199
4. Matplotlib:
○ A data visualization library that is used to create static, animated,
and interactive plots.

Example:

ng
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()

ni
ar
5. TensorFlow:
○ A machine learning library developed by Google, used for building
Le
and training machine learning models.

Example (very basic):


ve
import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
si

print(hello)
er

6. Flask:
m

○ A micro web framework for building small and simple web


applications.
Em

Example:

from flask import Flask


app = Flask(__name__)

@app.route('/')
def home():
return "Hello, Flask!"

200
if __name__ == "__main__":
app.run(debug=True)

7. BeautifulSoup:
○ A library for parsing HTML and XML documents, often used for web

ng
scraping.

Example:

ni
from bs4 import BeautifulSoup

ar
import requests

page = requests.get("https://example.com")
Le
soup = BeautifulSoup(page.content, "html.parser")
print(soup.title.text) # Prints the title of the page
ve

3. Installing and Managing Libraries


si

Installing a Library with pip


er

You can install third-party libraries using Python's package manager, pip. To
m

install a library, use the following command in your terminal or command prompt:
Em

bash

pip install library_name

For example, to install NumPy, you would use:

pip install numpy

201
Checking Installed Libraries

To check which libraries are installed on your system, you can use:

pip list

ng
Uninstalling a Library

ni
If you no longer need a library, you can uninstall it using:

ar
pip uninstall library_name
Le
ve
4. Creating Your Own Python Library

You can create your own library by organizing Python modules and packages,
si

and distributing them so others can install and use them.


er
m

1. Create Modules and Packages: Group your modules into a package. For
Em

example:

my_library/
__init__.py
module1.py
module2.py

202
2. Distribute with setuptools: You can use the setuptools library to
package your Python code so that it can be installed via pip.
3. Upload to PyPI: Once your library is packaged, you can upload it to the
Python Package Index (PyPI) so others can install it using pip.

ng
5. Popular Python Libraries by Domain

ni
Here’s a list of libraries based on different application domains:

ar
Data Science and Machine Learning:

● NumPy: Multi-dimensional arrays and mathematical functions.


Le
● Pandas: Data manipulation and analysis.
● SciPy: Advanced scientific computations.
ve
● Matplotlib/Seaborn: Data visualization.
● TensorFlow/PyTorch: Machine learning and neural networks.
si

Web Development:
er

● Django: A full-stack web framework for rapid web development.


● Flask: A micro-framework for smaller web applications.
m

● Requests: HTTP requests for interacting with web APIs.


Em

Web Scraping:

● BeautifulSoup: Parsing HTML and XML.


● Scrapy: A framework for web scraping.

Game Development:

● Pygame: Used for making 2D games.

203
Automation:

● Selenium: Automating browser tasks.


● OpenCV: Computer vision and image processing.

Graphical User Interface (GUI) Development:

● Tkinter: Built-in library for basic GUI applications.

ng
● PyQt: A set of Python bindings for the Qt application framework.

ni
ar
Conclusion
Le
Python libraries play a crucial role in extending Python’s functionality. You can
leverage both the standard library and third-party libraries to make development
ve
faster and more efficient. Whether you are building a web application, a machine
learning model, or a simple script, libraries make your life easier by providing
reusable, tested, and optimized code.
si
er
m
Em

4. Python Frameworks

A framework is a collection of libraries and modules designed to help developers


build applications more easily by providing ready-made components and
solutions for common problems. Frameworks dictate the structure and flow of an
application, while still allowing customization.

204
Types of Frameworks

1. Web Frameworks:
○ Django: A high-level web framework for rapid development of
secure and scalable web applications.
○ Flask: A lightweight web framework for small to medium applications
with more flexibility and fewer built-in features than Django.

ng
Example (Flask):

ni
pip install flask

ar
from flask import Flask

app = Flask(__name__)
Le
@app.route('/')
ve
def hello():
return "Hello, World!"
si

if __name__ == '__main__':
er

app.run(debug=True)
m

2. GUI Frameworks:
Em

○ Tkinter: Built-in Python GUI library for creating desktop applications.


○ PyQt: An external library for creating advanced desktop applications.

Example (Tkinter):

import tkinter as tk

window = tk.Tk()

205
greeting = tk.Label(text="Hello, Tkinter!")
greeting.pack()
window.mainloop()

3. Machine Learning Frameworks:


○ TensorFlow: A popular framework for building machine learning

ng
models.
○ PyTorch: Another leading machine learning framework, especially

ni
popular in research.

ar
4. Game Development Frameworks:
○ Pygame: A library for developing games in Python.

Example (Pygame):
Le
pip install pygame
ve

import pygame
si

pygame.init()
er

screen = pygame.display.set_mode((640, 480))


pygame.display.set_caption('Simple Game')
m

running = True
Em

while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

screen.fill((0, 0, 0))
pygame.display.flip()

pygame.quit()

206
Em
m
er
si
ve
Le
ar
ni
ng

207
5. Difference Between Libraries, Packages, Modules, and
Frameworks

Concept Description Example

ng
Module A single file with Python code that can define math.py, random.py

ni
functions, classes, or variables.

ar
Package A collection of modules organized in directories numpy, pandas
with an __init__.py file.
Le
ve

Library A collection of packages and modules grouped Python Standard Library,


together to provide functionality. requests, Flask
si
er

Framework A complete solution that provides pre-built Django, Flask,


m

functionality and defines the structure of an TensorFlow


application.
Em

6. The __name__ == "__main__" Statement in Modules

Python modules have a special built-in variable called __name__. When a


module is executed directly, __name__ is set to "__main__". This is useful for

208
distinguishing between code that should be run when the module is executed as
a script and code that should run when it's imported as a module.

Example:

# my_module.py
def greet():
print("Hello from my_module!")

ng
if __name__ == "__main__":
greet() # This runs only if executed directly

ni
ar
Conclusion
Le
ve
si
er
m
Em

209
● Modules: Python files that group code for reuse.
● Packages: A way to structure multiple related modules.
● Libraries: Collections of packages/modules providing specific functionality.
● Frameworks: Complete solutions that help in building applications (e.g.,
web frameworks like Django, Flask).

ng
These concepts form the backbone of Python's extensibility and efficiency. They
allow Python developers to write modular, reusable, and maintainable code

ni
ar
12. Advanced Python Concepts Le
In this section, we'll cover various advanced Python topics that allow you to write
ve
more efficient, readable, and sophisticated code. These topics build on basic
Python knowledge, taking your programming skills to the next level.
si

1. Iterators and Generators


er

Iterators
m

● An iterator in Python is an object that allows you to traverse through all the
Em

elements of a collection (like a list or tuple).


● Every iterator must implement the __iter__() and __next__()
methods.

Example:

class MyIterator:

210
def __init__(self, max):
self.max = max
self.num = 0

def __iter__(self):
return self

def __next__(self):

ng
if self.num >= self.max:
raise StopIteration
else:

ni
self.num += 1
return self.num

ar
it = MyIterator(3)
for i in it:
print(i)
Le
ve

Generators
si

● A generator is a special type of iterator that is defined using a function.


Instead of returning all the values at once, it yields one value at a time,
er

suspending its state between each call.


m

Example:
Em

def my_generator():
for i in range(5):
yield i

gen = my_generator()
for i in gen:
print(i)

211
2. Decorators

A decorator is a higher-order function that allows you to modify or extend the


behavior of other functions or methods.

Basic Example:

ng
def my_decorator(func):
def wrapper():
print("Something is happening before the function is

ni
called.")
func()

ar
print("Something is happening after the function is
called.")
return wrapper

@my_decorator
Le
def say_hello():
ve
print("Hello!")

say_hello()
si
er

In this example, my_decorator adds extra functionality before and after the
m

say_hello function is called.


Em

3. Context Managers and the with Statement

A context manager in Python is an object that properly manages resources,


ensuring that setup and cleanup are handled correctly. The with statement is
used to wrap the execution of a block of code within a context manager.

Basic Example:

212
with open('example.txt', 'w') as file:
file.write('Hello, world!')

# 'file.close()' is automatically called after the block ends.

Custom Context Manager:

ng
class MyContext:
def __enter__(self):

ni
print("Enter the context")
return self

ar
def __exit__(self, exc_type, exc_value, traceback):
print("Exit the context")

with MyContext():
Le
print("Inside the context")
ve
si

4. Closures
er

A closure is a function object that remembers values in its enclosing lexical


scope, even if they are not in memory anymore. Closures allow us to retain state
m

between function calls without using global variables.


Em

Example:

def outer_function(msg):
def inner_function():
print(msg)
return inner_function

closure = outer_function("Hello, World!")

213
closure() # Output: Hello, World!

5. Metaclasses

Metaclasses are the "classes of classes." They define the behavior of class
objects. When you create a class, Python automatically uses a metaclass to

ng
define how that class behaves.

Example:

ni
ar
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f"Creating class {name}")
Le
return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=MyMeta):
ve
pass
# Output: Creating class MyClass
si
er

6. Descriptors

A descriptor is an object that defines how attribute access works. They are used
m

to manage attributes in Python classes and are the underlying mechanism for
Em

properties and methods like property(), staticmethod(), and


classmethod().

A descriptor must define one or more of the following methods: __get__(),


__set__(), and __delete__().

Example:

214
class MyDescriptor:
def __get__(self, instance, owner):
return "This is a descriptor value"

class MyClass:
attr = MyDescriptor()

obj = MyClass()

ng
print(obj.attr) # Output: This is a descriptor value

ni
7. Abstract Base Classes (ABC)

ar
Abstract Base Classes (ABCs) are a way to define interfaces in Python. They

Le
provide a blueprint for other classes and ensure that derived classes implement
specific methods.
ve
To define an ABC, you use the abc module and the @abstractmethod
decorator.
si

Example:
er

from abc import ABC, abstractmethod


m

class Shape(ABC):
@abstractmethod
Em

def area(self):
pass

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def area(self):

215
return 3.14 * self.radius * self.radius

circle = Circle(5)
print(circle.area())

In this example, Shape is an abstract class, and the method area must be

ng
implemented in any class that inherits from Shape.

8. Type Hints and Annotations

ni
ar
Python supports type hints, which make it easier for developers to understand
the expected types of function arguments and return values.

Example: Le
def add(a: int, b: int) -> int:
ve
return a + b
si

print(add(2, 3)) # Output: 5


er

Type hints are not enforced during runtime, but they improve code readability and
m

allow static type checkers (like mypy) to validate the types.


Em

9. Coroutines and async/await

Coroutines in Python are functions that can pause their execution and resume
later. This is particularly useful for I/O-bound tasks, where waiting for input/output
operations can block the program's execution. The async and await keywords
are used to declare and run coroutines.

216
Example:

import asyncio

async def my_coroutine():


print("Start")
await asyncio.sleep(1)
print("End")

ng
asyncio.run(my_coroutine())

ni
ar
In this example, asyncio.run() is used to execute the coroutine, which
pauses execution for one second between the print statements.

10. Memory Management and __slots__


Le
ve
Python automatically manages memory using a private heap containing all
Python objects. Advanced memory management techniques involve limiting
object attribute creation to save memory using __slots__.
si
er

Example:
m

class MyClass:
__slots__ = ['name', 'age'] # Limits instance attributes to
Em

these

def __init__(self, name, age):


self.name = name
self.age = age

obj = MyClass('Alice', 30)


print(obj.name) # Output: Alice

217
By using __slots__, Python will not use a dictionary to store instance
attributes, reducing the memory footprint of the object.

Conclusion

ng
By understanding these advanced Python topics, you'll be able to write more
efficient, elegant, and powerful Python code. These concepts can also help you
improve your problem-solving approach and prepare for writing large-scale

ni
applications or more complex projects.

ar
13. Testing and Debugging in
Le
ve

Python.
si

Testing and debugging are crucial stages in software development to ensure that
er

code functions as expected and is free of errors. Python provides several tools
m

and techniques for both testing and debugging, which help developers write
reliable, maintainable, and error-free code.
Em

1. Debugging in Python

Debugging involves identifying and removing errors (bugs) in your code. Python
offers several debugging techniques, including:

218
1.1. Print Statements for Debugging

The simplest way to debug Python code is to use print() statements to check
the values of variables at various stages of program execution. While this is a
quick solution, it can become inefficient in larger projects.

ng
def add(a, b):
print(f"a: {a}, b: {b}") # Debug with print
return a + b

ni
result = add(5, 3)

ar
print(result) # Output: 8

1.2. The pdb Module


Le
ve
The pdb (Python Debugger) module is a built-in debugger that provides an
interactive environment to inspect the state of the program, set breakpoints, step
si

through code, and evaluate expressions.


er

Basic Example:
m

import pdb
Em

def add(a, b):


pdb.set_trace() # Set a breakpoint
return a + b

result = add(5, 3)

Commands inside the pdb debugger:

219
● n: Step to the next line.
● c: Continue execution until the next breakpoint.
● l: List the current code.
● p var: Print the value of a variable var.

1.3. Using assert for Debugging

ng
The assert statement is a simple debugging tool that tests if a condition is
True. If the condition is False, it raises an AssertionError.

ni
ar
x = 10
assert x > 5, "x should be greater than 5" # No error here

y = 3 Le
assert y > 5, "y should be greater than 5" # Raises
AssertionError
ve

1.4. Logging in Python


si

The logging module is used to record (log) messages that indicate what the
er

application is doing. It provides different levels of severity for messages: DEBUG,


m

INFO, WARNING, ERROR, and CRITICAL.


Em

import logging

logging.basicConfig(level=logging.DEBUG)

def add(a, b):


logging.debug(f"Adding {a} and {b}")
return a + b

220
result = add(5, 3)

2. Testing in Python

Testing is the process of verifying that the code behaves as expected. There are

ng
different levels of testing:

● Unit Testing: Testing individual units of code (e.g., functions or methods).

ni
● Integration Testing: Testing how different parts of a system work together.

ar
● System Testing: Testing the entire system to ensure it meets
requirements.

2.1. Unit Testing with unittest


Le
The unittest module is the built-in unit testing framework in Python. It provides
ve

a way to organize and run tests, check output, and handle failures.
si

Example:
er

import unittest
m

def add(a, b):


return a + b
Em

class TestMathFunctions(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
self.assertEqual(add(-1, 1), 0)
self.assertNotEqual(add(2, 2), 5)

if __name__ == '__main__':

221
unittest.main()

● self.assertEqual(a, b): Asserts that a and b are equal.


● self.assertNotEqual(a, b): Asserts that a and b are not equal.
● self.assertTrue(condition): Asserts that condition is True.

ng
● self.assertFalse(condition): Asserts that condition is False.

2.2. Test Discovery

ni
You can organize your tests into multiple files and run them all using test

ar
discovery. The unittest framework supports automatic test discovery. To run
all tests in a folder, you can execute:

python -m unittest discover


Le
ve

2.3. Test Coverage with coverage.py


si

To ensure that tests cover all parts of your code, you can use the coverage.py
er

tool. It tracks which lines of your code are executed during testing.
m

1. Install coverage:
Em

pip install coverage

2. Run your tests with coverage:

coverage run -m unittest discover

222
3. Generate a coverage report:

coverage report

2.4. Mocking in Unit Tests

When writing unit tests, you may need to replace parts of your code with "mocks"
to simulate different behaviors. The unittest.mock module provides tools for

ng
mocking in Python.

Example:

ni
ar
from unittest import mock

def get_data_from_db():
return "data from the database" Le
def process_data():
ve
data = get_data_from_db()
return f"Processed {data}"
si

class TestProcessData(unittest.TestCase):
@mock.patch('__main__.get_data_from_db',
er

return_value="mocked data")
def test_process_data(self, mock_db):
m

result = process_data()
self.assertEqual(result, "Processed mocked data")
Em

if __name__ == '__main__':
unittest.main()

In this example, we mock the get_data_from_db function to return "mocked


data" during testing.

223
2.5. Using pytest for Testing

pytest is another popular testing framework that is simpler and more powerful
than unittest. It supports fixtures, parameterized tests, and more.

Install pytest:
bash

ng
Copy code
pip install pytest

ni
1.

ar
Write a test:
python
Copy code
Le
def add(a, b):
ve

return a + b
si

def test_add():
er

assert add(2, 3) == 5
assert add(-1, 1) == 0
m

2.
Em

Run the test:


bash
Copy code
pytest

3.

224
3. Best Practices for Testing and Debugging

● Test early and often: Write tests while you're writing your code, not after
the code is complete.
● Test all possible cases: Cover edge cases and all possible scenarios.

ng
● Keep tests isolated: Tests should be independent of each other and not
rely on external factors (e.g., databases, APIs). Mock external services

ni
when necessary.
● Use descriptive messages: When using assert or logging, make sure

ar
error messages or log messages are descriptive to make debugging
easier.
Le
● Automate tests: Use Continuous Integration (CI) tools to automatically run
tests when code is pushed to a repository.
ve
si

Conclusion
er

Testing and debugging are essential to producing high-quality Python code.


Debugging tools like pdb and logging help you find and fix errors, while testing
m

frameworks like unittest and pytest ensure your code behaves as expected.
Em

By incorporating these practices into your development process, you can


improve code reliability, reduce bugs, and maintain code quality over time.

225
That is all.

Thank you for joining me on this journey. Your time, curiosity, and dedication
mean the world to me. I hope this book has inspired you, expanded your
knowledge, and ignited your passion.

ng
Keep learning, keep growing, and remember—great things are built one step at a
time.

ni
ar
Happy creating, and until next time—stay curious and keep coding!
Le
For any message, feel free to reach out to me at: 0923191253
ve

Muhammed Teshome.
si

Happy Coding!
er
m
Em

226

You might also like