Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
24 views10 pages

Python Oop

Uploaded by

mukesh.khanijo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views10 pages

Python Oop

Uploaded by

mukesh.khanijo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

================================================================================

PYTHON OBJECT-ORIENTED PROGRAMMING - MID-LEVEL DEVELOPER INTERVIEW QUESTIONS


================================================================================

Q1. CLASS AND OBJECT BASICS


---------------------------
Question: Create a simple BankAccount class with methods to deposit, withdraw, and
check balance.

Solution:
```python
class BankAccount:
def __init__(self, account_number, owner_name, initial_balance=0):
self.account_number = account_number
self.owner_name = owner_name
self.balance = initial_balance
self.transactions = []

def deposit(self, amount):


if amount > 0:
self.balance += amount
self.transactions.append(f"Deposit: +${amount}")
return True
return False

def withdraw(self, amount):


if amount > 0 and self.balance >= amount:
self.balance -= amount
self.transactions.append(f"Withdrawal: -${amount}")
return True
return False

def get_balance(self):
return self.balance

def get_transaction_history(self):
return self.transactions

# Usage
account = BankAccount("12345", "John Doe", 1000)
account.deposit(500)
account.withdraw(200)
print(f"Balance: ${account.get_balance()}")
print("Transactions:", account.get_transaction_history())
```

Q2. INHERITANCE
---------------
Question: Create a hierarchy of vehicles: Vehicle (base class), Car, and Motorcycle
(derived classes).

Solution:
```python
class Vehicle:
def __init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
self.is_running = False
def start_engine(self):
self.is_running = True
return f"{self.brand} {self.model} engine started"

def stop_engine(self):
self.is_running = False
return f"{self.brand} {self.model} engine stopped"

def get_info(self):
return f"{self.year} {self.brand} {self.model}"

class Car(Vehicle):
def __init__(self, brand, model, year, num_doors):
super().__init__(brand, model, year)
self.num_doors = num_doors

def get_info(self):
return f"{super().get_info()} - {self.num_doors} doors"

def honk(self):
return "Car horn: Beep! Beep!"

class Motorcycle(Vehicle):
def __init__(self, brand, model, year, engine_size):
super().__init__(brand, model, year)
self.engine_size = engine_size

def get_info(self):
return f"{super().get_info()} - {self.engine_size}cc"

def wheelie(self):
return "Motorcycle doing a wheelie!"

# Usage
car = Car("Toyota", "Camry", 2022, 4)
motorcycle = Motorcycle("Honda", "CBR600", 2021, 600)

print(car.get_info())
print(car.start_engine())
print(car.honk())

print(motorcycle.get_info())
print(motorcycle.start_engine())
print(motorcycle.wheelie())
```

Q3. ENCAPSULATION
-----------------
Question: Create a Student class with private attributes and public methods to
access them.

Solution:
```python
class Student:
def __init__(self, name, age, student_id):
self._name = name # Protected attribute
self._age = age # Protected attribute
self.__student_id = student_id # Private attribute
self.__grades = [] # Private attribute

# Getter methods
def get_name(self):
return self._name

def get_age(self):
return self._age

def get_student_id(self):
return self.__student_id

def get_grades(self):
return self.__grades.copy() # Return a copy to prevent modification

# Setter methods with validation


def set_name(self, name):
if isinstance(name, str) and len(name.strip()) > 0:
self._name = name.strip()
else:
raise ValueError("Name must be a non-empty string")

def set_age(self, age):


if isinstance(age, int) and 0 <= age <= 120:
self._age = age
else:
raise ValueError("Age must be between 0 and 120")

def add_grade(self, grade):


if isinstance(grade, (int, float)) and 0 <= grade <= 100:
self.__grades.append(grade)
else:
raise ValueError("Grade must be between 0 and 100")

def get_average_grade(self):
if not self.__grades:
return 0
return sum(self.__grades) / len(self.__grades)

# Usage
student = Student("Alice", 20, "S12345")
student.add_grade(85)
student.add_grade(92)
student.add_grade(78)

print(f"Name: {student.get_name()}")
print(f"Age: {student.get_age()}")
print(f"Student ID: {student.get_student_id()}")
print(f"Grades: {student.get_grades()}")
print(f"Average: {student.get_average_grade():.2f}")
```

Q4. POLYMORPHISM
----------------
Question: Create different shapes (Circle, Rectangle, Triangle) that can calculate
their area and perimeter.

Solution:
```python
from abc import ABC, abstractmethod
import math

class Shape(ABC):
@abstractmethod
def calculate_area(self):
pass

@abstractmethod
def calculate_perimeter(self):
pass

def get_info(self):
return f"{self.__class__.__name__} - Area: {self.calculate_area():.2f},
Perimeter: {self.calculate_perimeter():.2f}"

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def calculate_area(self):
return math.pi * self.radius ** 2

def calculate_perimeter(self):
return 2 * math.pi * self.radius

class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height

def calculate_area(self):
return self.width * self.height

def calculate_perimeter(self):
return 2 * (self.width + self.height)

class Triangle(Shape):
def __init__(self, side1, side2, side3):
self.side1 = side1
self.side2 = side2
self.side3 = side3

def calculate_area(self):
# Using Heron's formula
s = (self.side1 + self.side2 + self.side3) / 2
return math.sqrt(s * (s - self.side1) * (s - self.side2) * (s -
self.side3))

def calculate_perimeter(self):
return self.side1 + self.side2 + self.side3

# Usage - demonstrating polymorphism


shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 4, 5)
]
for shape in shapes:
print(shape.get_info())
```

Q5. STATIC METHODS AND CLASS METHODS


------------------------------------
Question: Create a MathUtils class with static and class methods for mathematical
operations.

Solution:
```python
class MathUtils:
PI = 3.14159

@staticmethod
def add(a, b):
return a + b

@staticmethod
def multiply(a, b):
return a * b

@staticmethod
def is_even(number):
return number % 2 == 0

@classmethod
def get_pi(cls):
return cls.PI

@classmethod
def circle_area(cls, radius):
return cls.PI * radius ** 2

@classmethod
def create_from_string(cls, number_string):
try:
return float(number_string)
except ValueError:
return None

# Usage
print(MathUtils.add(5, 3)) # 8
print(MathUtils.multiply(4, 7)) # 28
print(MathUtils.is_even(10)) # True
print(MathUtils.get_pi()) # 3.14159
print(MathUtils.circle_area(5)) # 78.53975
print(MathUtils.create_from_string("3.14")) # 3.14
```

Q6. PROPERTY DECORATORS


-----------------------
Question: Create a Temperature class that can convert between Celsius and
Fahrenheit using properties.

Solution:
```python
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius

@property
def celsius(self):
return self._celsius

@celsius.setter
def celsius(self, value):
self._celsius = value

@property
def fahrenheit(self):
return (self._celsius * 9/5) + 32

@fahrenheit.setter
def fahrenheit(self, value):
self._celsius = (value - 32) * 5/9

def __str__(self):
return f"{self._celsius}°C ({self.fahrenheit}°F)"

# Usage
temp = Temperature(25)
print(temp) # 25°C (77.0°F)

temp.fahrenheit = 100
print(temp) # 37.77777777777778°C (100.0°F)

temp.celsius = 0
print(temp) # 0°C (32.0°F)
```

Q7. SPECIAL METHODS (MAGIC METHODS)


-----------------------------------
Question: Create a Book class with special methods for string representation,
comparison, and arithmetic operations.

Solution:
```python
class Book:
def __init__(self, title, author, pages, price):
self.title = title
self.author = author
self.pages = pages
self.price = price

def __str__(self):
return f"'{self.title}' by {self.author}"

def __repr__(self):
return f"Book('{self.title}', '{self.author}', {self.pages}, {self.price})"

def __len__(self):
return self.pages

def __lt__(self, other):


return self.price < other.price

def __eq__(self, other):


return (self.title == other.title and
self.author == other.author and
self.pages == other.pages)

def __add__(self, other):


# Combine two books (create a collection)
return BookCollection([self, other])

def __contains__(self, item):


return item.lower() in self.title.lower() or item.lower() in
self.author.lower()

class BookCollection:
def __init__(self, books):
self.books = books

def __str__(self):
return f"Collection of {len(self.books)} books"

def total_pages(self):
return sum(book.pages for book in self.books)

# Usage
book1 = Book("Python Programming", "John Smith", 300, 29.99)
book2 = Book("Data Science", "Jane Doe", 250, 34.99)

print(str(book1)) # 'Python Programming' by John Smith


print(len(book1)) # 300
print(book1 < book2) # True
print("Python" in book1) # True

collection = book1 + book2


print(collection) # Collection of 2 books
print(collection.total_pages()) # 550
```

Q8. ERROR HANDLING IN CLASSES


-----------------------------
Question: Create a robust Calculator class with proper error handling.

Solution:
```python
class CalculatorError(Exception):
"""Custom exception for calculator errors"""
pass

class Calculator:
def __init__(self):
self.history = []

def add(self, a, b):


try:
result = float(a) + float(b)
self.history.append(f"{a} + {b} = {result}")
return result
except (ValueError, TypeError):
raise CalculatorError("Invalid input: both arguments must be numbers")

def subtract(self, a, b):


try:
result = float(a) - float(b)
self.history.append(f"{a} - {b} = {result}")
return result
except (ValueError, TypeError):
raise CalculatorError("Invalid input: both arguments must be numbers")

def multiply(self, a, b):


try:
result = float(a) * float(b)
self.history.append(f"{a} * {b} = {result}")
return result
except (ValueError, TypeError):
raise CalculatorError("Invalid input: both arguments must be numbers")

def divide(self, a, b):


try:
if float(b) == 0:
raise CalculatorError("Division by zero is not allowed")
result = float(a) / float(b)
self.history.append(f"{a} / {b} = {result}")
return result
except (ValueError, TypeError):
raise CalculatorError("Invalid input: both arguments must be numbers")

def get_history(self):
return self.history

def clear_history(self):
self.history.clear()

# Usage with error handling


calc = Calculator()

try:
print(calc.add(5, 3)) # 8.0
print(calc.multiply(4, 2.5)) # 10.0
print(calc.divide(10, 2)) # 5.0
print(calc.divide(5, 0)) # Raises CalculatorError
except CalculatorError as e:
print(f"Calculator error: {e}")

print("History:", calc.get_history())
```

PRACTICAL EXERCISES:
====================

Exercise 1: Library Management System


------------------------------------
```python
class Book:
def __init__(self, isbn, title, author, year):
self.isbn = isbn
self.title = title
self.author = author
self.year = year
self.is_borrowed = False
class Library:
def __init__(self):
self.books = {}
self.borrowers = {}

def add_book(self, book):


self.books[book.isbn] = book

def borrow_book(self, isbn, borrower_name):


if isbn in self.books:
book = self.books[isbn]
if not book.is_borrowed:
book.is_borrowed = True
if borrower_name not in self.borrowers:
self.borrowers[borrower_name] = []
self.borrowers[borrower_name].append(isbn)
return True
return False

def return_book(self, isbn):


if isbn in self.books:
book = self.books[isbn]
book.is_borrowed = False
# Remove from borrower's list
for borrower, books in self.borrowers.items():
if isbn in books:
books.remove(isbn)
return True
return False
```

Exercise 2: Bank Account with Interest


-------------------------------------
```python
class BankAccount:
def __init__(self, account_number, balance=0, interest_rate=0.01):
self.account_number = account_number
self.balance = balance
self.interest_rate = interest_rate

def add_interest(self):
interest = self.balance * self.interest_rate
self.balance += interest
return interest

class SavingsAccount(BankAccount):
def __init__(self, account_number, balance=0):
super().__init__(account_number, balance, 0.02) # Higher interest rate

def withdraw(self, amount):


if self.balance - amount >= 100: # Minimum balance requirement
self.balance -= amount
return True
return False
```

KEY CONCEPTS TO REMEMBER:


=========================
1. **Encapsulation**: Bundling data and methods that operate on that data
2. **Inheritance**: Creating new classes based on existing ones
3. **Polymorphism**: Using objects of different classes through a common interface
4. **Abstraction**: Hiding complex implementation details
5. **Composition**: Building complex objects from simpler ones
6. **Association**: Relationships between objects

BEST PRACTICES:
===============

1. Use meaningful class and method names


2. Keep classes focused on a single responsibility
3. Use inheritance for "is-a" relationships
4. Use composition for "has-a" relationships
5. Implement proper error handling
6. Use docstrings to document classes and methods
7. Follow PEP 8 naming conventions
8. Use properties for controlled access to attributes

You might also like