OOP In Python
Shubham Kumar Gupta
Posted on February 15, 2023
OOP In Python
- OOP (Object Oriented Programming) in Python allows us to use objects to represent entities.
- Each object has its own attributes and methods derived from the Class it belongs to.
- Some examples of pre-existing classes in Python are Integer, Strings, Lists, Sets, Dictionary, etc.
- Whenever we are creating, for example, a new list in Python, we are actually creating an object of class List.
- The new list created has all the methods that are defined in List Class, for example, append, insert, sort, etc.
- We can create our own classes and objects in Python to build real-life applications
- Using OOPS allows us to organize, maintain and scale our code more efficiently.
- The four main pillars of OOP are Encapsulation, Inheritance, Abstraction, and Polymorphism.
Class and Objects
- An object is to represent an entity belonging to a particular Class.
- A class is a blueprint for creating objects in OOP.
- Classes have their own attributes and methods(functions) that can be accessed by objects belonging to that class.
- We can initialize the attributes of Class using init method (constructor).
class Dog: # class naming with PascalCase
# constructor
def __init__(self, name, age):
self.name = name # creating class attributes
self.age = age
def speak(self): # creating class methods
return f'My name is {self.name}, and I am {self.age} years old.'
bruno = Dog("Bruno", 9) # creating object
print(bruno.name) # accessing Class attribute from object
print(bruno.age)
print(bruno.speak()) # accessing Class method from object
Output:
- Bruno
- 9
- My name is Bruno, and I am 9 years old.
1. Encapsulation:
- Encapsulation allows us to hide the object's attributes and method from outside access.
- Python doesn't have encapsulation in the same sense as other OOP languages.
- Python doesn't have truly private or protected attributes and methods.
- Attributes and methods that are meant to be protected are prefixed with a single underscore: _
- However, they can still be accessed and modified using their names.
- Attributes and methods that are meant to be private are prefixed with a double underscore: __
- However, they can still be accessed and modified using name mangling.
- Also, both can still be accessed and modified using get and set methods.
class Dog:
def __init__(self, name, age):
self.__name = name # private attribute
self._age = age # protected attribute
def get_name(self): # get method
return self.__name
def set_name(self, name): # set method
self.__name = name
def get_age(self): # get method
return self._age
def set_age(self, age): # set method
self._age = age
def __show(self): # private method
return f"My name is {self.__name} and I am {self._age} years old."
def _speak(self): # protected method
return "WOOF!"
bruno = Dog("Bruno", 9)
bruno._Dog__name = "Shero" # modifying private attribute using name mangling
print(bruno._Dog__name) # accessing private attribute using name mangling
bruno.set_name("Cheems") # modifying private attribute using set method
print(bruno.get_name()) # accessing private attribute using get method
bruno._age = 6 # modifying protected attribute using its name
print(bruno._age) # accessing protected attribute using its name
bruno.set_age(3) # modifying protected attribute using set method
print(bruno.get_age()) # accessing protected attribute using get method
print(bruno._Dog__show()) # accessing private method using name mangling
print(bruno._speak()) # accessing protected method using it's name
Output:
- Shero
- Cheems
- 6
- 3
- My name is Cheems and I am 3 years old.
- WOOF!
2. Inheritance
- Inheritance allows us to create a new class (called 'child class') based on another class (called 'parent class').
- The child class inherits all the attributes and methods of the parent class.
- In addition, the child class it's own unique attributes and methods.
- There are several types of inheritance namely, single-level, multi-level, multiple, hierarchical, and hybrid.
class Pet:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print(f'My name is {self.name}, and I am {self.age} years old.')
class Cat(Pet): # inheriting parent class in child class
def speak(self): # accessing parent class attribute in child class by default
print("Meow!")
class Dog(Pet): # inheriting parent class in child class
def __init__(self, name, age, sport):
super().__init__(name, age) # accessing parent class attribute in child class using super
self.sport = sport # child class accessing its own attributes
def speak(self):
print(f'My favorite sport is {self.sport}.')
D = Dog("Bruno", 9, 'Football')
C = Cat("Missa", 6)
D.show() # accessing parent class method in child class
D.speak() # child class accessing its own attributes
C.show() # accessing parent class method in child class
C.speak() # child class accessing its own attributes
Output:
- My name is Bruno, and I am 9 years old.
- My favorite sport is Football.
- My name is Missa, and I am 6 years old.
- Meow!
3. Abstraction
- Abstraction allows us to hide classes and methods not necessary for the user.
- We can make an abstract class in python by setting the parent class of any class to ABC after importing it from abc (Abstract Class Bases).
- After that, we can create an abstract method using the @abstractmethod decorator.
- We can still access the non-abstract method of abstract classes.
from abc import ABC, abstractmethod
class PET(ABC): # create an abstract class
@abstractmethod # create an abstract method
def speak(self):
pass
def show(self):
print("I am a Pet.")
class Dog(PET):
def speak(self):
print("WOOF!")
class Cat(PET):
def speak(self):
print("Meow!")
bruno = Dog()
bruno.speak() # ignoring abstract method of abstract class
bruno.show() # non-abstract method of the abstract class still works
missa = Cat()
missa.speak() # ignoring abstract method of abstract class
missa.show() # non-abstract method of the abstract class still works
nemo = PET() # will throw an error because we cannot instantiate an abstract class.
Output:
- WOOF!
- I am a Pet.
- Meow!
- I am a Pet.
- Can't instantiate abstract class PET with abstract method speak
4. Polymorphism
- Polymorphism allows an object to take on many forms.
- Polymorphism in Python can be achieved in two ways: method over-riding and duck-typing.
A. Method Over-riding
Method overriding allows a child class to have a different definition of a method already defined in the parent class.
class Pet:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print(f'My name is {self.name} and I am {self.age} years old.')
class Fish(Pet):
pass
class Dog(Pet):
def speak(self): # over-riding parent's class method
print(f'WOOF! My name is {self.name} and I am {self.age} years old.')
nemo = Fish("Nemo", 2)
bruno = Dog("Bruno", 9)
nemo.speak() # parent's class method runs
bruno.speak() # child's class method runs
Output:
- My name is Nemo and I am 2 years old.
- WOOF! My name is Bruno and I am 9 years old.
B. Duck Typing
Duck Typing allows different types of classes to have the same method name with its own definition.
class Fish:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self): # method of first class
print(f'My name is {self.name} and I am {self.age} years old.')
class Dog:
def __init__(self, name, age, breed):
self.name = name
self.age = age
self.breed = breed
def speak(self): # method of second class with same name
print(f'WOOF! My name is {self.name} and I am {self.age} years old, and I am a {self.breed}.')
nemo = Fish("Nemo", 2)
bruno = Dog("Bruno", 9, "Shiba Inu")
nemo.speak() # method of first class runs
bruno.speak() # method of the second class with the same name runs
Output:
- My name is Nemo and I am 2 years old.
- WOOF! My name is Bruno and I am 9 years old, and I am a Shiba Inu.
Dunder/Magic Methods:
- Dunder or magic methods are special methods used in Python classes.
- They are used to define how objects of classes behave in case they are used with in-built Python operations.
- Some commonly used dunder methods are init(self,...), str(self), repr(self), len(self), ads(self), del(self), etc.
- Dunder methods cannot be called, they run automatically when called by in-built python functions.
class SimpleClass:
# constructor
def __init__(self, value1, value2):
self.value1 = value1
self.value2 = value2
# string representation of the object
def __str__(self):
return f'value 1 is {self.value1} and value 2 is {self.value2}.'
# string representation for debugging purposes
def __repr__(self):
return f'This is an object of the class SimpleClass'
# returns output when len() function is called
def __len__(self):
return 1
# returns the sum when + operator is called between two objects.
def __add__(self, other):
return (self.value1 + other.value1, self.value2 + other.value2)
def __del__(self):
print("object deleted")
a = SimpleClass(5, 10) # __init__ is called
b = SimpleClass(7, 9) # __init__ is called
print(a) # __str__ is called
print(repr(a)) # __repr__ is called
print(len(a)) # __len__ is called
print(a + b) # __add_ is called
Output:
- value 1 is 5 and value 2 is 10.
- This is an object of the class SimpleClass
- 1
- (12, 19)
REFERENCES
💖 💪 🙅 🚩
Shubham Kumar Gupta
Posted on February 15, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
privacy Caught in the Crunch My Journey from Snacks to 2 Million Exposed Users Privacy
November 30, 2024
devchallenge Submission for the DevCycle Feature Flag Challenge: Feature Flag Funhouse
November 30, 2024