VTU Python Programming — Full Model Question Paper
Answers
Module 1 | Module 2 | Module 3 | Module 4 | Module 5
MODULE – 1
Q1a. Type Conversion in Python — Implicit vs Explicit
Type conversion refers to converting one data type to another. Python supports two types: Implicit and Explicit
conversion.
1. Implicit Type Conversion (Coercion)
Python automatically converts a smaller data type to a larger data type without any loss of data. The
programmer does not need to intervene.
# Implicit Conversion Example
x = 5 # int
y = 2.5 # float
z = x + y # Python auto-converts x to float
print(z) # Output: 7.5
print(type(z)) # <class 'float'>
2. Explicit Type Conversion (Type Casting)
The programmer manually converts data types using built-in functions like int(), float(), str(), list(), etc.
# Explicit Conversion Examples
a = '100'
b = int(a) # str to int => 100
c = float(a) # str to float => 100.0
d = str(123) # int to str => '123'
e = list('abc') # str to list => ['a','b','c']
print(b, c, d, e)
Differences: Implicit vs Explicit
• Implicit: Done automatically by Python | Explicit: Done manually by programmer
• Implicit: No risk of data loss | Explicit: May cause data loss (e.g., float→int truncates decimal)
• Implicit: Only lower→higher type | Explicit: Any compatible type conversion possible
Q1b. Fibonacci Sequence using While Loop
A Fibonacci sequence starts with 0 and 1, and each subsequent number is the sum of the previous two. The
program below displays the sequence up to n terms entered by the user.
n = int(input('Enter number of terms: '))
a, b = 0, 1
count = 0
print('Fibonacci Sequence:')
while count < n:
print(a, end=' ')
a, b = b, a + b
count += 1
# Output (n=7): 0 1 1 2 3 5 8
Here, 'a' and 'b' store the current and next Fibonacci numbers. The loop runs n times, printing and updating
values each iteration.
Q1c. Syntax Error vs Runtime Error
Syntax Error
A syntax error occurs when the code violates Python's grammar rules. It is detected before execution during the
parsing phase.
# Syntax Error Example
if True # SyntaxError: missing colon
print('Hello')
Runtime Error (Exception)
A runtime error occurs during program execution when a logically correct statement encounters an impossible
operation (e.g., division by zero, accessing undefined variable).
# Runtime Error Example
x = 10
y = 0
print(x / y) # ZeroDivisionError: division by zero
Key Difference: Syntax errors prevent the program from running at all, whereas runtime errors crash the
program only when the problematic line is executed.
Module 1 — OR (Q2)
Q2a. Collatz 3n+1 Sequence — Iteration and Conditionals
The Collatz conjecture states: take any positive integer n. If n is even, divide it by 2. If n is odd, multiply by 3 and
add 1. Repeat until n becomes 1.
def collatz(n):
print(n, end=' ')
while n != 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
print(n, end=' ')
num = int(input('Enter a positive integer: '))
collatz(num)
# Input: 6 => Output: 6 3 10 5 16 8 4 2 1
Iteration (while loop) keeps executing until n reaches 1. Conditional statements (if/else) decide the operation
based on whether n is even or odd.
Q2b. Print Numbers Divisible by 3 or 5 (not both) — 1 to 100
for i in range(1, 101):
div3 = (i % 3 == 0)
div5 = (i % 5 == 0)
if div3 or div5:
if div3 and div5: # divisible by BOTH → skip
continue
print(i, end=' ')
# Output: 3 5 6 9 10 12 18 20 21 24 25 ...
Q2c. Function Composition
Function composition means applying one function to the result of another. If f and g are functions, composition
is f(g(x)).
def double(x):
return x * 2
def add_one(x):
return x + 1
# Compose: apply add_one first, then double
def compose(f, g, x):
return f(g(x))
result = compose(double, add_one, 5)
print(result) # add_one(5)=6, double(6)=12
MODULE – 2
Q3a. String Operations: Slicing, Concatenation, Repetition, Comparison
1. Slicing
s = 'PythonProgramming'
print(s[0:6]) # 'Python' (index 0 to 5)
print(s[6:]) # 'Programming'
print(s[::-1]) # Reverse: 'gnimmargorPnohtyP'
2. Concatenation
s1 = 'Hello'
s2 = ' World'
print(s1 + s2) # 'Hello World'
3. Repetition
s = 'VTU'
print(s * 3) # 'VTUVTUVTU'
4. Comparison
print('apple' == 'apple') # True
print('abc' < 'abd') # True (lexicographic)
print('Python' > 'Java') # True
Q3b. Lists in Python — Definition, Difference from Arrays
A list is a mutable, ordered collection that can store elements of different data types. Unlike arrays (from the
array module), lists do not require homogeneous types and are built-in.
# Array: only one data type
# List: mixed types allowed
nums = [3, 6, 9, 12]
# Access third element (index 2)
print(nums[2]) # Output: 9
# List supports mixed types
mixed = [1, 'hello', 3.14, True]
print(mixed[1]) # Output: hello
Q3c. Count Number of Words in a Line of Text
line = input('Enter a line of text: ')
words = [Link]()
print('Number of words:', len(words))
# Example: 'Hello World from VTU'
# Output: Number of words: 4
Module 2 — OR (Q4)
Q4a. Mutability in Lists — Modify vs Clone
Lists are mutable — their content can be changed after creation. This can cause issues when two variables
point to the same list object.
Modifying a List
a = [1, 2, 3]
b = a # b references the SAME list
[Link](4)
print(a) # [1, 2, 3, 4] — a is also changed!
Creating a Clone (Copy)
a = [1, 2, 3]
b = a[:] # shallow copy using slicing
# OR: b = [Link]()
# OR: b = list(a)
[Link](4)
print(a) # [1, 2, 3] — a is unchanged
print(b) # [1, 2, 3, 4]
Q4b. Palindrome Check using Slicing
s = input('Enter a string: ').lower().strip()
if s == s[::-1]:
print(s, 'is a Palindrome')
else:
print(s, 'is NOT a Palindrome')
# 'madam' => Palindrome
# 'hello' => NOT a Palindrome
Q4c. Return New List with Only Even Numbers
def get_evens(numbers):
return [x for x in numbers if x % 2 == 0]
nums = [1, 2, 3, 4, 5, 6, 7, 8]
print(get_evens(nums)) # [2, 4, 6, 8]
MODULE – 3
Q5a. Word Frequency Counter using Dictionary
This program counts how often each word appears in a paragraph and displays the top 3 most frequent words.
paragraph = '''Python is a great language. Python is easy
to learn. Python is popular for data science and web'''
words = [Link]().split()
freq = {}
for word in words:
word = [Link]('.,!?')
freq[word] = [Link](word, 0) + 1
# Sort by frequency descending
sorted_freq = sorted([Link](), key=lambda x: x[1], reverse=True)
print('Top 3 most frequent words:')
for word, count in sorted_freq[:3]:
print(f'{word}: {count}')
# Output:
# python: 3
# is: 3
# a: 1
Q5b. Masking in NumPy
Masking in NumPy means using a Boolean array (True/False) to filter elements of an array. Elements where the
mask is True are selected; others are ignored.
import numpy as np
arr = [Link]([10, 25, 3, 47, 8, 60, 15])
# Create mask: elements greater than 20
mask = arr > 20
print('Mask:', mask)
# [False True False True False True False]
# Apply mask to filter array
filtered = arr[mask]
print('Filtered:', filtered) # [25 47 60]
# Direct one-liner
print(arr[arr % 2 == 0]) # Even elements: [10 8 60]
Q5c. 'with' Statement in File Handling
The 'with' statement automatically handles opening and closing of files. It ensures the file is properly closed
even if an exception occurs, preventing resource leaks.
# Writing to a file using 'with'
with open('[Link]', 'w') as f:
[Link]('Hello, VTU Students!\n')
[Link]('Python file handling is easy.')
# File is auto-closed when the block exits
# Reading from a file using 'with'
with open('[Link]', 'r') as f:
content = [Link]()
print(content)
# Output:
# Hello, VTU Students!
# Python file handling is easy.
Advantage: No need to explicitly call [Link](). The context manager handles it.
Module 3 — OR (Q6)
Q6a. Python Dictionaries — Features, Operations, and Differences from
Lists
A dictionary is an unordered (Python 3.7+ insertion-ordered) collection of key-value pairs. Keys must be unique
and immutable; values can be of any type.
Key Features
• Fast lookup using keys (hash table internally)
• Keys are unique; values can be duplicate
• Mutable — can insert, update, delete entries
Differences from Lists
• List: accessed by index (position); Dict: accessed by key (name)
• List: ordered sequence; Dict: key-value mapping
• List: [0], [1]...; Dict: d['name'], d['age']
Operations — Insertion, Deletion, Lookup
student = {}
# Insertion
student['name'] = 'Alice'
student['age'] = 20
student['marks'] = 85
# Lookup
print(student['name']) # Alice
print([Link]('age', 0)) # 20 (safe lookup)
# Deletion
del student['marks']
print(student) # {'name': 'Alice', 'age': 20}
# Iteration
for key, value in [Link]():
print(f'{key}: {value}')
Q6b. NumPy — 3x3 Random Matrix: Shape, Transpose, Mean
import numpy as np
# Create 3x3 matrix of random integers (1-100)
matrix = [Link](1, 100, size=(3, 3))
print('Matrix:\n', matrix)
# Shape
print('Shape:', [Link]) # (3, 3)
# Transpose
print('Transpose:\n', matrix.T)
# Mean of all elements
print('Mean:', [Link]())
# Sample Output:
# Matrix:
# [[34 72 15]
# [50 8 91]
# [23 67 44]]
# Shape: (3, 3)
# Transpose:
# [[34 50 23]
# [72 8 67]
# [15 91 44]]
# Mean: 44.89
Q6c. Binary Files vs Text Files
Text files store data as human-readable characters (encoded as ASCII or UTF-8). Binary files store raw bytes
and are not human-readable directly.
Text File Example
# Writing text file
with open('[Link]', 'w') as f:
[Link]('Hello VTU')
# Reading text file
with open('[Link]', 'r') as f:
print([Link]()) # Hello VTU
Binary File Example
# Writing binary file
with open('[Link]', 'wb') as f:
[Link](bytes([72, 101, 108, 108, 111]))
# Reading binary file
with open('[Link]', 'rb') as f:
data = [Link]()
print(data) # b'Hello'
print(list(data)) # [72, 101, 108, 108, 111]
Key Differences: Text files use newline translation and encoding; binary files skip these, making them faster and
suitable for images, audio, executables.
MODULE – 4
Q7a. Random and Time Modules — Stopwatch Simulation
Python's random module generates random numbers, and the time module provides time-related functions like
measuring elapsed time.
import random
import time
intervals = []
print('Simulated Stopwatch — Recording 5 time intervals')
for i in range(5):
duration = [Link](0.5, 2.0) # Random 0.5–2 sec
print(f'Interval {i+1}: sleeping {duration:.2f}s...')
start = [Link]()
[Link](duration)
elapsed = [Link]() - start
[Link](elapsed)
print(f' Elapsed: {elapsed:.4f}s')
avg = sum(intervals) / len(intervals)
print(f'Average elapsed time: {avg:.4f}s')
Q7b. Namespaces and LEGB Rule in Python
A namespace is a mapping from names (identifiers) to objects. Python resolves variable names using the LEGB
rule: Local → Enclosing → Global → Built-in.
x = 'Global' # Global scope
def outer():
x = 'Enclosing' # Enclosing scope
def inner():
x = 'Local' # Local scope
print(x) # Finds 'Local' first
inner()
print(x) # 'Enclosing'
outer()
print(x) # 'Global'
# LEGB Search order:
# 1. Local (innermost function)
# 2. Enclosing (outer function)
# 3. Global (module level)
# 4. Built-in (Python's built-ins: len, print, etc.)
Q7c. Class Attribute vs Instance Attribute
Class attributes are shared across all instances of the class. Instance attributes are unique to each object and
defined inside __init__.
class Student:
school = 'VTU' # Class attribute — shared
def __init__(self, name, marks):
[Link] = name # Instance attribute
[Link] = marks # Instance attribute
s1 = Student('Alice', 90)
s2 = Student('Bob', 75)
print([Link]) # VTU (class attribute)
print([Link]) # VTU (same for all)
print([Link]) # Alice (unique to s1)
print([Link]) # Bob (unique to s2)
# Change class attribute
[Link] = 'MIT'
print([Link]) # MIT — reflects change
Module 4 — OR (Q8)
Q8a. Module [Link] with square, cube, factorial
Step 1: Create [Link]
# [Link]
def square(n):
return n ** 2
def cube(n):
return n ** 3
def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
Step 2: Import all three variants in [Link]
# [Link]
# Import 1: import entire module
import utilities
print([Link](4)) # 16
# Import 2: import specific functions
from utilities import cube
print(cube(3)) # 27
# Import 3: import with alias
from utilities import factorial as fact
print(fact(5)) # 120
Q8b. Custom Module for Factorial and Binomial Coefficient
Step 1: [Link]
# [Link]
def factorial(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
Step 2: [Link] — Binomial Coefficient C(n,r)
# [Link]
from mathutils import factorial
def binomial(n, r):
if r > n:
return 0
return factorial(n) // (factorial(r) * factorial(n - r))
n = int(input('Enter n: '))
r = int(input('Enter r: '))
print(f'C({n},{r}) = {binomial(n, r)}')
# C(5,2) = 10
Q8c. 'is' vs '==' with Immutable Objects
'==' checks value equality; 'is' checks identity (whether two variables point to the SAME object in memory).
# With integers (small int caching in CPython)
a = 10
b = 10
print(a == b) # True (same value)
print(a is b) # True (CPython caches small ints)
# With strings
s1 = 'hello'
s2 = 'hello'
print(s1 == s2) # True (same value)
print(s1 is s2) # True (interned by CPython)
# With larger integers
x = 1000
y = 1000
print(x == y) # True
print(x is y) # False (not cached; different objects)
Rule: Always use '==' for value comparison. Use 'is' only to check against None, True, or False (e.g., if x is
None).
MODULE – 5
Q9a. Python Class Point — Sameness with 'is', Mutability
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x}, {self.y})'
p1 = Point(3, 4)
p2 = Point(3, 4)
p3 = p1 # p3 references the same object as p1
# 'is' checks identity (same object in memory)
print(p1 is p2) # False — different objects
print(p1 is p3) # True — same object
# Mutability demo
p3.x = 10 # Modifies through p3
print(p1.x) # 10 — p1 also changed (same object!)
print(p2.x) # 3 — p2 is unaffected
This demonstrates that 'is' compares object identity, and because p1 and p3 refer to the same object, modifying
through p3 also changes p1.
Q9b. Exception Handling — try, except, else, finally
Exception handling allows programs to respond to errors gracefully without crashing.
def safe_divide(a, b):
try:
result = a / b # Code that may raise exception
except ZeroDivisionError:
print('Error: Cannot divide by zero!')
except TypeError:
print('Error: Invalid types for division!')
else:
print(f'Result: {result}') # Runs only if no exception
finally:
print('--- Operation complete ---') # Always runs
safe_divide(10, 2) # Result: 5.0
safe_divide(10, 0) # Error: Cannot divide by zero!
safe_divide(10, 'x') # Error: Invalid types!
• try: block containing code that might raise an exception
• except: handles specific exceptions
• else: executes when no exception occurs
• finally: always executes (cleanup code)
Q9c. Operator Overloading using __add__()
Operator overloading lets us define custom behaviour for Python operators (+, -, *, etc.) for user-defined classes
by implementing special (dunder) methods.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other): # Overloads '+' operator
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f'Vector({self.x}, {self.y})'
v1 = Vector(1, 3)
v2 = Vector(4, 2)
v3 = v1 + v2 # Calls v1.__add__(v2)
print(v3) # Vector(5, 5)
Module 5 — OR (Q10)
Q10a. Polymorphism — Common Interface in Two Different Classes
Polymorphism means 'many forms'. The same method name works differently based on the object calling it.
This is achieved through method overriding.
class Dog:
def speak(self):
return 'Woof!'
class Cat:
def speak(self):
return 'Meow!'
class Duck:
def speak(self):
return 'Quack!'
# Common interface — same method name, different behaviour
animals = [Dog(), Cat(), Duck()]
for animal in animals:
print(type(animal).__name__, '->', [Link]())
# Output:
# Dog -> Woof!
# Cat -> Meow!
# Duck -> Quack!
The for loop uses the same speak() interface without knowing the specific type — this is the essence of
polymorphism.
Q10b. Pure Functions vs Modifiers — BankAccount Class
Pure Functions
A pure function returns a new value without modifying the original object. It has no side effects.
Modifiers
A modifier (mutator method) changes the state of the object in place.
class BankAccount:
def __init__(self, owner, balance=0):
[Link] = owner
[Link] = balance
# MODIFIER — changes object state
def deposit(self, amount):
[Link] += amount
print(f'Deposited {amount}. Balance: {[Link]}')
# MODIFIER — changes object state
def withdraw(self, amount):
if amount > [Link]:
print('Insufficient funds!')
else:
[Link] -= amount
print(f'Withdrawn {amount}. Balance: {[Link]}')
# PURE FUNCTION — returns value, no state change
def get_balance(self):
return [Link]
# PURE FUNCTION — returns new object
def transfer_preview(self, amount):
return BankAccount([Link], [Link] - amount)
acc = BankAccount('Alice', 1000)
[Link](500) # Modifier: balance → 1500
[Link](200) # Modifier: balance → 1300
print(acc.get_balance()) # Pure: returns 1300
Q10c. Role of finally Clause
The finally block always executes regardless of whether an exception occurred or not. It is used for cleanup
tasks such as closing files, releasing resources, or database connections.
def read_file(filename):
f = None
try:
f = open(filename, 'r')
data = [Link]()
print('File content:', data)
except FileNotFoundError:
print(f'Error: {filename} not found!')
finally:
if f:
[Link]() # Always close the file!
print('Execution complete (finally block ran)')
read_file('[Link]') # Opens and reads
read_file('[Link]') # Exception raised
# In BOTH cases, finally block executes
• finally executes whether or not an exception was raised
• finally executes even if a return statement is hit in try/except
• Ideal for cleanup: closing files, releasing locks, DB connections
Note: If both try and finally contain a return statement, finally's return takes precedence.