PANIMALAR ENGINEERING COLLEGE
(An Autonomous Institution, Affiliated to Anna University, Chennai)
ANSWER KEY
Name of the Course PROGRAMMING IN PYTHON
Course Code 23ES1206
Regulation 2023
Semester II
UNIT – II
FUNCTIONS AND STRINGS
PART A – 2 MARKS
Q1. [2 Marks] How do functions contribute to modular programming in Python?
Answer:
Functions divide programs into smaller, reusable modules. Advantages:
• Reusability – define once, call many times.
• Readability – clearer program structure.
• Maintainability – easier to debug and update.
Q2. [2 Marks] State the difference between user-defined and built-in function.
Answer:
Built-in functions: Pre-defined in Python (print(), len(), input(), range(), type()). Always available without import.
User-defined functions: Created by the programmer using the def keyword to perform specific tasks. Must be
defined before calling.
Q3. [2 Marks] Differentiate Global and local scope of a variable with an example.
Answer:
Global scope: Variable declared outside any function; accessible throughout the program.
Local scope: Variable declared inside a function; accessible only within that function.
x = 10 # global
def func():
y = 20 # local
print(x, y)
func() # prints 10 20
# print(y) # Error: y not defined outside
Q4. [2 Marks] What are default arguments? How do they help in reducing function call complexity?
Answer:
Default arguments have preset values used when the caller does not pass those arguments. They make
arguments optional and reduce the number of required parameters.
def greet(name, msg='Hello'):
print(msg, name)
greet('Alice') # Hello Alice
greet('Bob', 'Hi') # Hi Bob
Q5. [2 Marks] Justify when a lambda function is preferred over normal functions.
Answer:
Lambda functions (anonymous functions) are preferred when:
• A function is needed for a short duration (one-time use).
• Used as an argument to higher-order functions like map(), filter(), sorted().
• The function body is a single expression.
square = lambda x: x**2
print(square(5)) # 25
Q6. [2 Marks] What are positional arguments and keyword arguments?
Answer:
Positional arguments: Passed in order; position determines which parameter receives the value. Example:
func(10, 20)
Keyword arguments: Passed with parameter names; order doesn't matter. Example: func(b=20, a=10)
Q7. [2 Marks] What is string slicing? Give an example.
Answer:
String slicing extracts a portion (substring) of a string using the syntax: string[start:stop:step]
s = 'Python'
print(s[0:3]) # Pyt
print(s[::2]) # Pto
print(s[::-1]) # nohtyP (reverse)
Q8. [2 Marks] Define recursion with an example.
Answer:
Recursion is the process where a function calls itself to solve a smaller instance of the same problem. It must
have a base case to stop.
def factorial(n):
if n == 0: # base case
return 1
return n * factorial(n-1) # recursive call
print(factorial(5)) # 120
Q9. [2 Marks] What are negative indices in strings? Explain with an example.
Answer:
Negative indices count from the end of the string. Index -1 refers to the last character, -2 to second last, and so
on.
s = 'Python'
print(s[-1]) # n
print(s[-3:]) # hon
Q10. [2 Marks] What is the purpose of split() and strip() functions in strings?
Answer:
split(sep): Splits a string into a list at each separator. Default separator is whitespace.
strip(): Removes leading and trailing whitespace (or specified characters) from a string.
s = ' hello world '
print([Link]()) # 'hello world'
print([Link]().split()) # ['hello', 'world']
PART B – 13 MARKS
Q1. [13 Marks] Explain functions in Python. Program: compute power of a number.
Answer:
A function is a named, reusable block of code that performs a specific task. Defined with def keyword.
Advantages of functions:
• Modularity – breaks complex problem into parts.
• Code reuse – avoids repetition.
• Ease of testing – individual functions can be tested independently.
• Readability and maintainability.
Types: Built-in (print, len), User-defined, Lambda, Recursive.
Program – Power of a number:
def compute_power(base, exponent):
"""Returns base raised to the exponent."""
return base ** exponent
base = float(input('Enter base: '))
exp = float(input('Enter exponent: '))
result = compute_power(base, exp)
print(f'{base} ^ {exp} = {result}')
Q2. [7+6 Marks] i) Lambda functions ii) Fibonacci using lambda
Answer:
i) Lambda Functions:
A lambda function is an anonymous, inline function defined using the lambda keyword. Syntax: lambda
arguments: expression
Comparison with normal functions:
• Normal: uses def, can have multiple statements, has a name.
• Lambda: single expression, no name, used for short operations.
# Normal function
def add(a, b):
return a + b
# Lambda equivalent
add_lambda = lambda a, b: a + b
print(add(3, 4)) # 7
print(add_lambda(3, 4)) # 7
ii) Fibonacci using lambda:
fib = lambda n: n if n <= 1 else (lambda f: [f(f, i) for i in range(n)])(lambda f, i: i if
i <= 1 else f(f, i-1) + f(f, i-2))
# Simpler readable version:
from functools import reduce
n = int(input('Enter number of terms: '))
fib_series = [0, 1]
[fib_series.append(fib_series[-1] + fib_series[-2]) for _ in range(n-2)]
print('Fibonacci:', fib_series[:n])
Q3. [7+6 Marks] i) Recursion concept ii) Factorial using recursion
Answer:
i) Recursion:
Recursion occurs when a function calls itself. Every recursive function has:
• Base case – condition that stops recursion.
• Recursive case – function calls itself with a smaller problem.
Example – Sum of first n natural numbers:
def sum_n(n):
if n == 0:
return 0
return n + sum_n(n - 1)
Advantages: Elegant, easy to implement for tree/graph problems.
Disadvantage: Overhead of function calls; risk of stack overflow.
ii) Factorial using recursion:
def factorial(n):
if n < 0:
return 'Undefined'
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
n = int(input('Enter a number: '))
print(f'{n}! = {factorial(n)}')
Trace for factorial(4): 4*factorial(3) → 4*3*factorial(2) → 4*3*2*factorial(1) → 4*3*2*1 = 24
Q4. [7+6 Marks] i) String indexing and negative indices ii) Check symmetrical string
Answer:
i) String Indexing:
Each character in a string has a positive index (0 from start) and negative index (-1 from end).
s = 'PYTHON'
# Positive: P=0, Y=1, T=2, H=3, O=4, N=5
# Negative: P=-6,Y=-5,T=-4,H=-3,O=-2,N=-1
print(s[0]) # P
print(s[-1]) # N
print(s[1:4]) # YTH
print(s[-3:]) # HON
ii) Symmetrical String (reads same from both halves):
def is_symmetrical(s):
mid = len(s) // 2
return s[:mid] == s[len(s)-mid:][::-1]
word = input('Enter a string: ')
if is_symmetrical(word):
print(f'{word} is symmetrical')
else:
print(f'{word} is not symmetrical')
Q5. [7+6 Marks] i) String operations ii) Reverse, length, substring
Answer:
i) String Operations:
Formatting: f-strings, format() method.
name = 'Alice'; age = 20
print(f'Name: {name}, Age: {age}')
Comparison: Strings compared lexicographically using ==, !=, <, >.
Slicing: s[start:stop:step] — extracts substring.
ii) Program:
s = input('Enter a string: ')
# a) Reverse
reversed_s = s[::-1]
print('Reversed:', reversed_s)
# b) Length
print('Length:', len(s))
# c) Substring using slicing
start = int(input('Slice start index: '))
end = int(input('Slice end index: '))
print('Substring:', s[start:end])
Q6. [13 Marks] Regular Expressions in Python
Answer:
The re module provides support for regular expressions (regex) — patterns to match, search, and manipulate
strings.
Common functions:
• [Link](pattern, string) – searches for pattern anywhere in string.
• [Link](pattern, string) – matches pattern at start of string.
• [Link](pattern, string) – returns all matches as a list.
• [Link](pattern, replacement, string) – replaces matches.
• [Link](pattern) – compiles pattern for reuse.
Common patterns: \d = digit, \w = word char, \s = whitespace, . = any char, * = 0 or more, + = 1 or more.
import re
text = 'The price is 100 dollars and 50 cents'
# a) Search a pattern
match = [Link](r'\d+', text)
if match:
print('First number found:', [Link]())
# b) Replace a word
new_text = [Link](r'dollars', 'USD', text)
print('After replacement:', new_text)
# c) Find all numbers
numbers = [Link](r'\d+', text)
print('All numbers:', numbers)
Q7. [13 Marks] Evaluate the buggy function and fix it
Answer:
Given code has two errors:
• Missing colon after function definition: def add(a,b) should be def add(a,b):
• print(result) is outside the function (indentation error); result is a local variable.
i) Errors identified:
SyntaxError: Missing ':' in def statement. NameError/IndentationError: print(result) is outside function scope —
'result' is a local variable inaccessible outside.
ii) Function scope and return values:
Variables declared inside a function are local; they don't exist outside. To use a value outside, the function must
return it.
iii) Corrected version:
def add(a, b):
result = a + b
return result
output = add(5, 6)
print(output) # 11
PART C – 15 MARKS
Q1. [15 Marks] Menu-driven sorting with user-defined functions
Answer:
Using functions improves modularity (each sort is isolated), testability, and readability.
def bubble_sort(lst):
n = len(lst)
arr = [Link]()
for i in range(n-1):
for j in range(n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
def selection_sort(lst):
arr = [Link]()
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
def insertion_sort(lst):
arr = [Link]()
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and arr[j] > key:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
lst = list(map(int, input('Enter numbers separated by space: ').split()))
while True:
print('\n1. Bubble Sort 2. Selection Sort 3. Insertion Sort 4. Exit')
ch = int(input('Choice: '))
if ch == 1:
print('Bubble Sort:', bubble_sort(lst))
elif ch == 2:
print('Selection Sort:', selection_sort(lst))
elif ch == 3:
print('Insertion Sort:', insertion_sort(lst))
elif ch == 4:
break
Q2. [15 Marks] Regex to validate email and phone number
Answer:
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return [Link](pattern, email) is not None
def validate_phone(phone):
# Accepts: +91-XXXXXXXXXX or 10-digit number
pattern = r'^(\+91[-]?)?[6-9]\d{9}$'
return [Link](pattern, phone) is not None
while True:
print('\n1. Validate Email 2. Validate Phone 3. Exit')
ch = int(input('Choice: '))
if ch == 1:
email = input('Enter email: ')
print('Valid email' if validate_email(email) else 'Invalid email')
elif ch == 2:
phone = input('Enter phone number: ')
print('Valid phone' if validate_phone(phone) else 'Invalid phone number')
elif ch == 3:
break
Email pattern explanation: ^ = start, [a-zA-Z0-9._%+-]+ = local part, @ = literal @, domain + TLD, $ = end.
Q3. [15 Marks] String built-in methods with examples
Answer:
Python strings have many useful built-in methods:
• upper() / lower() – convert case: 'hello'.upper() → 'HELLO'
• title() – title case: 'hello world'.title() → 'Hello World'
• strip() / lstrip() / rstrip() – remove whitespace
• split(sep) – split into list: 'a,b,c'.split(',') → ['a','b','c']
• join(iterable) – join list: '-'.join(['a','b','c']) → 'a-b-c'
• replace(old,new) – 'hello'.replace('l','r') → 'herro'
• find(sub) – returns index of first occurrence (-1 if not found)
• count(sub) – counts occurrences: 'banana'.count('a') → 3
• startswith(s) / endswith(s) – returns True/False
• isdigit() / isalpha() / isalnum() – type checks
• center(w) / ljust(w) / rjust(w) – text alignment
• zfill(w) – pad with zeros: '42'.zfill(5) → '00042'
s = 'Hello, Python World!'
print([Link]()) # HELLO, PYTHON WORLD!
print([Link]()) # hello, python world!
print([Link]('o')) # 3
print([Link]('Python')) # 7
print([Link]('World','Universe')) # Hello, Python Universe!
print([Link](',')) # ['Hello', ' Python World!']
print([Link]('H')) # True
print([Link]('!')) # True
print(' spaces '.strip()) # 'spaces'
print('-'.join(['a','b','c'])) # a-b-c