Python Programming
Complete Study Notes
Unit 1 & Unit 2 — All Sessions Covered
UNIT 1 — Python Fundamentals
Session 1 — Python Language Features
Python is a high-level, interpreted, general-purpose programming language. It emphasizes code
readability and uses indentation to define code blocks.
• Interpreted: Code runs line by line; no compilation step needed.
• Dynamically typed: Variables don't need explicit type declarations.
• Object-oriented: Everything in Python is an object.
• Cross-platform: Runs on Windows, macOS, Linux without modification.
• Extensive standard library: 'batteries included' philosophy.
💡 Python files use the .py extension. Run with: python [Link]
Session 2 — Comments, Identifiers & Variables
Comments
Comments are non-executable lines used to explain code.
# This is a single-line comment
"""
This is a
multi-line comment
"""
Identifiers
Identifiers are names given to variables, functions, classes, etc.
• Must start with a letter (a-z, A-Z) or underscore (_).
• Cannot start with a digit.
• Case-sensitive: age and Age are different identifiers.
• Cannot use reserved keywords like if, else, while, for, etc.
Variables & Assignments
Variables store data values. Python infers the type automatically.
name = 'Arush' # string
age = 20 # integer
gpa = 8.5 # float
is_student = True # boolean
💡 Python is dynamically typed — you can reassign a variable to a different type: x = 5 then
x = 'hello' is valid.
Session 3 — Variables & Assignments (Advanced)
Multiple assignments can be done in one line:
a, b, c = 1, 2, 3
x = y = z = 0 # All three assigned 0
• Augmented assignment: x += 1 is shorthand for x = x + 1
• Same applies to -=, *=, /=, //=, %=, **=
Session 4 — Expressions & Statements
An expression evaluates to a value. A statement performs an action.
3 + 4 # expression — evaluates to 7
x = 3 + 4 # statement — assigns value to x
• Python evaluates expressions using operator precedence (BODMAS / PEMDAS).
• Parentheses always take highest priority.
Session 5 — Data Types: Numbers
Python has three main numeric types:
• int — whole numbers: 5, -3, 100
• float — decimal numbers: 3.14, -0.5, 2.0
• complex — complex numbers: 3 + 4j
type(5) # <class 'int'>
type(3.14) # <class 'float'>
int('42') # converts string '42' to integer 42
float(7) # converts 7 to 7.0
💡 Integer division uses // (floor division). Example: 7 // 2 = 3. Regular / always returns float.
Session 6 — Data Types: List & Set
List
An ordered, mutable (changeable) collection. Allows duplicates.
fruits = ['apple', 'banana', 'cherry']
fruits[0] # 'apple' (indexing starts at 0)
fruits[-1] # 'cherry' (negative index from end)
[Link]('mango') # add to end
[Link]('banana') # remove by value
len(fruits) # number of elements
Set
An unordered collection with no duplicate values.
s = {1, 2, 3, 2, 1} # stored as {1, 2, 3}
[Link](4)
[Link](2)
• Sets support union (|), intersection (&), difference (-) operations.
• Sets are NOT indexed — you cannot do s[0].
Session 7 — Data Types: Dictionary
A dictionary stores key-value pairs. Keys must be unique and immutable.
student = {'name': 'Arush', 'age': 20, 'grade': 'A'}
student['name'] # 'Arush'
student['age'] = 21 # update value
student['city'] = 'Delhi' # add new key
del student['grade'] # delete a key
[Link]() # dict_keys(['name','age','city'])
[Link]() # dict_values(['Arush', 21, 'Delhi'])
[Link]() # returns (key, value) pairs
💡 Accessing a key that doesn't exist raises KeyError. Use [Link]('key', default) to avoid
this.
Session 8 — Input & Output Statements
Output — print()
print('Hello, World!')
print('Name:', name, 'Age:', age)
print(f"My name is {name} and I am {age} years old.") # f-string
Input — input()
name = input('Enter your name: ')
age = int(input('Enter your age: ')) # always returns string, cast as needed
💡 input() always returns a string. If you need a number, wrap it: int(input(...)) or
float(input(...))
Session 9 — Arithmetic Operators
Python supports all standard arithmetic operations:
+ Addition 5 + 3 = 8
- Subtraction 5 - 3 = 2
* Multiplication 5 * 3 = 15
/ Division 5 / 2 = 2.5 (always float)
// Floor Division 5 // 2 = 2 (discards decimal)
% Modulus 5 % 2 = 1 (remainder)
** Exponentiation 2 ** 3 = 8 (power)
💡 Remember operator precedence: ** > * / // % > + -. Use parentheses to control order.
Session 10 — Assignment Operators
Assignment operators assign and optionally modify values in one step:
x = 10 # basic assignment
x += 5 # x = x + 5 → 15
x -= 3 # x = x - 3 → 12
x *= 2 # x = x * 2 → 24
x /= 4 # x = x / 4 → 6.0
x //= 2 # x = x // 2 → 3
x **= 3 # x = x ** 3 → 27
x %= 5 # x = x % 5 → 2
Session 11 — Logical Operators
Used to combine or modify boolean (True/False) expressions:
and — True if both conditions are True
or — True if at least one condition is True
not — Reverses the boolean value
x = 5
x > 3 and x < 10 # True
x < 3 or x > 4 # True
not(x > 3) # False
Session 12 — Identity Operators
Identity operators check if two variables point to the same object in memory.
is — returns True if both variables refer to the same object
is not — returns True if they refer to different objects
a = [1, 2, 3]
b = a
c = [1, 2, 3]
a is b # True — same object
a is c # False — same values, different objects
💡 Use == to compare values. Use 'is' to compare identity (memory location). They are NOT
the same.
Session 13 — Introduction to Numbers (Deeper Dive)
Useful built-in number functions:
abs(-5) # 5 — absolute value
round(3.567, 2) # 3.57 — round to 2 decimal places
pow(2, 10) # 1024 — power
max(3, 7, 1) # 7 — maximum
min(3, 7, 1) # 1 — minimum
sum([1,2,3]) # 6 — sum of list
Math module for advanced operations:
import math
[Link](16) # 4.0
[Link] # 3.14159...
[Link](3.9) # 3
[Link](3.1) # 4
Session 14 — if Statement
The if statement executes a block of code only when a condition is True.
age = 18
if age >= 18:
print('You are an adult.')
• Indentation is mandatory in Python — it defines the code block.
• Condition must evaluate to True or False.
Session 15 — if-else Statement
The else block runs when the if condition is False.
marks = 45
if marks >= 50:
print('Pass')
else:
print('Fail')
if-elif-else (multiple conditions)
if marks >= 90:
print('Grade A')
elif marks >= 75:
print('Grade B')
elif marks >= 50:
print('Grade C')
else:
print('Fail')
Session 16 — if-else-if (Nested & Chained)
You can nest if statements inside each other for complex decisions:
if x > 0:
if x < 100:
print('x is between 0 and 100')
else:
print('x is 100 or more')
else:
print('x is 0 or negative')
💡 Avoid deeply nested if-else. Use elif chains for flat, readable code.
Session 17 — While Loop
Repeats a block as long as the condition remains True. Use when the number of iterations is
unknown.
count = 0
while count < 5:
print(count)
count += 1 # IMPORTANT: update variable or infinite loop!
• Always ensure the condition eventually becomes False.
• An infinite loop runs forever — exit with Ctrl+C.
Session 18 — For Loop
Iterates over a sequence (list, string, range, etc.).
for i in range(5):
print(i) # prints 0 1 2 3 4
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)
range() function
range(5) # 0, 1, 2, 3, 4
range(1, 6) # 1, 2, 3, 4, 5
range(0, 10, 2) # 0, 2, 4, 6, 8 (step = 2)
Session 19 — Break Statement
break exits the loop immediately, even if the condition is still True.
for i in range(10):
if i == 5:
break # stops loop when i reaches 5
print(i) # prints 0 1 2 3 4
💡 break only exits the innermost loop. In nested loops, the outer loop continues.
Session 20 — Continue Statement
continue skips the rest of the current iteration and jumps to the next one.
for i in range(6):
if i == 3:
continue # skip 3
print(i) # prints 0 1 2 4 5
Session 21 — Pass Statement
pass is a placeholder that does nothing. Used when code is syntactically required but you have
nothing to write yet.
for i in range(5):
pass # no error; loop runs but does nothing
def my_function():
pass # placeholder for future implementation
UNIT 2 — Strings, Functions &
Advanced Topics
Session 1 — Introduction to Strings
A string is a sequence of characters enclosed in single or double quotes.
s1 = 'Hello'
s2 = "World"
s3 = """Multi
line
string"""
• Strings are immutable — you cannot change a character in place.
• Strings are indexed starting at 0.
s = 'Python'
s[0] # 'P'
s[-1] # 'n'
s[1:4] # 'yth' (slicing)
Session 2 — Built-in String Methods
s = 'Hello World'
[Link]() # 'HELLO WORLD'
[Link]() # 'hello world'
[Link]() # removes leading/trailing whitespace
[Link]('o','0') # 'Hell0 W0rld'
[Link](' ') # ['Hello', 'World']
[Link]('World') # 6 (index where found)
[Link]('He') # True
[Link]('ld') # True
len(s) # 11
'hello'.capitalize() # 'Hello'
' hi '.strip() # 'hi'
Session 3 — String Functions to Lists
Strings and lists interact closely in Python:
sentence = 'apple,banana,cherry'
words = [Link](',') # ['apple', 'banana', 'cherry']
words = ['apple', 'banana', 'cherry']
sentence = ', '.join(words) # 'apple, banana, cherry'
list('hello') # ['h', 'e', 'l', 'l', 'o']
Session 4 — Basic List Operations
lst = [3, 1, 4, 1, 5, 9]
[Link](2) # [3,1,4,1,5,9,2]
[Link](0, 10) # [10,3,1,4,1,5,9,2]
[Link](1) # removes first occurrence of 1
[Link]() # removes & returns last element
[Link](2) # removes & returns element at index 2
[Link]() # sorts in-place ascending
[Link](reverse=True) # sort descending
[Link]() # reverse in-place
[Link](1) # count occurrences of 1
[Link](5) # index of first 5
sorted(lst) # returns new sorted list (non-destructive)
Session 5 — Built-in List Functions
numbers = [5, 2, 8, 1, 9]
len(numbers) # 5 — number of elements
max(numbers) # 9 — maximum value
min(numbers) # 1 — minimum value
sum(numbers) # 25 — sum of all elements
sorted(numbers) # [1, 2, 5, 8, 9] — new sorted list
list(range(5)) # [0, 1, 2, 3, 4]
enumerate(numbers) # gives (index, value) pairs
# Useful with loops:
for i, val in enumerate(numbers):
print(i, val)
Session 6 — List Methods
Key list methods — note the difference between in-place vs returning new list:
lst = [1, 2, 3]
[Link](4) # in-place, returns None
[Link]([5, 6]) # adds multiple elements — [1,2,3,4,5,6]
[Link]() # empties the list — []
copy = [Link]() # shallow copy
💡 [Link]() modifies the original. sorted(lst) creates a new sorted list. Know the difference in
exams.
Session 7 — Introduction to Tuples
A tuple is an ordered, immutable collection. Defined with parentheses.
t = (1, 2, 3)
t[0] # 1
t[-1] # 3
len(t) # 3
• Immutable — cannot add, remove, or change elements after creation.
• Faster than lists for iteration.
• Used for fixed data like coordinates, RGB colors, database rows.
# Tuple unpacking
x, y, z = (10, 20, 30)
💡 A single-element tuple needs a trailing comma: t = (5,). Without it, (5) is just an int.
Session 8 — Built-in Dictionary Functions
d = {'a': 1, 'b': 2, 'c': 3}
len(d) # 3
[Link]() # dict_keys(['a','b','c'])
[Link]() # dict_values([1, 2, 3])
[Link]() # dict_items([('a',1),('b',2),('c',3)])
[Link]('a') # 1
[Link]('z', 0) # 0 — default if key missing
[Link]('b') # removes 'b', returns its value 2
[Link]({'d': 4}) # adds or updates key
'a' in d # True — membership check
Session 9 — Introduction to Sets
A set is an unordered collection of unique elements.
s = {1, 2, 3, 4}
[Link](5)
[Link](2) # raises KeyError if not found
[Link](10) # no error if not found
[Link]() # removes & returns arbitrary element
Set Operations
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
A | B # union: {1,2,3,4,5,6}
A & B # intersection: {3, 4}
A - B # difference: {1, 2}
A ^ B # symmetric diff: {1,2,5,6}
Session 10 — Sets: Scope of Functions
Frozenset is an immutable version of set — useful as dictionary keys.
fs = frozenset([1, 2, 3])
# [Link](4) — this would raise AttributeError
Set comprehension:
squares = {x**2 for x in range(6)} # {0, 1, 4, 9, 16, 25}
Session 11 — Built-in Set Functions
s = {5, 1, 8, 3}
len(s) # 4
max(s) # 8
min(s) # 1
sum(s) # 17
sorted(s) # [1, 3, 5, 8] — returns list, not set
list(s) # convert to list (order not guaranteed)
Session 12 — Scope of Functions
Local vs Global Scope
A variable defined inside a function is local to that function. A variable defined outside is global.
x = 10 # global variable
def show():
y = 5 # local variable
print(x) # can access global
print(y) # can access local
show()
# print(y) # Error! y is not accessible here
global keyword
count = 0
def increment():
global count
count += 1 # modifies global variable
Session 13 — Parameters and Arguments
Types of Arguments
# Positional
def greet(name, age):
print(f'{name} is {age}')
greet('Arush', 20)
# Keyword
greet(age=20, name='Arush') # order doesn't matter
# Default
def greet(name, age=18):
print(f'{name} is {age}')
greet('Arush') # uses default age=18
# Variable-length (*args and **kwargs)
def add(*args):
return sum(args)
add(1, 2, 3, 4) # 10
def info(**kwargs):
for k, v in [Link]():
print(k, ':', v)
info(name='Arush', age=20)
Session 14 — Default Arguments
Default values are used when no argument is provided for that parameter.
def power(base, exp=2):
return base ** exp
power(3) # 9 (uses default exp=2)
power(3, 3) # 27 (overrides default)
💡 Default parameters must come AFTER non-default parameters in the function definition.
Session 15 — Anonymous Functions (Lambda)
A lambda function is a small, one-line anonymous function.
# Syntax: lambda arguments: expression
square = lambda x: x ** 2
square(5) # 25
add = lambda x, y: x + y
add(3, 4) # 7
Lambda is often used with map(), filter(), sorted():
nums = [3, 1, 4, 1, 5, 9]
sorted(nums, key=lambda x: -x) # descending sort
# map — apply function to all elements
squares = list(map(lambda x: x**2, [1,2,3,4])) # [1,4,9,16]
# filter — keep elements where function returns True
evens = list(filter(lambda x: x%2==0, [1,2,3,4,5,6])) # [2,4,6]
Session 16 — Global and Local Variables
Python scoping follows the LEGB rule:
• L — Local: Inside the current function
• E — Enclosing: In any enclosing function (for nested functions)
• G — Global: At the module level
• B — Built-in: Python's built-in names like len, print, range
x = 'global'
def outer():
x = 'enclosing'
def inner():
x = 'local'
print(x) # 'local'
inner()
print(x) # 'enclosing'
outer()
print(x) # 'global'
Session 17 — Recursion
A function that calls itself is recursive. Every recursive function needs a base case to stop.
def factorial(n):
if n == 0 or n == 1: # base case
return 1
return n * factorial(n - 1) # recursive call
factorial(5) # 5 * 4 * 3 * 2 * 1 = 120
Fibonacci using Recursion
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
fib(6) # 8 (sequence: 0 1 1 2 3 5 8)
• Pros: Clean, mirrors mathematical definition.
• Cons: Can be slow for large inputs (repeated subproblems). Use memoization for
optimization.
💡 Every recursive function MUST have a base case. Without it, you get infinite recursion and
a RecursionError.
Appendix — Lambda, map() and zip() in Detail
lambda — Anonymous One-Line Function
A lambda is a small, nameless function written in a single line. It does exactly what a def
function does but without a name and without a return statement — the expression after the
colon is automatically returned.
lambda arguments : expression
# Regular def function
def square(x):
return x ** 2
# Exact same thing using lambda
square = lambda x: x ** 2
square(5) # 25
Multiple arguments and with if/else (ternary):
add = lambda x, y: x + y
add(3, 4) # 7
even_odd = lambda x: "even" if x % 2 == 0 else "odd"
even_odd(4) # 'even'
even_odd(7) # 'odd'
Best real use — as a sort key:
students = [('Arush', 85), ('Raj', 92), ('Priya', 78)]
sorted(students, key=lambda x: x[1])
# [('Priya', 78), ('Arush', 85), ('Raj', 92)]
💡 Lambda can only hold ONE expression — no multiple lines, no loops inside. The moment
your logic needs two lines, use a regular def function instead.
map() — Apply a Function to Every Element
map(function, iterable) applies a function to every element of an iterable and returns a map
object. You usually wrap it in list() to see the result.
# Syntax
map(function, iterable)
Example 1 — convert list of strings to integers:
nums = ['1', '2', '3', '4']
list(map(int, nums)) # [1, 2, 3, 4]
Example 2 — square every number using lambda:
list(map(lambda x: x**2, [1, 2, 3, 4]))
# [1, 4, 9, 16]
Most common exam use — reading multiple integers on one line:
# User types: 10 20 30
nums = list(map(int, input().split()))
# nums = [10, 20, 30]
# Or unpack directly into variables:
a, b, c = map(int, input().split())
💡 map() returns a map object, not a list. Always wrap with list() if you want to print or index
into it. Also, map() never changes the original iterable — it always produces a new result.
zip() — Combine Multiple Iterables Together
zip() takes two or more iterables and pairs their elements together index by index, returning
tuples. Think of it like a physical zip on a jacket — it joins two sides together tooth by tooth.
names = ['Arush', 'Raj', 'Priya']
marks = [85, 92, 78]
list(zip(names, marks))
# [('Arush', 85), ('Raj', 92), ('Priya', 78)]
Using zip() in a for loop — most common use:
for name, mark in zip(names, marks):
print(f'{name} scored {mark}')
# Arush scored 85
# Raj scored 92
# Priya scored 78
zip() with three lists:
names = ['Arush', 'Raj']
marks = [85, 92]
grades = ['B', 'A']
list(zip(names, marks, grades))
# [('Arush', 85, 'B'), ('Raj', 92, 'A')]
What happens when lists have different lengths:
list(zip([1, 2, 3], ['a', 'b']))
# [(1, 'a'), (2, 'b')] — stops at shortest list
💡 zip() stops at the shortest iterable — extra elements in longer lists are silently ignored.
Also like map(), it returns a zip object so wrap with list() to use it.
Using lambda + map() + zip() Together
These three are often combined for concise data processing:
# Add corresponding elements of two lists
a = [1, 2, 3]
b = [10, 20, 30]
list(map(lambda x, y: x + y, a, b))
# [11, 22, 33]
# Sort zipped pairs by mark descending
names = ['Arush', 'Raj', 'Priya']
marks = [85, 92, 78]
sorted(zip(names, marks), key=lambda x: x[1], reverse=True)
# [('Raj', 92), ('Arush', 85), ('Priya', 78)]
UNIT 3 — Object-Oriented Programming (OOP)
Session 1 — Classes, Attributes & Objects
Classes are blueprints for creating objects. They encapsulate data (attributes) and behavior
(methods) into a single entity.
Class Definition
A class is defined using the class keyword:
class Dog:
def __init__(self, name, age):
[Link] = name # Attribute
[Link] = age
dog1 = Dog("Buddy", 5) # Creating an object (instance)
Key Concepts:
• Object: An instance of a class containing specific data and behavior.
• Attributes: Variables that belong to an object (e.g., name, age).
• __init__() method: Constructor that initializes objects when created.
• self: Refers to the current object instance; must be the first parameter in methods.
Session 2 — Methods
Methods are functions defined inside a class that describe behaviors of objects.
Types of Methods:
• Instance Methods: Access and modify object-specific data using self.
• Class Methods: Marked with @classmethod; use cls instead of self; operate on class-level
data.
• Static Methods: Marked with @staticmethod; don't access self or cls; act as utility functions.
Example:
class Calculator:
@staticmethod
def add(a, b):
return a + b
print([Link](5, 3)) # Output: 8
Session 3 — Inheritance
Inheritance allows a class (child) to inherit attributes and methods from another class (parent),
promoting code reuse.
Single Inheritance:
class Animal:
def speak(self):
return "Some sound"
class Dog(Animal):
def speak(self):
return "Woof!" # Overriding parent method
dog = Dog()
print([Link]()) # Output: Woof!
Key Points:
• Child class inherits all parent methods and attributes.
• super() is used to call parent class methods.
• Method Overriding: Child redefines a parent method with new behavior.
• isinstance() checks if an object is an instance of a class or its subclass.
Session 4 — Polymorphism & Method Overloading
Polymorphism means "many forms." It allows objects of different classes to be used
interchangeably.
Method Overriding (Runtime Polymorphism):
class Cat(Animal):
def speak(self):
return "Meow!"
for animal in [Dog(), Cat()]:
print([Link]()) # Calls appropriate method
Duck Typing:
Python doesn't care about an object's class, only its behavior. If it has the required method, it
works.
def make_sound(creature):
print([Link]()) # Works with Dog, Cat, or any class
Note: Python doesn't support traditional method overloading (same name, different parameters).
Use *args or default parameters instead.
Session 5 — Encapsulation, Abstraction & Data Hiding
Encapsulation is bundling data and methods, and controlling access to them.
Access Modifiers:
• Public (no prefix): Accessible from anywhere (e.g., [Link]).
• Protected (_single underscore): Convention; meant for internal use (e.g., self._age).
• Private (__double underscore): Name-mangled; harder to access from outside (e.g.,
self.__salary).
Example with Properties:
class Person:
def __init__(self, name, age):
self.__age = age # Private
@property
def age(self):
return self.__age
@[Link]
def age(self, value):
if value > 0:
self.__age = value
person = Person("Alice", 25)
print([Link]) # Uses getter
[Link] = 26 # Uses setter
Abstraction:
• Hide complex implementation details; expose only essential features.
• Use abstract classes and methods to define contracts for subclasses.
Session 6 — Operator Overloading
Define custom behavior for operators like +, -, *, ==, etc., using special methods (dunder
methods).
Common Operator Methods:
• __add__(self, other): Addition (obj1 + obj2)
• __sub__(self, other): Subtraction (obj1 - obj2)
• __mul__(self, other): Multiplication (obj1 * obj2)
• __eq__(self, other): Equality (obj1 == obj2)
• __lt__(self, other): Less than (obj1 < obj2)
• __str__(self): String representation for print()
• __repr__(self): Official string representation for debugging
Example:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # Calls __add__
print(v3) # Output: (4, 6)
Session 7 — Abstract Base Classes (ABC)
Abstract Base Classes define a template for subclasses. They cannot be instantiated directly.
Key Concepts:
• Use abc module to create abstract classes.
• @abstractmethod defines methods that must be implemented by subclasses.
• Prevents incomplete implementations; enforces interface contracts.
Example:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
[Link] = radius
def area(self):
return 3.14 * [Link] ** 2
circle = Circle(5)
print([Link]()) # Works fine
UNIT 4 — File Handling & Exception Management
Session 1 — File Handling: File Paths & File Operations
File handling involves reading from and writing to files on disk.
File Paths:
• Absolute Path: Full path from root directory (e.g., C:\Users\Name\[Link])
• Relative Path: Path relative to current working directory (e.g., ./data/[Link])
Opening Files:
Use open(filename, mode) function. Common modes:
• "r" (Read): Open for reading (default; file must exist).
• "w" (Write): Open for writing; creates file if not exists; overwrites if exists.
• "a" (Append): Open for appending; adds content to end of file.
• "b" (Binary): Combine with above (e.g., "rb", "wb") for binary files.
Example:
# Writing to a file
with open("[Link]", "w") as file:
[Link]("Hello, World!")
# Reading from a file
with open("[Link]", "r") as file:
content = [Link]()
print(content)
Best Practice:
Always use context managers (with statement) to ensure files close automatically.
Session 2 — File Handling: Operations & Methods
Common File Methods:
• read(): Returns entire file content as a string.
• readline(): Reads one line from file.
• readlines(): Reads all lines; returns list of strings.
• write(string): Writes string to file.
• writelines(list): Writes multiple strings (list) to file.
• seek(position): Moves file pointer to specified position.
• tell(): Returns current file pointer position.
• close(): Closes the file.
Reading Line by Line:
with open("[Link]", "r") as file:
for line in file:
print([Link]()) # strip() removes newline
Appending to File:
with open("[Link]", "a") as file:
[Link]("\nNew line") # Adds to end
Working with CSV:
Use csv module for structured data:
import csv
with open("[Link]", "r") as file:
reader = [Link](file)
for row in reader:
print(row)
Session 3 — Errors and Exception Handling
Exceptions are runtime errors that disrupt program flow. Proper handling prevents crashes.
Common Exceptions:
• SyntaxError: Invalid Python syntax (caught during parsing).
• ZeroDivisionError: Division by zero.
• NameError: Using undefined variable or function.
• TypeError: Operating on wrong data type.
• ValueError: Correct type but invalid value.
• IndexError: Accessing invalid list/string index.
• KeyError: Accessing non-existent dictionary key.
• FileNotFoundError: File does not exist.
• IOError: Input/output operation fails.
Try-Except Block:
try:
num = int(input("Enter number: "))
result = 10 / num
except ZeroDivisionError:
print("Cannot divide by zero!")
except ValueError:
print("Enter a valid integer!")
except Exception as e:
print(f"An error occurred: {e}")
else:
print(f"Result: {result}") # Runs if no exception
finally:
print("Cleanup code here") # Always runs
Raising Custom Exceptions:
def validate_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
return age
try:
validate_age(-5)
except ValueError as e:
print(f"Error: {e}")
Creating Custom Exception Classes:
class InsufficientFundsError(Exception):
def __init__(self, balance):
[Link] = balance
super().__init__(f"Insufficient funds. Balance: {balance}")
try:
raise InsufficientFundsError(100)
except InsufficientFundsError as e:
print(e)