Scenario based Question for python
UNIT 2
Scenario 1: Modeling a Bank Account
Q1: You want to create a BankAccount class where users can deposit, withdraw, and check their
balance. How would you design it?
Answer:
class BankAccount:
def __init__(self, account_holder, balance=0):
self.account_holder = account_holder
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"${amount} deposited. Current balance: ${self.balance}")
else:
print("Deposit amount must be positive.")
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
print(f"${amount} withdrawn. Current balance: ${self.balance}")
else:
print("Insufficient balance.")
def check_balance(self):
return f"Balance for {self.account_holder}: ${self.balance}"
# Example usage:
account = BankAccount("John Doe", 100)
account.deposit(50)
account.withdraw(30)
print(account.check_balance())
Scenario 2: Implementing a Student Class
Q2: How would you create a class Student that stores and retrieves details like name, roll
number, and marks in three subjects, and also calculates the average marks?
Answer:
python
CopyEdit
class Student:
def __init__(self, name, roll_number, marks):
self.name = name
self.roll_number = roll_number
self.marks = marks
def get_average_marks(self):
return sum(self.marks) / len(self.marks)
def display_details(self):
print(f"Student Name: {self.name}")
print(f"Roll Number: {self.roll_number}")
print(f"Marks: {self.marks}")
print(f"Average Marks: {self.get_average_marks():.2f}")
# Example usage:
student1 = Student("Alice", 101, [85, 90, 78])
student1.display_details()
Scenario 3: Inheritance in Python Classes
Q3: How would you extend a Vehicle class to create a Car class with additional properties like
fuel type and methods to display information?
Answer:
class Vehicle:
def __init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
def display_info(self):
print(f"Vehicle: {self.brand} {self.model}, Year: {self.year}")
class Car(Vehicle):
def __init__(self, brand, model, year, fuel_type):
super().__init__(brand, model, year)
self.fuel_type = fuel_type
def display_info(self):
super().display_info()
print(f"Fuel Type: {self.fuel_type}")
# Example usage:
my_car = Car("Toyota", "Corolla", 2020, "Petrol")
my_car.display_info()
Scenario 4: Library Book Management System
Q4: How would you design a Book class to represent books in a library with attributes like title,
author, and availability status? Add methods to lend and return books.
Answer:
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
self.is_available = True
def lend_book(self):
if self.is_available:
self.is_available = False
print(f"You've successfully borrowed '{self.title}' by
{self.author}.")
else:
print(f"Sorry, '{self.title}' is currently unavailable.")
def return_book(self):
self.is_available = True
print(f"'{self.title}' has been returned and is now available.")
def display_info(self):
status = "Available" if self.is_available else "Not Available"
print(f"Title: {self.title}, Author: {self.author}, Status:
{status}")
# Example usage:
book1 = Book("1984", "George Orwell")
book1.display_info()
book1.lend_book()
book1.display_info()
book1.return_book()
Scenario 5: E-commerce Product System
Q5: How would you implement a Product class to store product details like name, price, and
stock quantity, and allow users to buy products and check stock levels?
Answer:
class Product:
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def buy_product(self, quantity):
if quantity > self.stock:
print(f"Insufficient stock for '{self.name}'. Only {self.stock}
available.")
else:
self.stock -= quantity
print(f"{quantity} unit(s) of '{self.name}' purchased
successfully.")
def check_stock(self):
print(f"'{self.name}' stock level: {self.stock}")
# Example usage:
laptop = Product("Laptop", 1500, 10)
laptop.buy_product(3)
laptop.check_stock()
Scenario 6: Employee Management System with Inheritance
Q6: How would you design a base Employee class and extend it to create a Manager subclass
that has additional responsibilities?
Answer:
class Employee:
def __init__(self, name, position, salary):
self.name = name
self.position = position
self.salary = salary
def display_info(self):
print(f"Employee Name: {self.name}, Position: {self.position},
Salary: ${self.salary}")
class Manager(Employee):
def __init__(self, name, position, salary, team_size):
super().__init__(name, position, salary)
self.team_size = team_size
def display_info(self):
super().display_info()
print(f"Manages a team of {self.team_size} members")
# Example usage:
manager = Manager("John Smith", "Project Manager", 90000, 8)
manager.display_info()
Scenario 7: Creating a Shape Class Hierarchy
Q7: How would you implement a Shape class and extend it to create Circle and Rectangle
classes that calculate their areas?
Answer:
import math
class Shape:
def __init__(self):
pass
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
# Example usage:
circle = Circle(5)
rectangle = Rectangle(4, 6)
print(f"Circle area: {circle.area():.2f}")
print(f"Rectangle area: {rectangle.area()}")
Scenario 8: Default Constructor Usage
Question:
Imagine you're tasked with creating a class Person that simply displays "A person has been
created" whenever an instance of it is initialized. Write the appropriate code and explain how the
constructor works here.
Answer:
class Person:
def __init__(self):
print("A person has been created")
# Creating an instance of Person
person1 = Person()
Explanation:
The __init__ method is a special method in Python called the constructor.
It gets called automatically when a new instance of the class is created.
In this example, the constructor prints the message whenever an instance is created.
Scenario 9: Parameterized Constructor
Question:
You are building an application where each product must store its name and price upon creation.
Design a class Product with a constructor that accepts and assigns these two values.
Answer:
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def display_info(self):
print(f"Product Name: {self.name}, Price: ${self.price:.2f}")
# Creating an instance of Product
product1 = Product("Laptop", 1200.50)
product1.display_info()
Explanation:
The constructor __init__ takes two parameters, name and price, and assigns them to
instance variables.
When an instance of the Product class is created, the values are passed and stored
automatically.
Scenario 10: Constructor with Default Values
Question:
Create a class Car where the brand defaults to "Toyota" if no brand is provided during instance
creation.
Answer:
class Car:
def __init__(self, brand="Toyota"):
self.brand = brand
def display_brand(self):
print(f"Car brand: {self.brand}")
# Instances with and without brand
car1 = Car()
car2 = Car("Honda")
car1.display_brand()
car2.display_brand()
Explanation:
The constructor provides a default value "Toyota" for the brand parameter.
This allows creating instances without explicitly passing a brand name.
Scenario 11: Using Constructor for Validation
Question:
Write a class BankAccount that ensures the initial balance is not negative. Raise a ValueError if
the balance is invalid.
Answer:
class BankAccount:
def __init__(self, balance):
if balance < 0:
raise ValueError("Initial balance cannot be negative.")
self.balance = balance
def display_balance(self):
print(f"Account Balance: ${self.balance:.2f}")
# Creating instances with valid and invalid balance
try:
account1 = BankAccount(500)
account1.display_balance()
account2 = BankAccount(-100) # This will raise an error
except ValueError as e:
print(e)
Explanation:
The constructor checks if the balance is negative and raises a ValueError if so.
This demonstrates using constructors for validation during instance creation.
Scenario 12: Animal Sounds
Question:
Suppose you are developing an application that needs to support different types of animals, each
making unique sounds. How can polymorphism help in this situation?
Answer:
Polymorphism allows you to define a single interface (make_sound()) for different classes (Dog,
Cat, Cow, etc.). This enables calling the same method on different objects without knowing their
specific types.
Code Example:
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print("Woof! Woof!")
class Cat(Animal):
def make_sound(self):
print("Meow!")
class Cow(Animal):
def make_sound(self):
print("Moo!")
# Polymorphism in action
animals = [Dog(), Cat(), Cow()]
for animal in animals:
animal.make_sound()
Output:
CopyEdit
Woof! Woof!
Meow!
Moo!
Scenario 13: Shape Area Calculation
Question:
You are tasked with designing a system that calculates the area of different shapes (Circle,
Rectangle, Square). How would you use polymorphism to solve this problem efficiently?
Answer:
Define a common method area() in the base class Shape and override it in derived classes to
compute the respective shape's area.
import math
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
# Polymorphism in action
shapes = [Circle(5), Rectangle(4, 7), Square(3)]
for shape in shapes:
print(f"Area: {shape.area():.2f}")
Output:
makefile
CopyEdit
Area: 78.54
Area: 28.00
Area: 9.00
Scenario 14 : Evan is going to an amusement park with his family to enjoy the rides. He
sees that the rides go around in circles, squares and rectangles. Calculate the real time
circumstance by calculating the area with the help of a python program.
# define a function for calculating
# the area of a shapes
def calculate_area(name):\
# converting all characters
# into lower cases
name = name.lower()
# check for the conditions
if name == "rectangle":
l = int(input("Enter rectangle's length: "))
b = int(input("Enter rectangle's breadth: "))
# calculate area of rectangle
rect_area = l * b
print(f"The area of rectangle is
{rect_area}.")
elif name == "square":
s = int(input("Enter square's side length: "))
# calculate area of square
sqt_area = s * s
print(f"The area of square is
{sqt_area}.")
elif name == "triangle":
h = int(input("Enter triangle's height length: "))
b = int(input("Enter triangle's breadth length: "))
# calculate area of triangle
tri_area = 0.5 * b * h
print(f"The area of triangle is
{tri_area}.")
elif name == "circle":
r = int(input("Enter circle's radius length: "))
pi = 3.14
# calculate area of circle
circ_area = pi * r * r
print(f"The area of circle is
{circ_area}.")
elif name == 'parallelogram':
b = int(input("Enter parallelogram's base length: "))
h = int(input("Enter parallelogram's height length: "))
# calculate area of parallelogram
para_area = b * h
print(f"The area of parallelogram is
{para_area}.")
else:
print("Sorry! This shape is not available")
# driver code
if __name__ == "__main__" :
print("Calculate Shape Area")
shape_name = input("Enter the name of shape whose area you want to find: ")
# function calling
calculate_area(shape_name)
Output
Calculate Shape Area
Enter the name of shape whose area you want to find: rectangle
Enter rectangle's length: 10
Enter rectangle's breadth: 15
The area of rectangle is 150.
Scenario 15: An Electronic Medical Record (EMR) is required by nurses and patients for
analysis of data. Use Python Programming for creating the same using a class patient.
class Patient():
# init method or constructor
def __init__(self, name, category):
self.name = name
self.category= category
def show(self):
print("Name is", self.name )
print(" Category is", self.category )
# both objects have different self which contain their attributes
Latha = Patient("Latha", "Female")
Ravi = Patient("Ravi", "Male")
Latha.show()
Ravi.show()
print("Name is ",Latha.Female)
print("Category is ",Ravi.Male)
Output
Name is Latha
Category is Female
Name is Ravi
Category is Male
Scenario 16: Anu has bought a new car and wants to know the specifications of it. Use the
concept of parameterized constructor and display the output.
class Car:
def __init__(self, make, model, year):
#Initialize the Car with specific attributes.
self.make = make
self.model = model
self.year = year
# Creating an instance using the parameterized constructor
car = Car("Honda", "Civic", 2022)
print(car.make)
print(car.model)
print(car.year)
Output:
Honda
Civic
2022
Scenario 17: A pet shop has a cat and dog. By using the concept of polymorphism, write a
python program to identify their sounds.
class Animal:
def sound(self):
return "Some generic sound"
class Dog(Animal):
def sound(self):
return "Bark"
class Cat(Animal):
def sound(self):
return "Meow"
# Polymorphic behavior
animals = [Dog(), Cat(), Animal()]
for animal in animals:
print(animal.sound())
Output:
Bark
Meow
Some generic sound
Scenario 18: The class teacher wants to know the number of students in a class. Using the
concept of constructor to develop a python program to display the same.
class Student:
count = 0
def __init__(self):
Student.count = Student.count + 1
s1=Student()
s2=Student()
s3=Student()
print("The number of students:",Student.count)
Output:
The number of students: 3
Scenario 19: Rectangle Area Calculation with Different Inputs: Method Overloading
Simulation
In this example, we simulate method overloading by using default arguments. We have a
Rectangle class where we calculate the area based on two scenarios:
1. With the given length and width.
2. With a given side (for a square).
class Rectangle:
def __init__(self):
pass
# Simulating method overloading using default arguments
def calculate_area(self, length=None, width=None):
if length is not None and width is not None:
return length * width # Area of rectangle
elif length is not None:
return length * length # Area of square (side*side)
else:
return "Invalid input"
# Creating an object of Rectangle
rect = Rectangle()
# Calculating area of a rectangle
print(f"Area of rectangle (5x10): {rect.calculate_area(5, 10)}")
# Calculating area of a square
print(f"Area of square (side 4): {rect.calculate_area(4)}")
Output:
Area of rectangle (5x10): 50
Area of square (side 4): 16
Scenario 20: Addition of Numbers with Different Data Types: Overloading with
*args
In this example, we demonstrate how to handle multiple types of input for the addition operation.
The add_numbers method will sum numbers and strings (concatenate them).
Code:
class Adder:
def add_numbers(self, *args):
if all(isinstance(arg, (int, float)) for arg in args):
return sum(args) # Sum if all arguments are numbers
elif all(isinstance(arg, str) for arg in args):
return " ".join(args) # Concatenate if all arguments are strings
else:
return "Incompatible types"
# Creating an object of Adder
adder = Adder()
# Adding numbers
print(f"Sum of numbers (2, 3, 4): {adder.add_numbers(2, 3, 4)}")
# Concatenating strings
print(f"Concatenating strings ('Hello', 'World'): {adder.add_numbers('Hello',
'World')}")
# Mixed types case (will return error message)
print(f"Mixed types (2, 'apple'): {adder.add_numbers(2, 'apple')}")
Output:
Sum of numbers (2, 3, 4): 9
Concatenating strings ('Hello', 'World'): Hello World
Mixed types (2, 'apple'): Incompatible types
Scenario 21: Concatenate Different Data Types: Method Overloading Using
Default Arguments
In this scenario, we simulate method overloading to concatenate different types of arguments
(integers, floats, and strings).
Code:
class Concatenator:
def concatenate(self, *args):
result = ""
for arg in args:
result += str(arg) # Convert everything to string and
concatenate
return result
# Creating an object of Concatenator
concatenator = Concatenator()
# Concatenating string, integer, and float
print(f"Concatenated result: {concatenator.concatenate('Value:', 100,
3.14)}")
# Concatenating only strings
print(f"Concatenated result: {concatenator.concatenate('Hello', ' ',
'World')}")
Output:
Concatenated result: Value:1003.14
Concatenated result: Hello World
Scenario 22: Vehicle Speed Calculation: Simulate Method Overloading with
Different Argument Types
This example demonstrates overloading by simulating different calculation methods based on the
input: one for a vehicle speed based on distance and time, and another based on total time for a
round trip.
Code:
class Vehicle:
def calculate_speed(self, distance=None, time=None, round_trip=False):
if distance is not None and time is not None:
return distance / time # Speed = Distance / Time
elif round_trip:
return distance / (time * 2) # Round trip speed (assuming the
distance is for both ways)
else:
return "Invalid input"
# Creating an object of Vehicle
vehicle = Vehicle()
# Speed calculation for single trip
print(f"Speed for a trip (100 km, 2 hours): {vehicle.calculate_speed(100, 2)}
km/h")
# Speed calculation for round trip (100 km, 2 hours)
print(f"Speed for round trip (100 km, 2 hours): {vehicle.calculate_speed(100,
2, round_trip=True)} km/h")
Output:
Speed for a trip (100 km, 2 hours): 50.0 km/h
Speed for round trip (100 km, 2 hours): 25.0 km/h
Scenario 23: Bank Account Withdrawal: Method Overloading for Multiple
Withdrawal Methods
In this example, we simulate method overloading where a BankAccount class has multiple
withdraw methods for different conditions:
One method for regular withdrawal.
One method for overdraft withdrawal.
Code:
class BankAccount:
def __init__(self, balance):
self.balance = balance
# Simulate method overloading
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return f"Withdrew {amount}. Remaining balance: {self.balance}"
else:
return "Insufficient balance."
def withdraw(self, amount, overdraft=True):
if overdraft and (self.balance + 500 >= amount): # Allow overdraft
up to 500
self.balance -= amount
return f"Withdrew {amount} (Overdraft allowed). Remaining
balance: {self.balance}"
else:
return "Insufficient balance or overdraft limit exceeded."
# Creating an object of BankAccount
account = BankAccount(1000)
# Regular withdrawal
print(account.withdraw(200))
# Overdraft withdrawal
print(account.withdraw(1200, overdraft=True))
# Trying to exceed overdraft limit
print(account.withdraw(2000, overdraft=True))
Output:
Withdrew 200. Remaining balance: 800
Withdrew 1200 (Overdraft allowed). Remaining balance: -400
Insufficient balance or overdraft limit exceeded.
Scenario 24: Animal Sound: Method Overriding
In this example, we simulate a scenario with an animal class and subclasses for different types of
animals. Each subclass overrides the make_sound method to provide its specific sound.
Code:
# Base class Animal
class Animal:
def __init__(self, name):
self.name = name
# Method to be overridden
def make_sound(self):
raise NotImplementedError("Subclass must implement abstract method")
# Subclass Dog
class Dog(Animal):
def make_sound(self):
return f"{self.name} says: Woof!"
# Subclass Cat
class Cat(Animal):
def make_sound(self):
return f"{self.name} says: Meow!"
# Subclass Cow
class Cow(Animal):
def make_sound(self):
return f"{self.name} says: Moo!"
# Creating objects of each animal
dog = Dog("Buddy")
cat = Cat("Whiskers")
cow = Cow("Bessie")
# Calling make_sound method for each
print(dog.make_sound())
print(cat.make_sound())
print(cow.make_sound())
Output:
Buddy says: Woof!
Whiskers says: Meow!
Bessie says: Moo!
Scenario 25: Employee Salary Calculation: Method Overriding
In this example, we have a base class Employee and two derived classes FullTimeEmployee and
PartTimeEmployee. Each subclass overrides the calculate_salary method to compute salary
differently based on the employee type.
Code:
# Base class Employee
class Employee:
def __init__(self, name, base_salary):
self.name = name
self.base_salary = base_salary
# Method to be overridden
def calculate_salary(self):
return self.base_salary
# Subclass FullTimeEmployee
class FullTimeEmployee(Employee):
def __init__(self, name, base_salary, bonus):
super().__init__(name, base_salary)
self.bonus = bonus
# Overriding calculate_salary for full-time employees
def calculate_salary(self):
return self.base_salary + self.bonus
# Subclass PartTimeEmployee
class PartTimeEmployee(Employee):
def __init__(self, name, hourly_rate, hours_worked):
super().__init__(name, 0) # No base salary for part-time employees
self.hourly_rate = hourly_rate
self.hours_worked = hours_worked
# Overriding calculate_salary for part-time employees
def calculate_salary(self):
return self.hourly_rate * self.hours_worked
# Creating objects of each employee
full_time_employee = FullTimeEmployee("Alice", 50000, 5000)
part_time_employee = PartTimeEmployee("Bob", 20, 80)
# Calculating salary for each
print(f"Full-time Employee {full_time_employee.name} Salary:
{full_time_employee.calculate_salary()}")
print(f"Part-time Employee {part_time_employee.name} Salary:
{part_time_employee.calculate_salary()}")
Output:
Full-time Employee Alice Salary: 55000
Part-time Employee Bob Salary: 1600
Scenario 26: Bank Account Withdrawal: Method Overriding
In this example, we simulate a banking system with a BankAccount class as the base class, and
SavingAccount and CurrentAccount as subclasses. The withdraw method is overridden in
both subclasses to reflect the specific rules for each type of account.
Code:
# Base class BankAccount
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
return f"Withdrew {amount}. New balance is {self.balance}"
else:
return "Insufficient funds."
# Subclass SavingAccount
class SavingAccount(BankAccount):
def __init__(self, balance, interest_rate):
super().__init__(balance)
self.interest_rate = interest_rate
# Overriding withdraw to add a rule for withdrawal limits
def withdraw(self, amount):
if amount <= 1000:
return super().withdraw(amount) # Calling the base class method
else:
return "Cannot withdraw more than $1000 from a Saving Account."
# Subclass CurrentAccount
class CurrentAccount(BankAccount):
def __init__(self, balance, overdraft_limit):
super().__init__(balance)
self.overdraft_limit = overdraft_limit
# Overriding withdraw to allow overdraft
def withdraw(self, amount):
if amount <= self.balance + self.overdraft_limit:
self.balance -= amount
return f"Withdrew {amount}. New balance is {self.balance}"
else:
return "Insufficient funds and overdraft limit exceeded."
# Creating objects of each account
saving_account = SavingAccount(5000, 5)
current_account = CurrentAccount(2000, 1000)
# Performing withdrawals
print(saving_account.withdraw(1200)) # Should give an error
print(saving_account.withdraw(800)) # Should succeed
print(current_account.withdraw(2500)) # Should succeed (with overdraft)
print(current_account.withdraw(5000)) # Should fail (overdraft limit
reached)
Output:
Cannot withdraw more than $1000 from a Saving Account.
Withdrew 800. New balance is 4200
Withdrew 2500. New balance is -500
Insufficient funds and overdraft limit exceeded.
Scenario 27: Shape Area Calculation: Method Overriding
In this scenario, we have a Shape base class with a calculate_area method. Two subclasses,
Circle and Rectangle, override the calculate_area method to compute the area according to
the shape type.
Code:
import math
# Base class Shape
class Shape:
def __init__(self, name):
self.name = name
def calculate_area(self):
pass # This method will be overridden in derived classes
# Subclass Circle
class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def calculate_area(self):
return math.pi * self.radius ** 2
# Subclass Rectangle
class Rectangle(Shape):
def __init__(self, length, width):
super().__init__("Rectangle")
self.length = length
self.width = width
def calculate_area(self):
return self.length * self.width
# Creating objects of each shape
circle = Circle(5)
rectangle = Rectangle(10, 5)
# Displaying area of shapes
print(f"Area of {circle.name}: {circle.calculate_area():.2f}")
print(f"Area of {rectangle.name}: {rectangle.calculate_area()}")
Output:
Area of Circle: 78.54
Area of Rectangle: 50
Scenario 28: Employee Bonus Calculation: Method Overriding
In this example, we have an Employee base class that calculates a general bonus. The Manager
subclass overrides this method to apply a different bonus calculation for managers.
Code:
# Base class Employee
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def calculate_bonus(self):
return self.salary * 0.05 # 5% bonus for general employees
# Subclass Manager
class Manager(Employee):
def __init__(self, name, salary, team_size):
super().__init__(name, salary)
self.team_size = team_size
# Overriding calculate_bonus for managers
def calculate_bonus(self):
return self.salary * 0.10 + 1000 # 10% bonus + flat 1000 for
managers
# Creating objects of each class
employee = Employee("Alice", 50000)
manager = Manager("Bob", 80000, 10)
# Calculating bonus for both
print(f"Employee {employee.name} Bonus: {employee.calculate_bonus()}")
print(f"Manager {manager.name} Bonus: {manager.calculate_bonus()}")
Output:
Employee Alice Bonus: 2500.0
Manager Bob Bonus: 9000.0