1. What is OOP?
OOP stands for Object-Oriented Programming, which is a programming paradigm that focuses on creating objects that encapsulate data and behavior. Python is an object-oriented programming language that fully supports the principles of OOP.
In OOP, everything is represented as an object, which is an instance of a class. A class is a blueprint for creating objects that defines the properties and methods of those objects. The properties of an object are represented by its attributes, which are variables that hold the data of the object. The behavior of an object is represented by its methods, which are functions that operate on the data of the object.
2. List the features and explain about different Object Oriented features supported by Python.
Python is an object-oriented programming language that supports various object-oriented features such as:
- Classes and Objects: A class is a blueprint for creating objects, which are instances of the class. Classes define attributes (data) and methods (functions) that are common to all instances of the class.
- Encapsulation: Encapsulation is the concept of restricting access to certain methods and attributes of an object. This is typically done by marking certain methods and attributes as private, which means they can only be accessed within the class.
- Inheritance: Inheritance allows defining a new class based on an existing class. The new class inherits all the attributes and methods of the existing class and can add new attributes and methods or override existing ones.
- Polymorphism: Polymorphism allows using objects of different classes interchangeably. This can be achieved through method overriding, where a subclass provides its own implementation of a method defined in its parent class, or method overloading, where a class has multiple methods with the same name but different arguments.
3. List and explain built in class attributes with example.
Built-in class attributes in Python are:
- name: The name of the class.
- doc: The documentation string of the class.
- module: The name of the module in which the class is defined.
- dict: A dictionary containing the class's namespace.
Example:
class MyClass:
"""This is my class."""
my_attribute = 42
print(MyClass.__name__) # Output: MyClass
print(MyClass.__doc__) # Output: This is my class.
print(MyClass.__module__) # Output: __main__
print(MyClass.__dict__) # Output: {'__module__': '__main__', '__doc__': 'This is my class.', 'my_attribute': 42}
4. Design a class that store the information of student and display the same.
Here's an example of a class in Python that stores information about a student and can display it:
class Student:
def __init__(self, name, roll_number, grade):
self.name = name
self.roll_number = roll_number
self.grade = grade
def display_info(self):
print("Name:", self.name)
print("Roll Number:", self.roll_number)
print("Grade:", self.grade)
# create a student object
my_student = Student("John Doe", 1234, "A+")
# display the student information
my_student.display_info()
In this example, we have a Student
class that takes in the name
, roll_number
, and grade
of a student as parameters in its constructor. We have a method called display_info
that prints out the student's information. We create a Student
object called my_student
with the given parameters and call the display_info
method to print out the student's information.
You can modify the class to add more attributes and methods to suit your needs.
5. What are basic overloading methods?
In Python, basic overloading methods are special methods that allow you to define how your objects behave with certain operators or built-in functions. The basic overloading methods in Python include:
__init__
: This is the constructor method that gets called when you create a new instance of the class. It initializes the object's attributes.__str__
: This method returns a string representation of the object when you use thestr()
function or print the object. It should return a human-readable description of the object.__repr__
: This method returns a string representation of the object when you use therepr()
function. It should return a string that, when evaluated, creates an equivalent object.__len__
: This method returns the length of the object when you use thelen()
function.__add__
: This method defines what happens when you use the+
operator with two objects. It should return a new object that is the sum of the two operands.__sub__
: This method defines what happens when you use the `` operator with two objects. It should return a new object that is the difference of the two operands.
Here's an example that demonstrates the use of some of these methods:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __len__(self):
return 2
# create two Vector objects
v1 = Vector(1, 2)
v2 = Vector(3, 4)
# use the + operator to add the two vectors
v3 = v1 + v2
print(v3)
# use the - operator to subtract the two vectors
v4 = v1 - v2
print(v4)
# use the len() function to get the length of the vector
print(len(v1))
In this example, we have a Vector
class that represents a two-dimensional vector. We define the __str__
, __add__
, __sub__
, and __len__
methods to allow us to print the object, add and subtract two vectors, and get the length of the vector. We create two Vector
objects v1
and v2
, and use the +
and -
operators to add and subtract them, respectively. We also use the len()
function to get the length of the vector.
6. What is method overriding? Write an example.
Method overriding is a concept in object-oriented programming where a subclass provides a different implementation for a method that is already defined in its parent class. This allows the subclass to customize the behavior of the inherited method without modifying the parent class.
Here's an example to illustrate method overriding in Python:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print("The animal makes a sound.")
class Dog(Animal):
def __init__(self, name):
super().__init__(name)
def speak(self):
print("The dog barks.")
class Cat(Animal):
def __init__(self, name):
super().__init__(name)
def speak(self):
print("The cat meows.")
# create animal objects
animal = Animal("Generic Animal")
dog = Dog("Fido")
cat = Cat("Whiskers")
# call the speak method on each object
animal.speak() # output: The animal makes a sound.
dog.speak() # output: The dog barks.
cat.speak() # output: The cat meows.
In this example, we have a parent class Animal
that has a speak
method that prints "The animal makes a sound." We define two subclasses Dog
and Cat
that inherit from Animal
. Both Dog
and Cat
have their own implementation of the speak
method that overrides the inherited method from Animal
.
We create three objects - animal
, dog
, and cat
- and call the speak
method on each object. When we call speak
on the animal
object, it uses the implementation defined in Animal
. However, when we call speak
on the dog
and cat
objects, they use their own implementations of the speak
method that were defined in their respective subclasses.
7. Explain class inheritance in Python with an example.
Class inheritance is a concept in object-oriented programming where a class (known as the subclass or child class) is derived from another class (known as the parent class or super class), and inherits its attributes and methods. The subclass can then customize and extend the behavior of the inherited attributes and methods, or add its own attributes and methods.
Here's an example to illustrate class inheritance in Python:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print("The animal makes a sound.")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def speak(self):
print("The dog barks.")
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name)
self.color = color
def speak(self):
print("The cat meows.")
# create animal objects
animal = Animal("Generic Animal")
dog = Dog("Fido", "Golden Retriever")
cat = Cat("Whiskers", "Grey")
# call the speak method on each object
animal.speak() # output: The animal makes a sound.
dog.speak() # output: The dog barks.
cat.speak() # output: The cat meows.
# print additional attributes of dog and cat objects
print(dog.breed) # output: Golden Retriever
print(cat.color) # output: Grey
In this example, we have a parent class Animal
that has an attribute name
and a method speak
that prints "The animal makes a sound." We define two subclasses Dog
and Cat
that inherit from Animal
.
Both Dog
and Cat
have their own implementation of the __init__
method that calls the parent class __init__
method using super()
, and sets their own additional attributes (breed
for Dog
and color
for Cat
).
Both Dog
and Cat
also have their own implementation of the speak
method that overrides the inherited method from Animal
.
We create three objects - animal
, dog
, and cat
- and call the speak
method on each object. When we call speak
on the animal
object, it uses the implementation defined in Animal
. However, when we call speak
on the dog
and cat
objects, they use their own implementations of the speak
method that were defined in their respective subclasses.
We also print out the additional attributes (breed
for dog
and color
for cat
) to demonstrate that each subclass can have its own set of attributes.
8. How to declare a constructor method in python? Explain.
In Python, a constructor method is a special method that gets called when an object is instantiated. The purpose of the constructor method is to initialize the object's attributes with some default values or with the values passed in during instantiation.
In Python, the constructor method is named __init__
(with two underscores before and after the word "init"). Here's an example of how to declare a constructor method in Python:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.speed = 0
def accelerate(self, amount):
self.speed += amount
def brake(self, amount):
self.speed -= amount
# create a Car object
my_car = Car("Toyota", "Corolla", 2021)
# print the attributes of the Car object
print(my_car.make) # output: Toyota
print(my_car.model) # output: Corolla
print(my_car.year) # output: 2021
print(my_car.speed) # output: 0
In this example, we define a class Car
that has a constructor method __init__
. The constructor takes three parameters make
, model
, and year
, which are used to initialize the make
, model
, and year
attributes of the object. We also initialize a speed
attribute to 0.
We define two methods accelerate
and brake
that update the speed
attribute of the object.
To create a Car
object, we call the class constructor method __init__
with the appropriate arguments. We store the resulting object in the variable my_car
.
Finally, we print the attributes of the my_car
object to verify that they have been initialized correctly.
9. How operator overloading can be implemented in Python? Give an example.
Operator overloading allows us to define how operators such as +
, -
, *
, /
, ==
, etc. behave when applied to objects of our custom classes. This allows us to use the operators with our objects just like we do with built-in types like integers and strings.
To implement operator overloading in Python, we need to define special methods that correspond to each operator. These methods have special names that start and end with two underscores. For example, to overload the +
operator, we need to define the __add__()
method.
Here is an example of implementing operator overloading in Python:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, other):
return Vector(self.x * other, self.y * other)
def __truediv__(self, other):
return Vector(self.x / other, self.y / other)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __str__(self):
return "({}, {})".format(self.x, self.y)
# create two Vector objects
v1 = Vector(1, 2)
v2 = Vector(3, 4)
# test operator overloading
v3 = v1 + v2
print(v3) # output: (4, 6)
v4 = v2 - v1
print(v4) # output: (2, 2)
v5 = v1 * 2
print(v5) # output: (2, 4)
v6 = v2 / 2
print(v6) # output: (1.5, 2.0)
print(v1 == v2) # output: False
print(v1 == Vector(1, 2)) # output: True
In this example, we define a Vector
class with attributes x
and y
. We overload several operators using the special methods __add__
, __sub__
, __mul__
, __truediv__
, __eq__
, and __str__
.
The __add__
method overloads the +
operator to allow adding two Vector objects. The __sub__
method overloads the -
operator to allow subtracting two Vector objects. The __mul__
method overloads the *
operator to allow multiplying a Vector object with a scalar. The __truediv__
method overloads the /
operator to allow dividing a Vector object by a scalar. The __eq__
method overloads the ==
operator to compare two Vector objects for equality. The __str__
method overloads the str()
function to allow printing the object in a human-readable format.
We create two Vector objects v1
and v2
and test the operator overloading with various arithmetic and comparison operations. The output of the program demonstrates that the overloaded operators work as expected.
10. Write a Python program to implement the concept of inheritance.
Here's an example Python program that implements the concept of inheritance:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def show_details(self):
print("Name:", self.name)
print("Age:", self.age)
class Student(Person):
def __init__(self, name, age, rollno, marks):
super().__init__(name, age)
self.rollno = rollno
self.marks = marks
def show_details(self):
super().show_details()
print("Roll Number:", self.rollno)
print("Marks:", self.marks)
# create a Student object
s = Student("John", 20, 1234, 90)
# call the show_details() method of Student object
s.show_details()
In this program, we define a Person
class with attributes name
and age
, and a method show_details()
that prints the person's details.
We also define a Student
class that inherits from Person
using the syntax class Student(Person):
. The Student
class has additional attributes rollno
and marks
, and overrides the show_details()
method of the Person
class to include the new attributes.
The super().__init__(name, age)
line in the Student
class constructor calls the constructor of the base class Person
to initialize the name
and age
attributes.
We then create a Student
object s
with name "John", age 20, roll number 1234, and marks 90. We call the show_details()
method of the Student
object s
which prints all the details of the student, including the inherited attributes name
and age
. The output of the program is:
Name: John
Age: 20
Roll Number: 1234
Marks: 90
This demonstrates how inheritance works in Python, where a child class can inherit attributes and methods from a parent class and also have its own unique attributes and methods.
11. Create a class employee with data members: name, department and salary. Create suitable methods for reading and printing employee information.
Here's an example Python program that creates a Employee
class with data members name
, department
and salary
, and methods for reading and printing employee information:
class Employee:
def __init__(self, name, department, salary):
self.name = name
self.department = department
self.salary = salary
def read_employee_info(self):
self.name = input("Enter employee name: ")
self.department = input("Enter employee department: ")
self.salary = float(input("Enter employee salary: "))
def print_employee_info(self):
print("Employee name:", self.name)
print("Employee department:", self.department)
print("Employee salary:", self.salary)
# create an Employee object
e = Employee("John Doe", "IT", 5000.0)
# call the print_employee_info() method of Employee object
e.print_employee_info()
# call the read_employee_info() method of Employee object
e.read_employee_info()
# call the print_employee_info() method of Employee object
e.print_employee_info()
In this program, we define a Employee
class with attributes name
, department
, and salary
, and methods read_employee_info()
and print_employee_info()
.
The __init__()
method is a constructor that initializes the name
, department
, and salary
attributes of the object.
The read_employee_info()
method reads employee information from the user using the input()
function and sets the object's attributes.
The print_employee_info()
method prints the object's attributes using the print()
function.
We then create an Employee
object e
with name "John Doe", department "IT", and salary 5000.0. We call the print_employee_info()
method of the Employee
object e
which prints the initial employee information.
We then call the read_employee_info()
method of the Employee
object e
to read new employee information from the user, and call the print_employee_info()
method of the Employee
object e
again to print the updated employee information.
The output of the program is:
Employee name: John Doe
Employee department: IT
Employee salary: 5000.0
Enter employee name: Jane Doe
Enter employee department: Sales
Enter employee salary: 6000.0
Employee name: Jane Doe
Employee department: Sales
Employee salary: 6000.0
This demonstrates how to create a class with data members and methods for reading and printing object information.
12. What is data abstraction? Explain in detail.
Data abstraction is a fundamental concept in object-oriented programming that allows us to focus on the essential features of an object, while hiding the implementation details. It is the process of creating abstract data types that only expose relevant information and operations, and hide the implementation details from the user.
Abstraction provides a way to simplify complex systems by breaking them down into smaller, more manageable parts. It allows us to represent complex objects in a simplified manner, making them easier to understand and work with.
In Python, data abstraction is achieved using classes and objects. A class is a blueprint for creating objects that defines the data and behavior of the objects. The data members of the class define the attributes or properties of the objects, while the member functions define the behavior or methods of the objects.
By encapsulating the data and behavior of objects in a class, we can abstract away the implementation details and expose only the essential features of the object. This makes it easier to work with the object and also makes the code more modular and reusable.
For example, consider a class Car
that represents a car object. The class may have data members like make
, model
, year
, color
, price
, etc. and methods like start
, stop
, accelerate
, brake
, etc. The user of the class only needs to know how to use the methods of the class to interact with the car object, and does not need to know how the car works internally.
Here is an example of a Car
class in Python that demonstrates data abstraction:
class Car:
def __init__(self, make, model, year, color, price):
self.make = make
self.model = model
self.year = year
self.color = color
self.price = price
def start(self):
print("Starting the car...")
def stop(self):
print("Stopping the car...")
def accelerate(self):
print("Accelerating the car...")
def brake(self):
print("Braking the car...")
In this example, the Car
class defines the data members make
, model
, year
, color
, and price
, which represent the attributes of a car object. It also defines methods start()
, stop()
, accelerate()
, and brake()
, which represent the behavior of a car object.
The user of the Car
class can create a car object by providing values for the data members:
my_car = Car("Honda", "Civic", 2019, "Red", 20000)
The user can then use the methods of the Car
class to interact with the car object, without needing to know how the car works internally:
my_car.start()
my_car.accelerate()
my_car.brake()
my_car.stop()
This example demonstrates how data abstraction allows us to focus on the essential features of an object, while hiding the implementation details, making it easier to work with the object and the code more modular and reusable.
13. Define the following terms:
1. Object
2. Class
3. Inheritance
4. Data abstraction.
- Object: In object-oriented programming, an object is an instance of a class that contains data members (attributes) and member functions (methods). An object is created from a class definition and can be manipulated using its methods.
- Class: A class is a blueprint or template for creating objects that define the data members (attributes) and member functions (methods) of the objects. It is a user-defined data type that encapsulates data and behavior. Classes provide a way to model real-world entities as objects in a program.
- Inheritance: Inheritance is a mechanism in object-oriented programming that allows a new class to be based on an existing class (called the base or parent class). The new class (called the derived or child class) inherits the properties and methods of the base class, and can also add new properties and methods or modify the existing ones. Inheritance allows code reuse, and facilitates the creation of new classes with similar functionality to existing classes.
- Data abstraction: Data abstraction is a fundamental concept in object-oriented programming that allows us to focus on the essential features of an object, while hiding the implementation details. It is the process of creating abstract data types that only expose relevant information and operations, and hide the implementation details from the user. Abstraction provides a way to simplify complex systems by breaking them down into smaller, more manageable parts, and allows us to represent complex objects in a simplified manner, making them easier to understand and work with.
14. Describe the term composition classes with example.
Composition is a concept in object-oriented programming where a class is composed of one or more objects of other classes, as opposed to inheritance where a class is derived from another class. In composition, the composed objects have an independent existence and are not a part of the class hierarchy.
For example, consider a Car class that is composed of an Engine object and a Wheel object. The Engine and Wheel classes are separate classes with their own properties and methods, and the Car class is composed of these objects to create a fully functional car.
class Engine:
def __init__(self, power):
self.power = power
def start(self):
print("Engine started.")
def stop(self):
print("Engine stopped.")
class Wheel:
def __init__(self, size):
self.size = size
def rotate(self):
print("Wheel rotating.")
class Car:
def __init__(self, engine_power, wheel_size):
self.engine = Engine(engine_power)
self.wheels = [Wheel(wheel_size) for i in range(4)]
def start(self):
self.engine.start()
for wheel in self.wheels:
wheel.rotate()
print("Car started.")
def stop(self):
self.engine.stop()
print("Car stopped.")
In this example, the Engine and Wheel classes are composed into the Car class. The Car class has an engine object and a list of wheel objects, and can start and stop the engine and wheels together to create a functioning car.
Composition allows for greater flexibility and reusability of code, as the composed objects can be used in other classes as well, and changes to the composed objects do not affect the class hierarchy.
15. Explain customization via inheritance specializing inherited methods.
Customization via inheritance is the process of modifying or specializing the behavior of inherited methods in a subclass to suit the requirements of the subclass. In other words, a subclass can override or extend the methods inherited from its parent class to provide its own implementation. This is a powerful feature of inheritance that allows subclasses to reuse the code of the parent class and customize it as needed.
For example, consider a Vehicle class that has a start method, which is inherited by its Car subclass. However, the Car subclass may need to start its engine in a different way than other types of vehicles. In this case, the Car subclass can override the start method of the Vehicle class with its own implementation.
class Vehicle:
def start(self):
print("Starting the vehicle.")
class Car(Vehicle):
def start(self):
print("Starting the car engine.")
In this example, the start method of the Vehicle class is overridden in the Car subclass with a new implementation that starts the car engine. When the start method is called on an instance of the Car class, it will execute the start method of the Car class instead of the one inherited from the Vehicle class.
Customization via inheritance allows for greater flexibility and code reuse in object-oriented programming, as subclasses can tailor the behavior of inherited methods to their own requirements while still inheriting the functionality of the parent class.