Python Chapter 5 Notes by Ur Engineering Friend
Python Chapter 5 Notes by Ur Engineering Friend
In Python, classes are created using the class keyword followed by the name of the class.
Within the class definition, you can define attributes and methods for the class.
Here is an example:
class Car:
self.make = make
self.model = model
self.year = year
def get_info(self):
In this example, we have defined a Car class with three attributes (make, model, and year)
and one method (get_info). The __init__ method is a special method that is called when an
object of the class is created. It initializes the attributes of the class.
To create an object of the Car class, we can simply call the class with the required
arguments:
Now, my_car is an object of the Car class, and we can call its methods and access its
attributes:
Method Overloading
class Calculator:
return a
elif c is None:
return a + b
else:
return a + b + c
In this example, the add method can take one, two, or three arguments. If only one argument
is provided, it is returned as is. If two arguments are provided, they are added and the result is
returned. If three arguments are provided, they are all added and the result is returned.
class Calculator:
total = 0
total += num
return total
➢ In this example, the add method takes any number of arguments and adds them
together. You can call the method with one argument, two arguments, or any number
of arguments.
➢ Note that while these techniques can simulate method overloading, they don't provide
the same level of type safety and error checking as true method overloading in other
languages. It is important to write clear and well-documented code when using these
techniques to avoid confusion and errors.
Method Overloading
class Animal:
def make_sound(self):
class Cat(Animal):
def make_sound(self):
print("Meow")
class Dog(Animal):
def make_sound(self):
print("Woof")
my_cat = Cat()
my_dog = Dog()
In this example, we have a base class Animal with a method make_sound. The Cat and Dog
classes inherit from the Animal class and override the make sound method with their own
implementations.
When we create an instance of Cat or Dog and call the make sound method, the
implementation from the subclass is used instead of the one from the parent class.
Data hiding
In Python, data hiding is a technique used to restrict the access to certain class attributes and
methods from outside the class. This is achieved by prefixing the attribute or method name
with two underscores (__).
class Person:
self.name = name
self.__age = age
def get_age(self):
return self.__age
self.__age = age
print(my_person.get_age()) # Output: 30
my_person.set_age(35)
print(my_person.get_age()) # Output: 35
Data Abstraction
In Python, data abstraction can be achieved using abstract classes and abstract methods. An
abstract class is a class that cannot be instantiated and has one or more abstract methods. An
abstract method is a method that does not have an implementation in the abstract class, but
must be implemented in any concrete subclass.
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
self.height = height
def area(self):
class Circle(Shape):
self.radius = radius
def area(self):
my_rectangle = Rectangle(3, 4)
print(my_rectangle.area()) # Output: 12
my_circle = Circle(5)
➢ In this example, we have an abstract class Shape with one abstract method area. This
method is implemented differently in the concrete subclasses Rectangle and Circle.
When we create instances of these subclasses and call the area method, we get the
area of the corresponding shape.
➢ Note that we cannot instantiate the abstract class Shape directly, because it has one or
more abstract methods that do not have an implementation. We must create a concrete
subclass that implements all the abstract methods before we can create an instance of
the class.
➢ Data abstraction can help you write more modular and maintainable code, by
separating the essential features of an object from the implementation details. It can
also help you enforce certain design patterns and prevent common errors, like
forgetting to implement a method in a subclass.
Inheritance
class Animal:
self.name = name
self.species = species
def make_sound(self):
class Cat(Animal):
super().__init__(name, species="cat")
self.breed = breed
def make_sound(self):
print("Meow")
Composition Class
In Python, composition is achieved by creating a new class that contains instances of other
classes as attributes.
Here is an example:
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine()
def start(self):
self.engine.start()
print("Car started")
my_car = Car()
➢ In this example, we have a class Engine that represents an engine, and a class Car that
represents a car. The Car class has an instance of the Engine class as an attribute.
When we create an instance of Car and call its start method, it calls the start method
of the Engine object first, and then prints "Car started".
➢ Composition can help you create complex objects by breaking them down into
simpler objects. It can also help you reuse existing code by creating objects that
contain other objects with useful functionality. Additionally, it can help you avoid the
pitfalls of inheritance, such as tight coupling and the fragile base class problem.
class Shape:
def area(self):
pass
class Rectangle(Shape):
self.width = width
self.height = height
def area(self):
class Circle(Shape):
self.radius = radius
def area(self):
my_rectangle = Rectangle(10, 5)
my_circle = Circle(7)
print(my_rectangle.area()) # Output: 50
➢ In this example, we have a superclass Shape with a method area that returns the area
of a shape. The subclass Rectangle overrides the area method to calculate the area of a
rectangle, and the subclass Circle overrides the area method to calculate the area of a
circle.
➢ When we create instances of Rectangle and Circle and call their area methods, we can
see that they behave differently, based on their specialized implementation of the area
method.
➢ This approach allows you to reuse the code of the superclass and customize it in the
subclasses. You can also create other subclasses of Shape and override its methods to
create other specialized behaviours.