Topic 1 / 70
Unit-I · Introduction

Programming Language

Beginner Unit-I CO1

A programming language is a formal set of instructions that can be used to produce various kinds of output. It enables humans to communicate logic to a computer in a structured, unambiguous way.

Programming languages are broadly classified into:

  • Low-level languages: Machine language (binary 0s and 1s) and Assembly language. Very fast, hardware-specific.
  • High-level languages: Languages like Python, Java, C++ — closer to human language, portable, and easier to learn.
  • Scripting languages: Interpreted languages used to automate tasks (e.g., Python, Bash, JavaScript).

A programming language is defined by its syntax (rules of structure) and semantics (meaning of the statements). The computer does not understand high-level code directly — it is translated by an interpreter or compiler.

🎯 Exercise 1

List 5 programming languages and classify each as compiled, interpreted, or hybrid.

Unit-I · Introduction

History and Origin of Python Language

Beginner Unit-I CO1

Python was conceived in the late 1980s by Guido van Rossum at Centrum Wiskunde & Informatica (CWI), Netherlands, as a successor to the ABC programming language.

VersionYearKey Milestone
Python 0.9.01991First published release
Python 1.01994lambda, map, filter added
Python 2.02000List comprehensions, garbage collection
Python 3.02008Major redesign, not backward compatible
Python 3.10+2021+Match statements, performance improvements

The name "Python" comes from the British comedy show "Monty Python's Flying Circus" — Guido van Rossum was a fan while writing the language.

🎯 Exercise 2

Research the key differences between Python 2 and Python 3. Why is Python 2 no longer supported?

Unit-I · Introduction

Features of Python

Beginner Unit-I CO1
  • Simple & Easy to Learn: Python's clean, readable syntax closely resembles English.
  • Interpreted: Code is executed line-by-line at runtime — no compilation step needed.
  • Dynamically Typed: Variable types are determined at runtime, not declared explicitly.
  • Object-Oriented: Supports classes, inheritance, encapsulation, and polymorphism.
  • Platform Independent: Runs on Windows, macOS, Linux, and Unix without changes.
  • Extensive Standard Library: Ships with libraries for math, file I/O, networking, and more.
  • Open Source & Free: Python is freely available and actively community-driven.
  • Extensible: Can integrate C/C++ code for performance-critical sections.
  • Embeddable: Python can be embedded within C/C++ programs.
  • High-level Language: Memory management is handled automatically.
🎯 Exercise 3

Explain why "dynamically typed" is both an advantage and a potential source of bugs. Give an example.

Unit-I · Introduction

Limitations of Python

Beginner Unit-I CO1

Despite its popularity, Python has several notable limitations:

  • Slow Execution Speed: Being interpreted, Python is significantly slower than compiled languages like C or C++.
  • High Memory Consumption: Dynamic typing and garbage collection consume more memory than statically typed languages.
  • Global Interpreter Lock (GIL): Python threads cannot run in true parallel on multi-core CPUs due to the GIL, limiting multi-threading performance.
  • Weak in Mobile Development: Python has limited native support for Android and iOS app development.
  • Runtime Errors: Dynamic typing means many errors only appear at runtime, not at compile time.
  • Not Ideal for Low-level Programming: Direct hardware manipulation, device drivers, and kernel code cannot be written in Python.
🎯 Exercise 4

Research what the Global Interpreter Lock (GIL) is and how Python developers work around it using multiprocessing.

Unit-I · Introduction

Major Applications of Python

Beginner Unit-I CO1

Python is one of the most versatile languages in the world. Its major application areas include:

  • Web Development: Frameworks like Django and Flask power millions of websites.
  • Data Science & Analytics: Libraries like Pandas, NumPy, and Matplotlib are industry standards.
  • Machine Learning & AI: TensorFlow, PyTorch, and scikit-learn are all Python-based.
  • Automation & Scripting: Automating repetitive system tasks, file operations, and workflows.
  • Cybersecurity: Writing penetration testing tools, exploit scripts, and network scanners.
  • Game Development: Pygame library allows 2D game creation.
  • Web Scraping: BeautifulSoup and Scrapy extract data from websites.
  • Scientific Computing: Used in physics, biology, and engineering simulations (SciPy).
  • Finance & Trading: Algorithmic trading bots and financial modelling.
  • Embedded Systems & IoT: MicroPython runs on microcontrollers like Raspberry Pi.
🎯 Exercise 5

Pick one application domain and research one real-world product or company that uses Python in that domain.

Unit-I · Introduction

Getting and Installing Python

Beginner Unit-I CO1

Python can be downloaded for free from the official website: https://www.python.org/downloads/

Steps to install Python on Windows:

  1. Go to python.org and download the latest installer (.exe).
  2. Run the installer.
  3. ✅ Check the box "Add Python to PATH" before clicking Install.
  4. Click "Install Now".
  5. Verify installation by opening Command Prompt and typing:
Terminal
python --version
# Expected: Python 3.x.x

pip --version
# Expected: pip xx.x from ...

pip is Python's package manager, installed alongside Python. It lets you install third-party libraries.

🎯 Exercise 6

Install Python on your system. Verify it is working by running python --version and pip --version in your terminal.

Unit-I · Introduction

Setting up Path and Environment Variables

Beginner Unit-I CO1

The PATH environment variable tells your operating system where to find executable programs. When Python is added to PATH, you can run python from any terminal directory.

Manually adding Python to PATH on Windows:

  1. Search for "Environment Variables" in the Start Menu.
  2. Click "Edit the system environment variables".
  3. Click "Environment Variables..." button.
  4. Under "System variables", select Path and click "Edit".
  5. Click "New" and add the path to Python (e.g., C:\Python312\ and C:\Python312\Scripts\).
  6. Click OK and restart your terminal.
Terminal — Verify PATH
where python
# Should output: C:\Python312\python.exe

echo %PATH%
# Lists all registered paths

The PYTHONPATH variable is a special environment variable that tells Python where to look for modules and packages beyond the default directories.

🎯 Exercise 7

Open your system's environment variables and verify Python is listed in PATH. Try running python from two different directories in your terminal.

Unit-I · Introduction

Running Python

Beginner Unit-I CO1

There are three main ways to run Python code:

1. Interactive Mode (REPL — Read Evaluate Print Loop):

Terminal
python
>>> 2 + 3
5
>>> print("Hello")
Hello
>>> exit()

2. Script Mode: Write code in a .py file and run it:

Terminal
python myprogram.py

3. IDE / Code Editor: Tools like VS Code, PyCharm, IDLE, or Jupyter Notebook provide a full development environment with syntax highlighting, debugging, and auto-complete.

🎯 Exercise 8

Run Python in interactive mode and compute: (15 + 3) * 2 / 9. Then create a script file that does the same calculation and prints the result.

Unit-I · Introduction

First Python Program

Beginner Unit-I CO1

The tradition in programming is to write a "Hello, World!" program as your very first code. In Python, this is remarkably simple:

hello.py
print("Hello, World!")

Run it with:

Terminal
python hello.py
# Output: Hello, World!

Let's extend this to a slightly more meaningful first program:

first_program.py
name = input("Enter your name: ")
print(f"Welcome to Python, {name}!")
🎯 Exercise 9

Write a Python program that asks for your name and age, then prints a message saying "Hello [name], you will be [age+1] next year!"

Unit-I · Introduction

Python Interactive Help Feature

Beginner Unit-I CO1

Python has a powerful built-in help system accessible directly from the interpreter. The help() function retrieves documentation for any object, function, module, or keyword.

Python Shell
>>> help()         # Enter interactive help mode
>>> help(print)    # Get docs for print function
>>> help(str)      # Get docs for string class
>>> help("for")    # Get docs for the 'for' keyword

Other useful built-in inspection tools:

  • dir(obj) — lists all attributes and methods of an object.
  • type(obj) — returns the data type of a variable.
  • id(obj) — returns the memory address of an object.
  • isinstance(obj, type) — checks if an object is an instance of a class.
Python Shell
>>> dir("hello")
['capitalize', 'casefold', 'center', ...]
>>> type(3.14)
<class 'float'>
🎯 Exercise 10

Use help(input) and dir(list) in the Python shell and document 5 interesting things you discover about each.

Unit-I · Introduction

Python Differences from Other Languages

Beginner Unit-I CO1
FeaturePythonC / C++Java
Code BlocksIndentationCurly braces { }Curly braces { }
TypingDynamicStaticStatic
ExecutionInterpretedCompiledCompiled to bytecode
Memory MgmtAutomatic (GC)ManualAutomatic (GC)
SemicolonsNot requiredRequiredRequired
Variable DeclarationNo keyword neededint x = 5;int x = 5;
Hello World Lines1 line5+ lines5+ lines
🎯 Exercise 11

Write "Hello, World!" in Python, C, and Java. Compare the amount of boilerplate code required in each.

Unit-I · Data Types & I/O

Keywords

Beginner Unit-I CO1

Keywords are reserved words in Python that have a fixed meaning and cannot be used as identifiers (variable names, function names, etc.).

Python 3 has 35 keywords. You can view them all with:

keywords.py
import keyword
print(keyword.kwlist)
print(len(keyword.kwlist))  # 35
CategoryKeywords
BooleanTrue, False, None
Logicaland, or, not
Control Flowif, elif, else, for, while, break, continue, pass, return
Functions/Classesdef, class, lambda, yield
Exceptionstry, except, finally, raise, with, as
Importimport, from, as
Scopeglobal, nonlocal, del
Identity/Membershipis, in
🎯 Exercise 12

Try to use a keyword as a variable name (e.g., for = 5). Observe the error. Then list 5 keywords and write a sentence explaining what each does.

Unit-I · Data Types & I/O

Identifiers

Beginner Unit-I CO1

An identifier is a user-defined name given to a variable, function, class, module, or any other object. Rules for valid identifiers:

  • Must start with a letter (a–z, A–Z) or underscore (_).
  • Cannot start with a digit.
  • Can contain letters, digits (0–9), and underscores.
  • Cannot be a Python keyword.
  • Case-sensitive: name, Name, and NAME are three different identifiers.
  • No special characters allowed (@, #, $, etc.).
identifiers.py
# Valid identifiers
student_name = "Alice"
_count = 10
MyClass2 = True

# Invalid identifiers
# 2count = 5      → SyntaxError: starts with digit
# my-var = 3     → SyntaxError: hyphen not allowed
# class = "CS"   → SyntaxError: keyword

Naming conventions:

  • snake_case — for variables and functions (Python standard)
  • PascalCase — for class names
  • UPPER_CASE — for constants
  • _single_leading_underscore — internal use
  • __double_leading_underscore — name mangling in classes
🎯 Exercise 13

Write 5 valid and 5 invalid identifiers. Explain why each invalid one fails.

Unit-I · Data Types & I/O

Python Statement

Beginner Unit-I CO1

A statement is an instruction that the Python interpreter can execute. Unlike many languages, Python statements do not require a semicolon at the end.

Types of statements:

  • Simple Statement: A single logical line of code. E.g., x = 5, print("Hi").
  • Compound Statement: Contains a header and a body (e.g., if, for, def, class).
  • Multi-line Statements: A statement that spans multiple lines using line continuation.
statements.py
# Explicit line continuation with backslash
total = 10 + 20 + \
        30 + 40

# Implicit continuation inside brackets
result = (10 + 20 +
          30 + 40)

# Multiple statements on one line (not recommended)
a = 1; b = 2; c = 3
🎯 Exercise 14

Write a multi-line statement calculating the sum of 10 numbers using both the backslash continuation and parenthesis methods.

Unit-I · Data Types & I/O

Indentation

Beginner Unit-I CO1

Unlike other languages that use curly braces { }, Python uses indentation (whitespace) to define code blocks. This is not optional — it is part of Python's syntax.

indentation.py
if True:
    print("This is inside the if block")
    print("Still inside the if block")
print("This is outside — not indented")

Rules:

  • Standard indentation is 4 spaces (PEP 8 guideline).
  • Tabs and spaces must not be mixed — Python 3 raises a TabError.
  • All lines within the same block must have the same indentation level.
  • An IndentationError is raised for incorrect indentation.
indent_error.py
if True:
print("Error!")   # IndentationError — not indented
🎯 Exercise 15

Write a nested if-else inside a for loop demonstrating 3 levels of indentation correctly.

Unit-I · Data Types & I/O

Documentation

Beginner Unit-I CO1

Documentation makes code readable and maintainable. Python supports two forms of documentation:

1. Single-line Comments: Use # — the interpreter ignores everything after it on that line.

2. Docstrings (Documentation Strings): Multi-line strings using triple quotes ("""...""" or '''...'''). They document modules, classes, and functions and can be accessed via __doc__.

documentation.py
# This is a single-line comment

def add(a, b):
    """
    Add two numbers and return the result.

    Parameters:
        a (int): First number
        b (int): Second number

    Returns:
        int: Sum of a and b
    """
    return a + b

print(add.__doc__)  # Access docstring
🎯 Exercise 16

Write a function multiply(x, y) with a full docstring describing parameters and return value. Access and print its __doc__.

Unit-I · Data Types & I/O

Variables

Beginner Unit-I CO1

A variable is a named reference to a memory location that stores data. In Python, variables are created when you assign a value — no explicit declaration is needed.

variables.py
name = "Alice"      # str
age = 20            # int
height = 5.6        # float
is_student = True   # bool

print(type(name))    # <class 'str'>
print(id(age))      # Memory address

Key Points:

  • Variables are labels pointing to objects in memory, not containers.
  • A variable can be reassigned to a completely different type at any time.
  • Python uses reference counting to manage memory for variables.
  • You can delete a variable using del variable_name.
🎯 Exercise 17

Create variables of types int, float, str, bool, and None. Print their types using type() and their memory addresses using id().

Unit-I · Data Types & I/O

Multiple Assignment

Beginner Unit-I CO1

Python allows assigning values to multiple variables in a single statement:

multiple_assign.py
# Assign different values to multiple variables
a, b, c = 10, 20.5, "Python"
print(a, b, c)   # 10 20.5 Python

# Assign the same value to multiple variables
x = y = z = 0
print(x, y, z)   # 0 0 0

# Swap variables without a temp variable
x, y = 5, 10
x, y = y, x
print(x, y)      # 10 5

# Unpack a list into variables
values = [1, 2, 3]
p, q, r = values
print(p, q, r)   # 1 2 3
🎯 Exercise 18

Use multiple assignment to swap three variables a, b, c in a cyclic manner (a→b, b→c, c→a) without a temp variable.

Unit-I · Data Types & I/O

Understanding Data Type

Beginner Unit-I CO1

A data type classifies data and determines what operations can be performed on it. Python has the following built-in data types:

CategoryTypeExample
Textstr"Hello"
Numericint, float, complex42, 3.14, 2+3j
Sequencelist, tuple, range[1,2], (1,2)
Mappingdict{"key": "val"}
Setset, frozenset{1, 2, 3}
BooleanboolTrue, False
Binarybytes, bytearrayb"hello"
NoneNoneTypeNone
datatypes.py
x = 42
print(type(x))         # <class 'int'>
print(isinstance(x, int))  # True
🎯 Exercise 19

Create one variable of each built-in type. Use type() and isinstance() to verify each one.

Unit-I · Data Types & I/O

Data Type Conversion

Beginner Unit-I CO1

Python supports two types of data conversion:

1. Implicit Conversion (Type Coercion): Python automatically converts one type to another without any user involvement.

implicit.py
result = 5 + 2.5      # int + float → float
print(result, type(result))  # 7.5 <class 'float'>

2. Explicit Conversion (Type Casting): You manually convert data types using built-in functions.

explicit.py
x = "42"
y = int(x)          # str → int
z = float(y)        # int → float
s = str(z)          # float → str
b = bool(0)         # int → bool → False
lst = list((1, 2, 3)) # tuple → list

print(y, z, s, b, lst)
🎯 Exercise 20

Write a program that takes a string number as input, converts it to int, performs arithmetic, converts back to string, and prints with formatting.

Unit-I · Data Types & I/O

Python Input and Output Functions

Beginner Unit-I CO1

Output — print():

output.py
print("Hello")                     # Basic output
print("Hello", "World", sep="-")    # Hello-World
print("Line1", end=" | ")           # No newline at end
print("Line2")

name = "Alice"; score = 98.5
print(f"Student: {name}, Score: {score:.2f}")  # f-string
print("Name: %s, Score: %.1f" % (name, score))  # % formatting

Input — input(): Always returns a string. Must be cast if you need a number.

input_demo.py
name = input("Enter your name: ")
age = int(input("Enter your age: "))
print(f"Hello {name}, you are {age} years old.")
🎯 Exercise 21

Write a program that inputs two numbers and prints their sum, difference, product, and quotient using f-strings with 2 decimal places.

Unit-I · Data Types & I/O

Import Command

Beginner Unit-I CO1

The import command loads external modules or libraries into your program. Python has several import forms:

imports.py
# Import entire module
import math
print(math.sqrt(16))    # 4.0

# Import specific function/attribute
from math import pi, ceil
print(pi)               # 3.14159...

# Import with alias
import datetime as dt
print(dt.date.today())

# Import all (not recommended)
from math import *
print(factorial(5))    # 120
🎯 Exercise 22

Import the random module and use it to generate 5 random integers between 1 and 100. Print them in a formatted list.

Unit-I · Operators & Expressions

Operators in Python

Beginner Unit-I CO1

An operator is a symbol that performs an operation on one or more operands. Python has the following operator categories:

TypeOperatorsExample
Arithmetic+ - * / // % **10 // 3 = 3
Comparison== != > < >= <=5 == 5 → True
Logicaland or notTrue and False → False
Assignment= += -= *= /= //= **=x += 5
Bitwise& | ^ ~ << >>5 & 3 = 1
Identityis is notx is None
Membershipin not in3 in [1,2,3]
operators.py
a, b = 10, 3
print(a + b, a - b, a * b)   # 13 7 30
print(a / b, a // b, a % b)  # 3.33 3 1
print(a ** b)                 # 1000
print(5 & 3, 5 | 3, 5 ^ 3)    # 1 7 6
🎯 Exercise 23

Write a program that accepts two integers and prints the result of every arithmetic and bitwise operator applied to them.

Unit-I · Operators & Expressions

Expressions

Beginner Unit-I CO1

An expression is a combination of values, variables, operators, and function calls that Python evaluates to produce a single value.

expressions.py
x = 5; y = 3

# Arithmetic expression
result = (x ** 2) + (2 * x * y) + (y ** 2)
print(result)   # 64

# Boolean expression
is_valid = (x > 0) and (y < 10)
print(is_valid)  # True

# Conditional (ternary) expression
label = "positive" if x > 0 else "non-positive"
print(label)     # positive

# String expression
greeting = "Hello" + " " + "World"
print(greeting)  # Hello World
🎯 Exercise 24

Write a program that evaluates the quadratic formula for given a, b, c values using a single expression. Handle the case where the discriminant is negative.

Unit-I · Operators & Expressions

Precedence

Beginner Unit-I CO1

Operator precedence determines which operator is evaluated first in an expression with multiple operators. Higher precedence operators are evaluated before lower ones.

PriorityOperatorsDescription
1 (Highest)()Parentheses
2**Exponentiation
3~, +, -Unary operators
4*, /, //, %Multiplication, Division
5+, -Addition, Subtraction
6<<, >>Bitwise Shift
7&Bitwise AND
8^Bitwise XOR
9|Bitwise OR
10==, !=, >, <...Comparisons
11notLogical NOT
12andLogical AND
13 (Lowest)orLogical OR
precedence.py
result = 2 + 3 * 4      # 14 (not 20)
result2 = (2 + 3) * 4    # 20
result3 = 2 ** 3 ** 2    # 512 (right-to-left)
print(result, result2, result3)
🎯 Exercise 25

Predict the output of: 3 + 5 * 2 - 4 / 2 ** 2 without running it. Then verify.

Unit-I · Operators & Expressions

Associativity of Operators

Beginner Unit-I CO1

When two operators have the same precedence, associativity determines the direction of evaluation:

  • Left-to-Right (Left associative): Most operators: +, -, *, /, //, %
  • Right-to-Left (Right associative): Exponentiation **, unary operators, assignment =
associativity.py
# Left associativity: evaluated left to right
result = 10 - 4 - 2     # (10 - 4) - 2 = 4
print(result)

# Right associativity: evaluated right to left
result2 = 2 ** 3 ** 2   # 2 ** (3 ** 2) = 2 ** 9 = 512
print(result2)

# Division is left associative
result3 = 100 / 10 / 2  # (100 / 10) / 2 = 5.0
print(result3)
🎯 Exercise 26

Evaluate 4 ** 3 ** 2 and (4 ** 3) ** 2. Show the difference and explain which one uses right associativity.

Unit-I · Operators & Expressions

Non Associative Operators

Beginner Unit-I CO1

Non-associative operators are operators that cannot be chained in the usual left-to-right or right-to-left manner. In Python, comparison operators are the primary example.

Python uses chained comparisons for comparison operators instead of standard associativity:

non_associative.py
# Chained comparison — Python reads it as:
# (1 < 5) and (5 < 10) → True
print(1 < 5 < 10)       # True

# Not: (1 < 5) < 10 → (True) < 10 → 1 < 10 → True (C-style)
# Python is smarter: it chains them properly

print(1 < 5 > 3)        # True (1<5 and 5>3)
print(1 == 1 == 1)      # True
print(5 < 5)             # False — not non-associative, just False
🎯 Exercise 27

Write expressions using chained comparisons to check if a number lies within a range (e.g., between 10 and 100 inclusive).

Unit-II · Control Structures

Decision Making Statements

Intermediate Unit-II

Decision making allows a program to choose different paths of execution based on conditions. Python uses if, elif, and else:

decisions.py
marks = 75

if marks >= 90:
    print("Grade: A")
elif marks >= 75:
    print("Grade: B")
elif marks >= 60:
    print("Grade: C")
else:
    print("Grade: F")

# Nested if
x = 10
if x > 0:
    if x % 2 == 0:
        print("Positive even number")

# One-liner (ternary)
status = "pass" if marks >= 50 else "fail"
print(status)
🎯 Exercise 28

Write a program that takes a year as input and checks whether it is a leap year using nested if statements.

Unit-II · Control Structures

Python Loops

Intermediate Unit-II

Loops execute a block of code repeatedly. Python has two types of loops:

1. for Loop: Iterates over a sequence (list, tuple, string, range).

for_loop.py
for i in range(1, 6):
    print(i, end=" ")  # 1 2 3 4 5

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

2. while Loop: Repeats as long as a condition remains True.

while_loop.py
count = 1
while count <= 5:
    print(count, end=" ")
    count += 1   # 1 2 3 4 5
🎯 Exercise 29

Print the multiplication table for a number entered by the user using both for and while loops.

Unit-II · Control Structures

Python Control Statements

Intermediate Unit-II

Control statements alter the normal sequential flow of loops:

  • break — exits the loop immediately.
  • continue — skips the current iteration and moves to the next.
  • pass — does nothing; acts as a placeholder.
control_stmts.py
for i in range(10):
    if i == 3:
        continue   # skip 3
    if i == 7:
        break      # stop at 7
    print(i, end=" ")   # 0 1 2 4 5 6

# pass — empty block placeholder
for x in range(5):
    pass   # will be implemented later
🎯 Exercise 30

Write a loop that prints numbers 1 to 20, skips all multiples of 3, and breaks when it hits a multiple of 7.

Unit-II · Native Data Types

Numbers

Intermediate Unit-II CO3

Python supports three numeric types:

  • int: Whole numbers of unlimited precision. E.g., 42, -7, 100000000
  • float: Real numbers with decimal points (64-bit IEEE 754). E.g., 3.14, -0.001, 2.5e10
  • complex: Numbers with real and imaginary parts. E.g., 3+4j
numbers.py
a = 100           # int
b = 3.14159       # float
c = 3 + 4j        # complex

print(c.real, c.imag)   # 3.0 4.0
print(abs(c))          # magnitude = 5.0

import math
print(math.floor(3.9))  # 3
print(math.ceil(3.1))   # 4
print(round(3.567, 2))  # 3.57
🎯 Exercise 31

Create a complex number and compute its magnitude, conjugate, and check if two complex numbers are equal.

Unit-II · Native Data Types

Lists

Intermediate Unit-II CO3

A list is an ordered, mutable collection that can hold items of different types. Lists allow duplicate elements.

lists.py
fruits = ["apple", "banana", "cherry"]

# Indexing & Slicing
print(fruits[0])          # apple
print(fruits[-1])         # cherry
print(fruits[0:2])        # ['apple', 'banana']

# Modifying
fruits.append("mango")
fruits.insert(1, "grape")
fruits.remove("banana")
popped = fruits.pop()

# Useful methods
nums = [3, 1, 4, 1, 5, 9]
nums.sort()
nums.reverse()
print(nums.count(1))   # 2
print(nums.index(5))   # position of 5
🎯 Exercise 32

Create a list of 10 numbers. Sort, reverse, find max/min, and use list comprehension to filter only even numbers.

Unit-II · Native Data Types

Tuples

Intermediate Unit-II CO3

A tuple is an ordered, immutable collection. Once created, elements cannot be added, removed, or changed. Tuples are faster than lists and are used for fixed data.

tuples.py
coords = (10, 20)
rgb = (255, 128, 0)

print(coords[0])      # 10
print(rgb[1:3])       # (128, 0)

# Unpacking
x, y = coords
print(x, y)           # 10 20

# Single element tuple — trailing comma required
single = (42,)
print(type(single))   # <class 'tuple'>

# Tuple methods
data = (1, 2, 2, 3)
print(data.count(2))  # 2
print(data.index(3))  # 3
🎯 Exercise 33

Create a tuple of student records (name, age, grade). Unpack and print each record. Try to modify a value and observe the error.

Unit-II · Native Data Types

Sets

Intermediate Unit-II CO3

A set is an unordered, mutable collection of unique elements. Duplicates are automatically removed. Sets support mathematical set operations.

sets.py
a = {1, 2, 3, 4, 2, 1}
print(a)              # {1, 2, 3, 4} — duplicates removed

a.add(5)
a.discard(2)         # safe remove (no error if missing)
a.remove(3)          # raises KeyError if missing

# Set operations
b = {3, 4, 5, 6}
print(a | b)          # Union
print(a & b)          # Intersection
print(a - b)          # Difference
print(a ^ b)          # Symmetric Difference
print(a.issubset(b))  # Subset check
🎯 Exercise 34

Given two lists of student names, use sets to find students who appear in both, only in the first, only in the second, and in either but not both.

Unit-II · Native Data Types

Dictionary

Intermediate Unit-II CO3

A dictionary is an ordered (Python 3.7+), mutable collection of key-value pairs. Keys must be unique and immutable.

dict_basics.py
student = {
    "name": "Alice",
    "age": 21,
    "grade": "A"
}

# Access
print(student["name"])        # Alice
print(student.get("age"))    # 21 (safe access)

# Modify
student["age"] = 22
student["city"] = "Delhi"    # add new key
del student["grade"]         # remove key

# Check key existence
print("name" in student)     # True
🎯 Exercise 35

Create a dictionary representing a product (name, price, stock). Update the price, add a "discount" key, and delete "stock". Print the final dictionary.

Unit-II · Native Data Types

Functions & Methods of Dictionary

Intermediate Unit-II CO3
MethodDescription
keys()Returns all keys as a view object
values()Returns all values as a view object
items()Returns key-value pairs as (key, value) tuples
get(key, default)Returns value or default if key missing
update(dict2)Merges another dictionary into this one
pop(key)Removes and returns the specified key's value
popitem()Removes and returns the last inserted pair
clear()Removes all items
copy()Returns a shallow copy
setdefault(key, val)Returns value if key exists, else inserts with val
fromkeys(seq, val)Creates dict from sequence of keys with same value
dict_methods.py
d = {"a": 1, "b": 2, "c": 3}
for key, val in d.items():
    print(f"{key} → {val}")

d.update({"d": 4, "e": 5})
removed = d.pop("a")
empty = dict.fromkeys(["x", "y"], 0)
print(empty)  # {'x': 0, 'y': 0}
🎯 Exercise 36

Create a word frequency counter: given a sentence, use a dictionary and setdefault() or get() to count how many times each word appears.

Unit-II · Native Data Types

Strings

Intermediate Unit-II CO3

A string is an immutable sequence of Unicode characters. Strings support a rich set of operations and methods.

strings.py
s = "Hello, Python World!"

# Indexing & Slicing
print(s[0])            # H
print(s[-6:])          # World!
print(s[::2])          # Hlo yhno ol!
print(s[::-1])         # Reversed string

# Case methods
print(s.upper())
print(s.lower())
print(s.title())
print(s.swapcase())

# Search methods
print(s.find("Python"))    # 7
print(s.count("l"))        # 3
print(s.startswith("Hello"))  # True

# Manipulation
print(s.replace("Python", "Code"))
print(s.split(","))
print(" | ".join(["a", "b", "c"]))
print("  hello  ".strip())
print(s.center(30, "*"))
🎯 Exercise 37

Write a program that takes a sentence, reverses each word individually (not the sentence), and prints the result in title case.

Unit-III · Python Functions

Functions

Intermediate Unit-III CO3

A function is a named, reusable block of code that performs a specific task. Functions are defined using the def keyword.

functions.py
# Basic function with default parameter
def greet(name="Guest"):
    """Greets the user by name."""
    print(f"Hello, {name}!")

greet()           # Hello, Guest!
greet("Alice")  # Hello, Alice!

# Function with return value
def add(a, b):
    return a + b

result = add(10, 5)
print(result)   # 15

# Function with *args (variable arguments)
def total(*nums):
    return sum(nums)

print(total(1, 2, 3, 4))  # 10

# Function with **kwargs
def profile(**info):
    for k, v in info.items():
        print(f"{k}: {v}")

profile(name="Bob", age=25)
🎯 Exercise 38

Write a function stats(*nums) that accepts any number of integers and returns a tuple of (min, max, sum, average).

Unit-III · Python Functions

Advantages of Functions

Intermediate Unit-III CO3
  • Code Reusability: Write once, use many times anywhere in the program.
  • Modularity: Break complex problems into smaller, manageable sub-problems.
  • Readability: Named functions make code self-documenting and easier to understand.
  • Easier Debugging: Test and fix individual functions independently.
  • Reduced Redundancy: Avoid writing duplicate logic in multiple places.
  • Abstraction: Hide implementation details — caller only needs to know what a function does, not how.
  • Maintainability: Change logic in one place and it updates everywhere it's called.
  • Testability: Functions can be unit tested in isolation.
reusability.py
def is_prime(n):
    if n < 2: return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0: return False
    return True

# Reused in multiple contexts:
primes = [x for x in range(100) if is_prime(x)]
print(primes)
🎯 Exercise 39

Write 3 separate functions: one to validate an email, one to validate a phone number, and one that calls both and prints a report. Demonstrate modularity.

Unit-III · Python Functions

Built-in Functions

Intermediate Unit-III CO3

Python ships with many built-in functions available without importing anything:

FunctionDescriptionExample
print()Output to consoleprint("Hi")
input()Read from stdininput("Enter: ")
len()Length of objectlen([1,2,3]) → 3
type()Return typetype(3.14) → float
int(),float(),str()Type conversionint("42") → 42
range()Generate integer sequencerange(1,6)
abs()Absolute valueabs(-7) → 7
max(),min()Max/Min valuemax(3,1,5) → 5
sum()Sum of iterablesum([1,2,3]) → 6
sorted()Returns sorted listsorted([3,1,2])
enumerate()Index + value pairsenumerate(["a","b"])
zip()Pairs from iterableszip([1,2],[3,4])
map()Apply function to iterablemap(str, [1,2,3])
filter()Filter iterable by functionfilter(is_even, lst)
🎯 Exercise 40

Use enumerate(), zip(), map(), and filter() each in a program working on a list of 10 numbers.

Unit-III · Python Functions

User Defined Functions

Intermediate Unit-III CO3

A user-defined function (UDF) is created by the programmer using the def keyword to solve a specific problem.

udf.py
# Function with positional arguments
def rectangle_area(length, width):
    return length * width

# Function with keyword arguments
def describe(name, age, city="Unknown"):
    return f"{name}, Age {age}, from {city}"

print(rectangle_area(5, 3))
print(describe("Alice", 25, city="Delhi"))

# Function returning multiple values
def min_max(lst):
    return min(lst), max(lst)

lo, hi = min_max([4, 2, 9, 1])
print(lo, hi)  # 1 9
🎯 Exercise 41

Write a UDF bmi(weight_kg, height_m) that returns the BMI value and category (Underweight / Normal / Overweight / Obese).

Unit-III · Python Functions

Anonymous Functions

Intermediate Unit-III CO3

An anonymous function (also called a lambda function) is a small, nameless function defined with the lambda keyword. Useful for short, one-expression functions.

Syntax: lambda arguments: expression

lambda.py
# Simple lambda
square = lambda x: x ** 2
print(square(5))   # 25

# Lambda with multiple args
add = lambda a, b: a + b
print(add(3, 4))   # 7

# Lambda with sorted() — sort by second element
pairs = [(1, 'b'), (3, 'a'), (2, 'c')]
pairs.sort(key=lambda p: p[1])
print(pairs)   # [(3, 'a'), (1, 'b'), (2, 'c')]

# Lambda with map() and filter()
nums = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, nums))
evens = list(filter(lambda x: x%2==0, nums))
print(squared, evens)
🎯 Exercise 42

Use a lambda with sorted() to sort a list of dictionaries by a key (e.g., sort students by their GPA descending).

Unit-III · Python Functions

Pass by Value Vs. Pass by Reference

Intermediate Unit-III CO3

Python uses Pass by Object Reference (also called "pass by assignment"). The behavior depends on whether the object is mutable or immutable:

  • Immutable types (int, str, float, tuple): Behave like pass-by-value — changes inside the function do not affect the original.
  • Mutable types (list, dict, set): Behave like pass-by-reference — changes inside the function affect the original object.
pass_by.py
# Immutable — original unchanged
def change_num(x):
    x = 999

n = 10
change_num(n)
print(n)   # 10 — unchanged

# Mutable — original IS changed
def append_item(lst):
    lst.append(99)

my_list = [1, 2, 3]
append_item(my_list)
print(my_list)  # [1, 2, 3, 99] — changed!

# To protect a list, pass a copy:
append_item(my_list.copy())
🎯 Exercise 43

Demonstrate the difference between passing a list and a tuple to a function that tries to modify them. Explain what happens and why.

Unit-III · Python Functions

Recursion

Intermediate Unit-III CO3

Recursion is when a function calls itself to solve a problem. Every recursive function must have:

  • Base Case: Condition that stops the recursion.
  • Recursive Case: The function calling itself with a simpler input.
recursion.py
# Factorial using recursion
def factorial(n):
    if n == 0 or n == 1:   # Base case
        return 1
    return n * factorial(n - 1)   # Recursive call

print(factorial(5))  # 120

# Fibonacci using recursion
def fib(n):
    if n <= 1: return n
    return fib(n-1) + fib(n-2)

print([fib(i) for i in range(10)])
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
🎯 Exercise 44

Write a recursive function to compute the sum of digits of a number. E.g., sum_digits(1234) returns 10.

Unit-III · Python Functions

Scope and Lifetime of Variables

Intermediate Unit-III CO3

The scope of a variable defines where in the program it can be accessed. Python uses the LEGB rule:

  • L — Local: Inside the current function.
  • E — Enclosing: Inside any enclosing functions (closures).
  • G — Global: At the top level of the module.
  • B — Built-in: Python's built-in namespace (e.g., print, len).
scope.py
x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)   # local
    inner()
    print(x)       # enclosing

outer()
print(x)           # global

# global keyword
counter = 0
def increment():
    global counter
    counter += 1

increment()
print(counter)   # 1

The lifetime of a local variable is the duration of the function call — it is created when the function is called and destroyed when it returns.

🎯 Exercise 45

Demonstrate all 4 LEGB scopes in a single program with nested functions. Show how global and nonlocal keywords change which scope is modified.

Unit-III · Python Modules

Module Definition

Intermediate Unit-III CO3

A module is a file containing Python definitions (functions, classes, variables) and statements. Any .py file is a module. Modules help organize code into logical, reusable units.

mathutils.py
# This file IS the module
PI = 3.14159

def circle_area(r):
    return PI * r * r

def square_area(s):
    return s * s

# This block only runs when executed directly
if __name__ == "__main__":
    print("Running mathutils directly")
    print(circle_area(5))

The special variable __name__ equals "__main__" when the file is run directly, but equals the module name when imported.

🎯 Exercise 46

Create a module greetings.py with functions for formal and informal greetings. Import and use it in a separate script.

Unit-III · Python Modules

Need of Modules

Intermediate Unit-III CO3

Modules solve critical software engineering problems:

  • Code Organization: Split large programs into manageable files.
  • Reusability: Write a function once, import it across multiple programs.
  • Namespace Management: Each module has its own namespace, preventing name conflicts.
  • Collaboration: Teams can work on different modules simultaneously.
  • Separation of Concerns: Keep database logic, UI logic, and business logic in separate modules.
  • Maintainability: Update one module without affecting others.
  • Testing: Test modules independently.

Without modules, a large program would be a single massive file — impossible to maintain.

🎯 Exercise 47

Explain how you would organize a student management system into 3–4 separate modules. Name each module and list what it would contain.

Unit-III · Python Modules

Creating a Module

Intermediate Unit-III CO3

Creating a module is as simple as saving Python code in a .py file:

converter.py
"""Unit Converter Module"""

KM_PER_MILE = 1.60934
KG_PER_POUND = 0.453592

def miles_to_km(miles):
    return miles * KM_PER_MILE

def pounds_to_kg(pounds):
    return pounds * KG_PER_POUND

def celsius_to_fahrenheit(c):
    return (c * 9/5) + 32
main.py
import converter
print(converter.miles_to_km(10))    # 16.0934
print(converter.celsius_to_fahrenheit(100))  # 212.0
🎯 Exercise 48

Create a module shapes.py with functions for area and perimeter of circle, rectangle, and triangle. Use it in a main program.

Unit-III · Python Modules

Importing Module

Intermediate Unit-III CO3

Python provides multiple ways to import modules:

import_styles.py
# 1. Import entire module
import math
print(math.pi)

# 2. Import specific names
from math import sqrt, factorial
print(sqrt(25))       # 5.0
print(factorial(5))  # 120

# 3. Import with alias
import numpy as np   # common convention
import pandas as pd  # common convention

# 4. Import all (generally discouraged)
from math import *

# 5. Import from a package
from os.path import join, exists
🎯 Exercise 49

Import the datetime module using all 4 styles shown above. Print today's date and time using each method.

Unit-III · Python Modules

Path Searching of a Module

Intermediate Unit-III CO3

When you run import module_name, Python searches for the module in this order:

  1. Built-in Modules: Standard library modules compiled into the interpreter (e.g., sys, os).
  2. Current Directory: The folder where the script is running.
  3. PYTHONPATH: A list of directories in the environment variable.
  4. Installation-Dependent Default: Standard library and site-packages.
path_search.py
import sys

# View the complete module search path
for path in sys.path:
    print(path)

# Add a custom directory to the path
sys.path.append("/my/custom/modules")

# Check where a module is loaded from
import math
print(math.__file__)  # Full path to math module
🎯 Exercise 50

Print your sys.path. Then create a module in a subdirectory, add that directory to sys.path, and import the module successfully.

Unit-III · Python Modules

Module Reloading

Intermediate Unit-III CO3

By default, Python imports a module only once per session. Subsequent import statements for the same module use the cached version from sys.modules. To force a re-import (e.g., after modifying the module file), use importlib.reload():

reload_demo.py
import importlib
import mymodule

# ... (you edit mymodule.py here) ...

importlib.reload(mymodule)   # Force fresh load
print(mymodule.some_function())

You can also check cached modules:

check_cache.py
import sys
print("math" in sys.modules)  # True after import math
print(sys.modules.keys())
🎯 Exercise 51

Create a simple module with a variable. Import it, print the variable. Modify the module file. Reload it and print again to see the updated value.

Unit-III · Python Modules

Standard Modules

Intermediate Unit-III CO3

Python's Standard Library contains hundreds of pre-built modules ready to use:

ModulePurposeExample
mathMathematical functionsmath.sqrt(16)
osOperating system interfaceos.getcwd()
sysSystem-specific parameterssys.argv
randomRandom number generationrandom.randint(1, 10)
datetimeDate and time handlingdatetime.date.today()
jsonJSON encoding/decodingjson.dumps(data)
reRegular expressionsre.findall(pattern, text)
collectionsSpecialized containersCounter(list)
itertoolsIterator building blocksitertools.chain()
functoolsHigher-order functionsfunctools.reduce()
🎯 Exercise 52

Use random to simulate rolling two dice 1000 times. Use collections.Counter to count how many times each sum appears.

Unit-III · Python Modules

Python Packages

Intermediate Unit-III CO3

A package is a directory containing multiple modules, organized hierarchically. It must contain a special file __init__.py (can be empty).

Package Structure
mypackage/
    __init__.py       ← makes it a package
    shapes.py         ← module 1
    converter.py      ← module 2
    utils/
        __init__.py
        validators.py ← sub-package module
using_package.py
from mypackage import shapes
from mypackage.utils import validators

shapes.circle_area(5)
validators.is_email("[email protected]")
🎯 Exercise 53

Create a package called school with sub-modules students.py and teachers.py. Each should have an add() and list_all() function. Import and test from a main script.

Unit-IV · Exception Handling

Exceptions

Advanced Unit-IV

An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. Unlike syntax errors (detected at parse time), exceptions occur at runtime.

When Python encounters an error at runtime, it creates an exception object. If unhandled, the program crashes and displays a traceback.

exception_demo.py
# This will raise a ZeroDivisionError
result = 10 / 0

# Traceback output:
# Traceback (most recent call last):
#   File "exception_demo.py", line 2, in module
# ZeroDivisionError: division by zero

All exceptions in Python are derived from the base class BaseException. The main hierarchy is:

  • BaseException
    • SystemExit, KeyboardInterrupt, GeneratorExit
    • Exception ← most exceptions inherit from this
      • ArithmeticError, LookupError, ValueError, etc.
🎯 Exercise 54

Deliberately trigger 5 different exceptions (ZeroDivisionError, TypeError, IndexError, KeyError, NameError) and read each traceback carefully.

Unit-IV · Exception Handling

Built-in Exceptions

Advanced Unit-IV

Python has many built-in exception types:

ExceptionRaised When
ZeroDivisionErrorDivision or modulo by zero
TypeErrorOperation on incompatible types
ValueErrorCorrect type but invalid value
IndexErrorSequence index out of range
KeyErrorDictionary key not found
AttributeErrorAttribute reference/assignment failure
NameErrorLocal or global name not found
FileNotFoundErrorFile/directory does not exist
ImportErrorModule import fails
MemoryErrorOperation ran out of memory
RecursionErrorMaximum recursion depth exceeded
StopIterationnext() called on exhausted iterator
OverflowErrorArithmetic result too large
RuntimeErrorGeneric error not covered by others
🎯 Exercise 55

Write a program that intentionally triggers 5 different built-in exceptions. Catch each one separately and print a helpful message explaining what went wrong.

Unit-IV · Exception Handling

Exception Handling

Advanced Unit-IV

Python handles exceptions using try-except-else-finally blocks:

exception_handling.py
try:
    num = int(input("Enter a number: "))
    result = 100 / num
except ZeroDivisionError:
    print("Cannot divide by zero!")
except ValueError:
    print("Please enter a valid integer!")
except Exception as e:
    print(f"Unexpected error: {e}")
else:
    # Runs ONLY if no exception occurred
    print(f"Result: {result}")
finally:
    # ALWAYS runs
    print("Program completed.")

You can also raise exceptions manually:

raise_demo.py
def set_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative")
    return age
🎯 Exercise 56

Write a safe division function that handles ZeroDivisionError, TypeError, and catches any other unexpected exception with a generic handler. Use finally to log every call.

Unit-IV · Exception Handling

User Defined Exceptions in Python

Advanced Unit-IV

You can create custom exceptions by subclassing the built-in Exception class. This allows you to define meaningful, application-specific errors.

custom_exceptions.py
# Define custom exceptions
class InsufficientFundsError(Exception):
    """Raised when bank balance is insufficient."""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        super().__init__(
            f"Cannot withdraw {amount}. Balance: {balance}"
        )

class InvalidAgeError(Exception):
    pass

# Use custom exception
def withdraw(balance, amount):
    if amount > balance:
        raise InsufficientFundsError(balance, amount)
    return balance - amount

try:
    withdraw(500, 800)
except InsufficientFundsError as e:
    print(f"Error: {e}")
🎯 Exercise 57

Create custom exceptions NegativeBalanceError, InvalidPINError, and DailyLimitExceededError for a banking system. Demonstrate raising and catching each one.

Unit-IV · File Management

Operations on Files

Advanced Unit-IV CO4

File management in Python starts with the open() function. Syntax: open(filename, mode, encoding)

ModeDescription
'r'Read — default. File must exist.
'w'Write — creates or overwrites file.
'a'Append — adds to end of file.
'x'Create — fails if file exists.
'rb'Read binary.
'wb'Write binary.
'r+'Read and write.

File attributes:

file_attrs.py
f = open("data.txt", "w", encoding="utf-8")
print(f.name)      # data.txt
print(f.mode)      # w
print(f.closed)    # False
f.close()
print(f.closed)    # True
🎯 Exercise 58

Open a file in write mode, write 5 lines of text, close it, then reopen in read mode and display its attributes (name, mode, encoding).

Unit-IV · File Management

read() & write() Methods

Advanced Unit-IV CO4
read_write.py
# WRITING
with open("notes.txt", "w") as f:
    f.write("Python is great!\n")
    f.write("File I/O is easy.\n")
    f.writelines(["Line 3\n", "Line 4\n"])

# READING — entire file
with open("notes.txt", "r") as f:
    content = f.read()       # entire file as string
    print(content)

# READING — line by line
with open("notes.txt") as f:
    line1 = f.readline()     # reads one line
    lines = f.readlines()    # reads all lines into list
    print(line1)
    print(lines)
💡 Best Practice
Always use with statements when working with files. It automatically closes the file even if an exception occurs — preventing resource leaks.
🎯 Exercise 59

Write a program that reads a text file and counts the number of lines, words, and characters in it. Use both read() and readlines().

Unit-IV · File Management

tell() & seek() Methods

Advanced Unit-IV CO4

These methods control the file pointer (read/write head position):

  • tell() — returns the current byte position of the file pointer.
  • seek(offset, whence) — moves the pointer. whence: 0=start, 1=current, 2=end.
tell_seek.py
with open("notes.txt", "r") as f:
    print(f.tell())       # 0 — at start

    data = f.read(10)    # read 10 bytes
    print(f.tell())       # 10

    f.seek(0)             # go back to start
    print(f.tell())       # 0

    f.seek(5)             # jump to byte 5
    word = f.read(6)     # read 6 bytes from pos 5
    print(word)

    f.seek(0, 2)          # jump to end of file
    print(f.tell())       # file size in bytes
🎯 Exercise 60

Write to a file, then use seek() and tell() to read only the 3rd and 4th words from the file without reading the whole content at once.

Unit-IV · File Management

Renaming & Deleting Files in Python

Advanced Unit-IV CO4

Use the os module to rename, delete, and manage files on the filesystem:

file_ops.py
import os

# Check if file exists before operating
if os.path.exists("old.txt"):
    os.rename("old.txt", "new.txt")    # rename
    print("Renamed successfully")

if os.path.exists("temp.txt"):
    os.remove("temp.txt")              # delete file
    print("Deleted successfully")

# Get file information
info = os.stat("new.txt")
print(f"Size: {info.st_size} bytes")

# Using shutil for more operations
import shutil
shutil.copy("new.txt", "backup.txt")   # copy
shutil.move("new.txt", "archive/")     # move
🎯 Exercise 61

Write a script that creates 5 files named file1.txt through file5.txt, writes data to each, renames them to doc1.txt etc., then deletes doc3.txt.

Unit-IV · File Management

Directories in Python

Advanced Unit-IV CO4

Use the os module to work with directories:

directories.py
import os

print(os.getcwd())           # Current working directory
os.chdir("C:/Users")         # Change directory

os.mkdir("new_folder")       # Create directory
os.makedirs("a/b/c")         # Create nested dirs

print(os.listdir("."))       # List directory contents

os.rmdir("new_folder")       # Remove empty directory

import shutil
shutil.rmtree("a")           # Remove directory and all contents

# Walk directory tree
for root, dirs, files in os.walk("."):
    for file in files:
        print(os.path.join(root, file))
🎯 Exercise 62

Write a program that creates a folder structure project/src/, project/docs/, creates files inside each, then uses os.walk() to list all files in the entire project tree.

Unit-IV · Classes & Objects

The Concept of OOP in Python

Advanced Unit-IV CO5

Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around objects and classes, rather than functions and logic alone.

The four pillars of OOP:

  • Encapsulation: Bundling data and methods that operate on that data within one unit (class). Restricts direct access to some components.
  • Abstraction: Hiding complex implementation details and showing only essential features.
  • Inheritance: A class (child) can inherit attributes and methods from another class (parent).
  • Polymorphism: Different classes can implement the same method differently.

Python is a fully object-oriented language — everything in Python is an object (integers, strings, functions, modules).

🎯 Exercise 63

Describe a real-world entity (e.g., a car) in OOP terms: identify its attributes (data) and methods (behaviors). Draw the class diagram.

Unit-IV · Classes & Objects

Designing Classes

Advanced Unit-IV CO5

A class is a blueprint/template defining attributes (data) and methods (behaviours). Defined using the class keyword:

designing_class.py
class BankAccount:
    """Represents a bank account."""

    bank_name = "Code Tutorium Bank"  # Class attribute

    def __init__(self, owner, balance=0):
        self.owner = owner       # Instance attribute
        self.__balance = balance # Private attribute

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return self.__balance

    def get_balance(self):
        return self.__balance

    def __str__(self):  # String representation
        return f"{self.owner}'s account: ₹{self.__balance}"
🎯 Exercise 64

Design a class Library with attributes for book list and methods to add, remove, search, and display books. Include a private attribute for book count.

Unit-IV · Classes & Objects

Creating Objects

Advanced Unit-IV CO5

An object is an instance of a class — a specific entity created from the class blueprint. Creating an object is called instantiation.

creating_objects.py
class Student:
    def __init__(self, name, roll, grade):
        self.name = name
        self.roll = roll
        self.grade = grade

    def display(self):
        print(f"Roll {self.roll}: {self.name} — Grade {self.grade}")

# Create objects (instantiation)
s1 = Student("Alice", 101, "A")
s2 = Student("Bob", 102, "B")
s3 = Student("Carol", 103, "A")

# Each object is independent
s1.display()
s2.display()

print(s1 is s2)    # False — different objects
print(type(s1))    # <class '__main__.Student'>
🎯 Exercise 65

Create a Car class and instantiate 3 different car objects. Store them in a list and iterate over them calling a display_info() method on each.

Unit-IV · Classes & Objects

Accessing Attributes

Advanced Unit-IV CO5

Attributes are accessed using the dot notation (object.attribute). Python provides built-in functions for attribute access:

access_attrs.py
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 30)

# Dot notation
print(p.name)             # Alice
print(p.age)              # 30

# Built-in attribute functions
print(getattr(p, "name"))         # Alice
print(getattr(p, "salary", 0))    # 0 (default if missing)
print(hasattr(p, "age"))          # True
print(hasattr(p, "email"))        # False

# Access class attribute via object
print(p.__class__.__name__)        # Person
print(p.__dict__)                  # {'name': 'Alice', 'age': 30}
🎯 Exercise 66

Create an object and use getattr(), hasattr(), and __dict__ to inspect its attributes dynamically without knowing the attribute names in advance.

Unit-IV · Classes & Objects

Editing Class Attributes

Advanced Unit-IV CO5

Attributes can be dynamically modified, added, or deleted at runtime:

edit_attrs.py
class Employee:
    company = "TechCorp"   # Class attribute
    def __init__(self, name):
        self.name = name

e1 = Employee("Alice")
e2 = Employee("Bob")

# Modify instance attribute
e1.name = "Alicia"
print(e1.name)    # Alicia
print(e2.name)    # Bob — unchanged

# Modify class attribute — affects ALL instances
Employee.company = "NewCorp"
print(e1.company) # NewCorp
print(e2.company) # NewCorp

# Add new attribute dynamically
setattr(e1, "salary", 50000)
print(e1.salary)  # 50000

# Delete attribute
delattr(e1, "salary")
del e2.name       # Alternative
🎯 Exercise 67

Create a Config class with class-level settings. Modify class attributes to update global config and instance attributes for per-object overrides. Show the difference.

Unit-IV · Classes & Objects

Built-in Class Attributes

Advanced Unit-IV CO5

Every Python class automatically has these built-in attributes:

AttributeDescription
__name__Name of the class as a string
__doc__Class documentation string (docstring)
__dict__Dictionary of class or instance namespace
__module__Module name where the class is defined
__bases__Tuple of base (parent) classes
__mro__Method Resolution Order tuple
builtin_attrs.py
class Animal:
    """Base class for all animals."""
    species = "Unknown"

class Dog(Animal):
    """Represents a dog."""
    def bark(self): pass

print(Dog.__name__)      # Dog
print(Dog.__doc__)       # Represents a dog.
print(Dog.__bases__)     # (<class 'Animal'>,)
print(Dog.__mro__)       # [Dog, Animal, object]
print(Dog.__module__)    # __main__
print(Dog.__dict__)      # {bark: ..., __doc__: ...}
🎯 Exercise 68

Create an inheritance chain (Animal → Mammal → Dog). Print __mro__, __bases__, and __dict__ for each class and explain the output.

Unit-IV · Classes & Objects

Garbage Collection

Advanced Unit-IV CO5

Garbage Collection (GC) is Python's automatic memory management system that frees memory occupied by objects that are no longer referenced.

Python uses two mechanisms:

  • Reference Counting: Every object tracks how many references point to it. When count reaches 0, memory is freed immediately.
  • Cyclic GC: Handles circular references (A references B, B references A) that reference counting alone cannot detect. The gc module manages this.
garbage.py
import gc
import sys

x = [1, 2, 3]
print(sys.getrefcount(x))  # 2 (x + getrefcount arg)

y = x    # ref count increases
print(sys.getrefcount(x))  # 3

del y    # ref count decreases
del x    # ref count → 0, memory freed

# Manual GC operations
gc.enable()
gc.disable()
gc.collect()               # Force garbage collection
print(gc.get_count())      # (gen0, gen1, gen2) counts
🎯 Exercise 69

Create two objects that reference each other (circular reference). Use the gc module to detect and collect them. Print the reference counts before and after collection.

Unit-IV · Classes & Objects

Destroying Objects

Advanced Unit-IV CO5

Objects are destroyed when their reference count drops to zero. You can define a destructor using the __del__() special method, which is called just before the object is removed from memory.

destructor.py
class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        print(f"Connection to '{db_name}' opened.")

    def query(self, sql):
        print(f"Running: {sql}")

    def __del__(self):
        print(f"Connection to '{self.db_name}' closed.")

# Object created
conn = DatabaseConnection("students_db")
conn.query("SELECT * FROM students")

# Explicit deletion — __del__ is called
del conn

# Objects also destroyed at program end

Important Notes:

  • __del__() is not guaranteed to be called at a specific time.
  • The preferred way to release resources is using the with statement (context managers).
  • Avoid complex logic in __del__() as it may cause unpredictable behavior.
🎯 Exercise 70

Create a FileHandler class with __init__ (opens file), write(), and __del__ (closes file). Use it to write data to a file and observe when the destructor is called.