Module 2 Notes - IPS
Module 2 Notes - IPS
Content: Variables, Data Types, Operators, Control Structures: if, else, loops, Functions and Modular
Programming, Lists, Tuples, Dictionaries, and Sets, Basics of File Handling, Exception Handling.
Variables:
In Python, a variable is a name that represents a value stored in the computer's memory.
It acts as a container to hold data that can be used and manipulated throughout a program.
Variables allow us to store and access information, making our code more dynamic and flexible.
To use a variable in Python, you need to assign a value to it using the assignment operator `=`.
The value can be of any data type, such as numbers, strings, or even more complex objects like lists or
dictionaries.
Unlike some other programming languages, you don't need to explicitly declare the variable type in
Python.
For example, consider the following code snippet:
# Example of variables in Python
message = "Hello, Python!"
number = 42
pi = 3.14
print(message)
print(number)
print(pi)
In this code, we have three variables: `message`, `number`, and `pi`. Each variable is assigned a specific
value. The `print()` function is used to display the values of these variables.
Variables can also be reassigned to new values as the program progresses:
# Reassigning variables
x=5
print(x) # Output: 5
x = 10
print(x) # Output: 10
In this example, the variable `x` is initially assigned the value `5`. However, we can reassign a new value to
`x`, in this case `10`. The new value replaces the previous one, and when we print `x`, it displays the
updated value.
Practice problem:
Write a Python program that calculates the area of a rectangle. The length and width of the rectangle should
be stored in variables, and the result should be displayed.
Here's a possible solution:
# Practice problem: Calculating the area of a rectangle
length = float(input("Enter the length of the rectangle: "))
width = float(input("Enter the width of the rectangle: "))
area = length * width
print("The area of the rectangle is:", area)
In this program, the `input()` function is used to prompt the user to enter the length and width of the
rectangle. The `float()` function is used to convert the input to floating-point numbers. The area is
calculated by multiplying the length and width, and the result is stored in the variable `area`. Finally, the
area is displayed using the `print()` function.
Data types:
In Python, the following are some of the built-in data types:
Numeric Types:
int: Integer values, e.g., 10, -3, 0.
float: Floating-point values, e.g., 3.14, -2.5, 0.0.
complex: Complex numbers, e.g., 1 + 2j, -3j.
Sequence Types:
str: Strings of characters, e.g., "Hello", 'Python'.
list: Ordered, mutable sequences, e.g., [1, 2, 3], ['a', 'b', 'c'].
tuple: Ordered, immutable sequences, e.g., (1, 2, 3), ('a', 'b', 'c').
Mapping Type:
dict: Key-value pairs, also known as dictionaries, e.g., {'name': 'uday', 'age': 31}.
Set Types:
set: Unordered collections of unique elements, e.g., {1, 2, 3}, {'a', 'b', 'c'}.
frozenset: Immutable versions of sets, e.g., frozenset({1, 2, 3}).
Boolean Type:
bool: Represents either True or False.
None Type:
None: Represents the absence of a value.
These are the commonly used built-in data types in Python. Additionally, Python allows you to create your
own custom data types using classes.
Operators:
In Python, operators are symbols or special characters that perform various operations on operands.
Operands can be variables, values, or expressions.
Python provides a wide range of operators to handle different types of operations, such as arithmetic,
comparison, logical, assignment, and more.
Let's look at some commonly used operators in Python:
Arithmetic Operators:
Addition (`+`): Adds two operands.
Subtraction (`-`): Subtracts the second operand from the first.
Multiplication (`*`): Multiplies two operands.
Division (`/`): Divides the first operand by the second.
Modulus (`%`): Returns the remainder of the division.
Exponentiation (`**`): Raises the first operand to the power of the second.
Floor Division (`//`): Performs integer division, discarding the remainder.
Comparison Operators:
Equal to (`==`): Checks if two operands are equal.
Not equal to (`!=`): Checks if two operands are not equal.
Greater than (`>`): Checks if the first operand is greater than the second.
Less than (`<`): Checks if the first operand is less than the second.
Greater than or equal to (`>=`): Checks if the first operand is greater than or equal to the second.
Less than or equal to (`<=`): Checks if the first operand is less than or equal to the second.
Logical Operators:
And (`and`): Returns `True` if both operands are `True`.
Or (`or`): Returns `True` if either operand is `True`.
Not (`not`): Returns the opposite of the operand's value (`True` becomes `False`, and vice versa).
Assignment Operators:
Assignment (`=`): Assigns a value to a variable.
Add and assign (`+=`): Adds the right operand to the left operand and assigns the result to the left operand.
Subtract and assign (`-=`): Subtracts the right operand from the left operand and assigns the result to the
left operand.
Multiply and assign (`*=`): Multiplies the left operand by the right operand and assigns the result to the
left operand.
Divide and assign (`/=`): Divides the left operand by the right operand and assigns the result to the left
operand.
Practice problem:
Write a Python program that converts a temperature from Fahrenheit to Celsius. Prompt the user to enter the
temperature in Fahrenheit, perform the conversion, and display the result in Celsius.
Here's a possible solution:
# Practice problem: Fahrenheit to Celsius conversion
fahrenheit = float(input("Enter the temperature in Fahrenheit: "))
celsius = (fahrenheit - 32) * 5 / 9
print("The temperature in Celsius is:", celsius)
In this program, the `input()` function is used to prompt the user to enter the temperature in Fahrenheit. The
`float()` function is used to convert the input to a floating-point number. The conversion from Fahrenheit to
Celsius is performed using the formula `(F - 32) * 5/9`, and the result is stored in the variable `celsius`.
Finally, the temperature in Celsius is displayed using the `print()` function.
Control structures:
In Python, control structures refer to the constructs that allow you to control the flow and execution of
your program.
They determine the order in which statements are executed and provide mechanisms for making
decisions and repeating actions.
There are three main types of control structures in Python:
1. Conditional Statements (if-elif-else):
The ‘if ‘ statement allows you to execute a block of code only if a certain condition is true.
The `elif ‘ statement (short for "else if") allows you to check additional conditions after the initial
`if` statement.
The `else` statement is used to specify a block of code that should be executed if none of the preceding
conditions are true.
Example:
2. Loops:
The `for` loop is used to iterate over a sequence (such as a list, tuple, or string) or any iterable object.
The `while` loop repeatedly executes a block of code as long as a specified condition is true.
Example of a `for` loop:
# Control structure: for loop
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
In this code, the program checks the value of the variable `age`. Depending on the value, it executes a
specific block of code:
- If `age` is less than 18, it prints "You are underage."
- If `age` is exactly 18, it prints "You just turned 18!"
- If none of the above conditions are true, it prints "You are an adult."
Practice problem:
Write a Python program that determines whether a given number is positive, negative, or zero. Prompt the
user to enter a number, evaluate the condition, and display the appropriate message.
Here's a possible solution:
# Practice problem: Positive, negative, or zero
number = float(input("Enter a number: "))
if number > 0:
In this program, the `input()` function is used to prompt the user to enter a number. The number is then
evaluated using conditional statements:
- If the number is greater than 0, it prints "The number is positive."
- If the number is less than 0, it prints "The number is negative."
- If the number is neither greater nor less than 0, it must be 0, so it prints "The number is zero."
loops:
Loops in Python allow you to repeatedly execute a block of code until a certain condition is met.
They provide a way to automate repetitive tasks and iterate over collections of data.
There are two main types of loops in Python:
1. `for` loop:
The `for` loop is used to iterate over a sequence (such as a list, tuple, or string) or
any iterable object.
It allows you to perform a specific action for each item in the sequence.
The loop variable takes on each value in the sequence one by one, and the indented block
of code below the `for` loop is executed for each iteration.
2. `while` loop:
The `while` loop repeatedly executes a block of code as long as a specified condition is true.
It allows you to perform a certain action repeatedly until the condition becomes false.
The condition is evaluated before each iteration. If it is true, the indented block of code
below the `while` loop is executed. If it becomes false, the program moves on to the
next statement after the `while` loop.
Here's an example to illustrate the usage of loops:
# Example of loops
fruits = ["apple", "banana", "orange"]
# Using a for loop
for fruit in fruits:
print(fruit)
# Using a while loop
count = 0
while count < 5:
print(count)
count += 1
Practice problem:
Write a Python program that calculates the sum of numbers from 1 to a given number (inclusive). Prompt
the user to enter a number, perform the calculation, and display the result.
Here's a possible solution:
# Practice problem: Sum of numbers
number = int(input("Enter a number: "))
sum = 0
for num in range(1, number + 1):
sum += num
print("The sum of numbers from 1 to", number, "is:", sum)
In this program, the `input()` function is used to prompt the user to enter a number. The number is then used
to calculate the sum of numbers from 1 to that number using a `for` loop. The loop iterates over the range of
numbers from 1 to `number + 1` (inclusive) and adds each number to the `sum` variable. Finally, the sum is
displayed using the `print()` function.
Break
In Python, the `break` statement is used to prematurely exit a loop before its normal completion.
When encountered, the `break` statement immediately terminates the innermost loop (such as a
`for` or `while` loop) and transfers control to the next statement following the loop.
Here are some key points about the `break` statement:
1. It is typically used within a loop when a specific condition is met, and there is no need
to continue iterating.
2. When the `break` statement is executed, the program jumps out of the loop
entirely, bypassing any remaining iterations.
3. The `break` statement can be used in both `for` and `while` loops.
Here's an example to demonstrate the usage of the `break` statement:
Functions
Python functions are the primary tool for creating modular, manageable, and reusable code. In Python, a
function is defined using the def keyword.
1. Function Syntax and Structure
A standard Python function consists of the header (keyword, name, parameters) and the body (the indented
code block).
f(x) = y
In programming, this translates to:
Python Code
def function_name(parameters):
# Logic goes here
return result
Components:
def: The keyword that tells Python you are defining a function.
Parameters: Variables listed inside the parentheses that receive data.
Docstring: A triple-quoted string used for documentation.
return: Sends a result back to the caller. If omitted, the function returns None by default.
2. Types of Arguments
Python offers great flexibility in how you pass data into functions.
A. Positional Arguments
The most common type; the order of the data matches the order of the parameters.
Python code
def describe_pet(animal, name):
print(f"I have a {animal} named {name}.")
describe_pet("Hamster", "Pip") # Order matters
B. Keyword Arguments
You explicitly name the parameters during the call, so the order doesn't matter.
Python Code
describe_pet(name="Luna", animal="Cat")
C. Default Parameters
You can provide a fallback value if no argument is provided.
Python Code
def greet(name, message="Welcome"):
print(f"Hello {name}, {message}")
greet("Alice") # Uses default "Welcome"
greet("Bob", "Good Morning") # Overrides default
3. Scope: Global vs. Local
Understanding where your variables "live" is crucial for modular programming.
Local Scope: Variables created inside a function. They are destroyed once the function finishes.
Global Scope: Variables defined in the main body of the script. They are accessible everywhere but
require the global keyword if you intend to modify them inside a function.
Python Code:
def make_pizza(size, *toppings):
print(f"Making a {size} inch pizza with:")
for topping in toppings:
print(f"- {topping}")
make_pizza(12, "Pepperoni", "Mushrooms", "Green Peppers")
5. Practical Example: A Modular Calculator
Here is how modularity looks in practice by separating logic into specific functions.
Python Code
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def calculate(a, b, operation):
"""A higher-level function that calls other functions."""
if operation == "add":
return add(a, b)
elif operation == "subtract":
return subtract(a, b)
# Usage
result = calculate(10, 5, "add")
print(f"The result is: {result}")
Modular Programming
Modular programming is a software design technique that emphasizes separating the functionality of a
program into independent, interchangeable modules, such that each contains everything necessary to execute
only one aspect of the desired functiona1lity.
In Python, a Module is simply a file containing Python definitions and statements (a .py file), while a Package
is a collection of modules organized in a folder hierarchy.
1. Key Principles of Modularity
To build an effective modular system, developers follow these three core concepts:
Modules hide their internal complexity. A programmer using a "Math" module doesn't need to know the
complex algorithm used to calculate a square root; they only need to know how to call the function.
B. High Cohesion
A module should have a singular, well-defined purpose. For example, a database_module.py should only
handle data storage, not user interface logic.
C. Low Coupling
Modules should depend on each other as little as possible. If you change the code inside Module A, it should
ideally not require you to rewrite Module B.
Creating a Module
Any Python file can be imported as a module. Suppose we have a file named [Link]:
Python Code
# [Link]
import math
def area_circle(radius):
return [Link] * (radius ** 2)
def area_square(side):
return side * side
Importing a Module
You can access the code in [Link] from another file (e.g., [Link]) using the import statement.
3. Python Packages
When a project grows, single modules aren't enough. You group related modules into Packages.
Structure: A package is a directory containing a special file named __init__.py (this can be empty) and
multiple module files.
Hierarchy:
Plaintext
Project/
│
├── [Link]
└── graphics/ <-- This is a Package
├── __init__.py
├── [Link] <-- This is a Module
└── [Link] <-- This is a Module
Python Code
def my_function():
print("Function logic running")
if __name__ == "__main__":
# This block ONLY runs if this file is executed directly.
# It will NOT run if this file is imported elsewhere.
print("Executing as a standalone script")
my_function()
5. Advantages of Modular Programming
1. Easier Debugging: Since the code is divided into logical chunks, you can isolate and test one module
at a time.
2. Code Reusability: You can use the same auth_module.py across five different projects without
rewriting the login logic.
3. Team Collaboration: One developer can work on the payment_gateway module while another works
on the user_profile module without merging conflicts.
4. Manageable Scope: It prevents "Spaghetti Code" where a single file becomes thousands of lines long
and impossible to navigate.
6. Standard Library vs. Third-Party Modules
Standard Library: Python comes "batteries included," meaning it has built-in modules like os, sys,
math, and datetime.
Third-Party: Modules created by the community (like pandas, requests, or numpy) which you install
using a package manager like pip.
1. Lists ([ ])
Lists are the most versatile data structure in Python. They are ordered, mutable (changeable), and allow
duplicate members.
Syntax: my_list = ["apple", "banana", "cherry"]
Key Characteristics:
Indexed: The first item is [0], the second is [1], etc.
Mutable: You can add, remove, or change items after the list is created.
Dynamic: They can grow or shrink in size.
Common Operations:
Python Code
fruits = ["apple", "banana"]
[Link]("orange") # Adds to the end
[Link](1, "mango") # Adds at index 1
[Link]() # Removes the last item
2. Tuples (())
Tuples are used to store multiple items in a single variable. They are ordered and unchangeable (immutable).
Syntax: my_tuple = ("apple", "banana", "cherry")
Key Characteristics:
Immutable: Once created, you cannot add or remove items. This makes them faster than lists.
Safety: Use tuples for data that should not change (e.g., coordinates, RGB color codes).
Unpacking: You can "unpack" tuple values into variables: x, y = (10, 20).
4. Sets ({})
Sets are used to store multiple items in a single variable, but they are unordered, unchangeable (though you
can add/remove items), and unindexed.
Syntax: my_set = {"apple", "banana", "cherry"}
Key Characteristics:
No Duplicates: If you add "apple" twice, the set will only contain it once.
Mathematical Operations: Great for operations like Union, Intersection, and Difference.
Comparison Summary Table
*Set items are unchangeable, but you can remove and add new items.
When to use which?
1. Use a List if you have a collection of items where the order matters and you might need to change the
data later.
2. Use a Tuple when the data is fixed and shouldn't be altered (acts like a constant list).
3. Use a Dictionary when you need a logical association between a key and a value (like a phonebook).
4. Use a Set when you only care about unique items and need to perform mathematical set operations.
SCHOOL OF COMPUTER SCIENCE AND ENGINEERING
Opening a File
To open a file, we can use open() function, which requires file-path and mode as arguments.
Syntax:
Note: If you don’t specify the mode, Python uses 'r' (read mode) by default.
Closing a File
The [Link]() method closes the file and releases the system resources. If the file was opened
in write or append mode, closing ensures that all changes are properly saved.
print("Filename:", [Link])
print("Mode:", [Link])
print("Is Closed?", [Link])
[Link]()
print("Is Closed?", [Link])
Output:
Filename: [Link]
Mode: r
Is Closed? False
Is Closed? True
Explanation:
[Link]: Returns the name of the file that was opened (in this case, "[Link]").
[Link]: Tells us the mode in which the file was opened. Here, it’s 'r' which means read mode.
[Link]: Returns a boolean value- False when file is currently open otherwise True.
Reading a File
Reading a file can be achieved by [Link]() which reads the entire content of the file. After
reading, it’s good practice to close the file to free up system resources.
Example: Reading a File in Read Mode (r)
file = open("[Link]", "r")
content = [Link]()
print(content)
[Link]()
Output:
Hello world
Writing a File
In Python, writing to a file is done using the mode "w". This creates a new file if it doesn’t exist,
or overwrites the existing file if it does. The write() method is used to add content. After
writing, make sure to close the file.
Example: Writing to a file (overwrites if file exists)
with open("[Link]", "w") as file:
[Link]("Hello, Python!\n")
[Link]("File handling is easy with Python.")
print("File written successfully")
Output:
Hello, Python!
File handling is easy with Python.
Explanation:
"w" mode opens the file for writing (overwrites existing content if the file already exists).
write() method adds new text to the file.
When using with, the file closes automatically at the end of the block.
SCHOOL OF COMPUTER SCIENCE AND ENGINEERING
Output:
Hello, World!
Mode Description
‘r+’ Read and write. Raises I/O error if the file does not exist.
‘a+’ Read and append. Pointer at end. Creates file if it doesn't exist.
Mode Description
‘ab+’ Read and append in binary. Creates file if it does not exist.
Exception Handling
Python Exception Handling allows a program to gracefully handle unexpected events (like
invalid input or missing files) without crashing. Instead of terminating abruptly, Python lets you
detect the problem, respond to it, and continue execution when possible.
Output:
Can’t be divided by zero!
Explanation: Dividing a number by 0 raises a ZeroDivisionError. The try block contains code
that may fail and except block catches the error, printing a safe message instead of stopping the
program.
Python provides four main keywords for handling exceptions: try, except, else and finally each
plays a unique role. Let's see syntax:
try:
# Code
except SomeException:
# Code
else:
# Code
finally:
# Code
Explanation:
try: Runs the risky code that might cause an error.
except: Catches and handles the error if one occurs.
else: Executes only if no exception occurs in try.
finally: Runs regardless of what happens useful for cleanup tasks like closing files.
Example: This code attempts division and handles errors gracefully using try-except-else-
finally.
try:
n=0
res = 100 / n
except ZeroDivisionError:
print("You can't divide by zero!")
except ValueError:
print("Enter a valid number!")
else:
print("Result is", res)
finally:
print("Execution complete.")
Output
You can't divide by zero!
Execution complete.
Explanation: try block attempts division, except blocks catch specific errors, else block
executes only if no errors occur, while finally block always runs, signaling end of execution.
Output
Not Valid!
Output
Explanation: A TypeError occurs because you can’t divide a string by a number. The bare
except catches it, but this can make debugging harder since the actual error type is hidden. Use
bare except only as a last-resort safety net.
Raise an Exception
We raise an exception in Python using the raise keyword followed by an instance of the
exception class that we want to trigger. We can choose from built-in exceptions or define our
own custom exceptions by inheriting from Python's built-in Exception class.
Basic Syntax:
raise ExceptionType("Error message")
Example: This code raises a ValueError if an invalid age is given.
def set(age):
if age < 0:
raise ValueError("Age cannot be negative.")
print(f"Age set to {age}")
try:
set(-5)
except ValueError as e:
print(e)
def set(age):
if age < 0:
raise ValueError("Age cannot be negative.")
print(f"Age set to {age}")
try:
set(-5)
except ValueError as e:
print(e)
def set(age):
if age < 0:
raise ValueError("Age cannot be negative.")
print(f"Age set to {age}")
try:
set(-5)
except ValueError as e:
print(e)
Output
Age cannot be negative.
Explanation: The function checks if age is invalid. If it is, it raises a ValueError. This prevents
invalid states from entering the program.
Custom Exceptions
You can also create custom exceptions by defining a new class that inherits from Python’s built-
in Exception class. This is useful for application-specific errors. Let's see an example to
understand how.
SCHOOL OF COMPUTER SCIENCE AND ENGINEERING
Example: This code defines a custom AgeError and uses it for validation.
class AgeError(Exception):
pass
def set(age):
if age < 0:
raise AgeError("Age cannot be negative.")
print(f"Age set to {age}")
try:
set(-5)
except AgeError as e:
print(e)
Output
Age cannot be negative
Explanation: Here, AgeError is a custom exception type. This makes error messages more
meaningful in larger applications.
Output:
Hello, World!
Explanation:
try: Starts the block to handle code that might raise an error.
open(): Opens the file in read mode.
read(): Reads the content of the file.
finally: Ensures the code inside it runs no matter what.
Advantages
Below are some benefits of using exception handling:
1. Improved reliability: Programs don’t crash on unexpected input.
2. Separation of concerns: Error-handling code stays separate from business logic.
3. Cleaner code: Fewer conditional checks scattered in code.
4. Helpful debugging: Tracebacks show exactly where the problem occurred.
Disadvantages
Exception handling have some cons as well which are listed below:
1. Performance overhead: Handling exceptions is slower than simple condition checks.
SCHOOL OF COMPUTER SCIENCE AND ENGINEERING