Showing posts with label Python OOPS. Show all posts
Showing posts with label Python OOPS. Show all posts

Thursday, June 30, 2022

Abstraction in Python

Abstraction is one of the four fundamental OOPS concepts. The other three being-

What is Abstraction

Abstraction means hiding the complexity and only showing the essential features of the object. So in a way, Abstraction means hiding the real implementation and we, as a user, knowing only how to use it.

Real world example would be a vehicle which we drive with out caring or knowing what all is going underneath.

A TV set where we enjoy programs with out knowing the inner details of how TV works.

Abstraction in Python

Abstraction in Python is achieved by using abstract classes and interfaces.

An abstract class is a class that generally provides incomplete functionality and contains one or more abstract methods. Abstract methods are the methods that generally don’t have any implementation, it is left to the sub classes to provide implementation for the abstract methods.

Refer this post Abstract Class in Python to know more about abstract class in Python.

An interface should just provide the method names without method bodies. Subclasses should provide implementation for all the methods defined in an interface. Note that in Python there is no support for creating interfaces explicitly, you will have to use abstract class. In Python you can create an interface using abstract class. If you create an abstract class which contains only abstract methods that acts as an interface in Python.

Python abstraction example using abstract class

In the example there is an abstract class Payment that has an abstract method payment(). There are two child classes CreditCardPayment and MobileWalletPayment derived from Payment that implement the abstract method payment() as per their functionality.

As a user we are abstracted from that implementation when an object of CreditCardPayment is created and payment() method is invoked using that object, payment method of CreditCardPayment class is invoked. When an object of MobileWalletPayment is created and payment() method is invoked using that object, payment method of MobileWalletPayment class is invoked.

from abc import ABC, abstractmethod
class Payment(ABC):
  def print_slip(self, amount):
    print('Purchase of amount- ', amount)
  @abstractmethod
  def payment(self, amount):
    pass

class CreditCardPayment(Payment):
  def payment(self, amount):
    print('Credit card payment of- ', amount)

class MobileWalletPayment(Payment):
  def payment(self, amount):
    print('Mobile wallet payment of- ', amount)

obj = CreditCardPayment()
obj.payment(100)
obj.print_slip(100)
print(isinstance(obj, Payment))
obj = MobileWalletPayment()
obj.payment(200)
obj.print_slip(200)
print(isinstance(obj, Payment))

Output

Credit card payment of-  100
Purchase of amount-  100
True
Mobile wallet payment of-  200
Purchase of amount-  200
True

That's all for this topic Abstraction in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Method Overriding in Python
  2. Multiple Inheritance in Python
  3. Local, Nonlocal And Global Variables in Python
  4. pass Statement in Python
  5. Check if String Present in Another String in Python

You may also like-

  1. Name Mangling in Python
  2. Magic Methods in Python With Examples
  3. User-defined Exceptions in Python
  4. Convert String to int in Python
  5. Difference Between Encapsulation And Abstraction in Java
  6. Object Creation Using new Operator in Java
  7. Spring MVC Form Example With Bean Validation
  8. Uber Mode in Hadoop

Saturday, June 18, 2022

Operator Overloading in Python

In this post we’ll learn about Operator overloading in Python which is one of the OOPS concept like method overloading and method overriding. Operator overloading is an example of polymorphism as the same operator can perform different actions.

What is operator overloading

Operator overloading as evident from the name itself means the ability to overload the operator to provide extra functionality in addition to its real operational meaning. For example ‘+’ operator which is used with numbers to perform addition operation. But ‘+’ operator when used with two strings concatenate those Strings and merge two lists when used with lists in Python. It is possible because ‘+’ operator is overloaded in str and list class to provide extended functionality.


Python Operator overloading for ‘+’ operator

#using + operator with integers to add them
print(5 + 7)
#using + operator with Strings to concatenate them
print('hello ' + 'world')
a = [1, 2, 3]
b = [4, 5, 6]
# using + operator with List to concatenate them
print(a + b)

Output

12
hello world
[1, 2, 3, 4, 5, 6]

When is Operator overloading required

In the above example ‘+’ operator worked with Strings and Lists because it is already overloaded to provide that functionality for String and List. What if you want to use operator with custom objects. For example if you want to use ‘+’ operator with your custom class objects.

In the example there is a class Point with two variables x and y. Two objects of Point class are instantiated and you try to add those objects with the intention to add the data (p1.x + p2.x) and (p1.y + p2.y) of these two objects.

class Point:
  def __init__(self, x, y):
    self.x = x
    self.y = y

p1 = Point(1, 2)
p2 = Point(3, 4)

print(p1+p2) 

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 9, in <module>
    print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

As you can see trying to add two objects results in an error ‘unsupported operand type(s) for +’ because ‘+’ operator doesn’t know how to add these two objects.

What you want to do here is to add the data (p1.x + p2.x) and (p1.y + p2.y) of these two objects but that will require operator overloading as that is some extra functionality that you want ‘+’ operator to perform.

Operator overloading in Python

For all operators internally Python defines methods to provide functionality for those operators. For example functionality for ‘+’ operator is provide by special method __add__(). Whenever ‘+’ operator is used internally __add__() method is invoked to do the operation.

Internal methods that provide functionality for the operators are known as magic methods in Python. These magic methods are automatically invoked when corresponding operators are used.

When you want any operator to work with custom objects you need to override the corresponding special method that provides functionality for that operator.

Python Operator overloading example

In the example there is a class Point with two variables x and y. Two objects of Point class are instantiated and you try to add those objects with the intention to add the data (p1.x + p2.x) and (p1.y + p2.y) of these two objects. In order to successfully do that magic method __add__() has to be overridden in your class to provide that functionality.

Overloading ‘+’ operator to work with custom objects

class Point:
  def __init__(self, x, y):
    self.x = x
    self.y = y
  #overriding magic method
  def __add__(self, other):
    return self.x + other.x, self.y + other.y

p1 = Point(1, 2)
p2 = Point(3, 4)

print(p1+p2)

Output

(4, 6)

Magic methods in Python

Magic methods in Python are the methods prefixed with two underscores and suffixed with two underscores. These magic methods are also known as Dunders (Double UNDERscores) in Python. In this section magic methods for some of the important operators are listed.

Magic methods for arithmetic operators

Operator Magic Method Description
+__add__(self, other)Additive operator
-__sub__(self, other)Subtraction operator
*__mul__(self, other)Multiplication operator
/__truediv__(self, other)Division with fractional result
%__mod__(self, other)Remainder operator
//__floordiv__(self, other)Division with integer result, discarding any fractional part
**__pow__(self, other)Return a to the power b, for a and b numbers.
@__matmul__(self, other)Matrix Multiplication. Available from version 3.5

Magic methods for Comparison operators

Operator Magic Method Description
<__lt__(self, other)less than
<=__le__(self, other)less than or equal to
==__eq__(self, other)equal to
!=__ne__(self, other)not equal to
>__gt__(self, other)greater than
>=__ge___(self, other)greater than or equal to

Magic methods for compound assignment operators

Operator Magic Method Description
+=__iadd__(self, other)Addition assignment
–=__isub__(self, other)Subtraction assignment
*=__imul__(self, other)Multiplication assignment
/=__itruediv__(self, other)Division assignment
%=__imod__(self, other)Modulus assignment
//=__ifloordiv__(self, other)Division with integer result, discarding any fractional part
**=__ipow__(self, other)Return a to the power b, for a and b numbers.
@=__imatmul__(self, other)Matrix Multiplication. Available from version 3.5

Magic methods for unary operators

Operator Magic Method Description
+__pos__(self, other)Unary plus operator; indicates positive value
-__neg__(self, other)Unary minus operator; negates an expression
~__invert__(self, other)Returns the bitwise inverse of the number

Overloading ‘*’ operator in Python

class Point:
  def __init__(self, x):
    self.x = x
  #overriding magic method
  def __mul__(self, other):
    return self.x * other.x

p1 = Point(12)
p2 = Point(5)
print(p1*p2)

Output

60

Overloading comparison operator (>) in Python

class Person:
  def __init__(self, name, salary):
    self.name = name
    self.salary = salary
  #overriding magic method
  def __gt__(self, other):
    return self.salary > other.salary

obj1 = Person('John', 4500)
obj2 = Person('Natasha', 6000)
print(obj1.name, 'earns more than', obj2.name, '-', obj1 > obj2)

Output

John earns more than Natasha - False

That's all for this topic Operator Overloading in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Inheritance in Python
  2. Interface in Python
  3. self in Python
  4. Nonlocal Keyword in Python With Examples
  5. Python Conditional Statement - if, elif, else Statements

You may also like-

  1. Constructor in Python - __init__() function
  2. Accessing Characters in Python String
  3. Magic Methods in Python With Examples
  4. Python Program to Display Armstrong Numbers
  5. Java Reflection API Tutorial
  6. Java Concurrency Interview Questions And Answers
  7. Spring JdbcTemplate Insert, Update And Delete Example
  8. HDFS Commands Reference List

Monday, June 6, 2022

Interface in Python

Using interface you can specify what a class should do, but how class does it is not specified. So basically interface provides description of how an object should behave without actually providing that behavior implementation.

Interface in Python

An interface should just provide the method names without method bodies. Subclasses should provide implement for all the methods defined in an interface.

Unlike Java where a keyword ‘interface’ is provided for explicitly creating an interface in Python there is no such support for creating interfaces. If you are wondering why no such support in Python then you must know about "duck typing philosophy" of Python.

Python and duck typing

Python though strongly typed is also dynamically typed so the type of any object/field is implicitly assigned depending on where and how the field is used.

In Python focus is more on behavior of object rather than on its types. If you want to call a method on object there is no need to check the type of the object and there is no need to check whether that method really belongs to that object.

If there is an object that can fly and quack like a duck then it must be a duck, this is duck typing principle followed in Python. Let’s try to clarify it with an example-

class Duck:
  def sound(self):
    print('Quack Quack')

class Cat:
  def sound(self):
    print('Meow Meow')

class Human:
  def sound(self):
    print('Hey hello')

class Test:
  def invoke(self, obj):
    obj.sound();

t = Test()
obj = Duck()
t.invoke(obj)

obj = Cat()
t.invoke(obj)

obj = Human()
t.invoke(obj)

Output

Quack Quack
Meow Meow
Hey hello

When the object of type Cat is passed to the invoke() method and sound() method is called using that object, sound() method of class Cat is executed. When object of type Duck is passed to the invoke() method and sound() method is called using that object, sound() method of class Duck is executed and same for object of type Human.

Those coming from Java which is a strongly typed language where every variable must be declared with a data type, would appreciate this difference between these languages. In Java if you need run time polymorphism best way is to create an interface and have the classes implement it. Then use interface reference to hold the actual object reference at run time to get run time polymorphism. In Python being a dynamically typed language (as shown in the above example) you can say that you get the run time polymorphism inbuilt with in the language. That may be one of the reason to not have explicit interface keyword in Python to create an interface.

How to create interface in Python

You may have a requirement to create an API that should be followed by the developers for implementation, that is best served by creating an interface so now the question is how to create interface in Python?

In Python you can create an interface using abstract class. If you create an abstract class which contains only abstract methods that acts as an interface in Python.

Note that it is not possible to create an object of an interface. Subclasses have to implement all the abstract methods of an interface and objects of those subclasses can be created. Using interface gives that flexibility that each subclass can provide its own implementation of the interface methods.

Interface in Python example

An abstract class Payment is created which contains only abstract method payment (no concrete methods) to qualify as an interface.

Two classes CreditCardPayment and MobileWalletPayment implement the interface method as per their requirement. Based on the object correct payment method is invoked, using isinstance() method it is also checked whether both objects are of type Payment or not.

from abc import ABC, abstractmethod
class Payment(ABC):
  @abstractmethod
  def payment(self, amount):
    pass

class CreditCardPayment(Payment):
  def payment(self, amount):
    print('Credit card payment of- ', amount)

class MobileWalletPayment(Payment):
  def payment(self, amount):
    print('Mobile wallet payment of- ', amount)

obj = CreditCardPayment()
obj.payment(100)
print(isinstance(obj, Payment))
obj = MobileWalletPayment()
obj.payment(200)
print(isinstance(obj, Payment))

Output

Credit card payment of-  100
True
Mobile wallet payment of-  200
True

Abstract class Vs Interface in Python

As we have seen there is no explicit ‘interface’ keyword in Python for creating an interface. To create an interface in Python abstract class is used which has only abstract methods. Now the question is when to go for abstract class when for an interface.

In your design if you have a set of classes which share some common functionality and there is some functionality which varies then you can opt for an abstract class where you can have concrete methods for the common functionality shared by all the sub classes and abstract methods for functionality that varies giving sub classes a chance to implement those abstract methods as per their requirement.

If there are a set of classes that you want to relate in a class hierarchy even if how the functionality is implemented completely differs then you can go for an interface. That gives sub classes a chance to implement all the abstract methods as per their requirement.

That's all for this topic Interface in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Multiple Inheritance in Python
  2. Method Overriding in Python
  3. Constructor in Python - __init__() function
  4. Name Mangling in Python
  5. self in Python

You may also like-

  1. Strings in Python With Method Examples
  2. Tuple in Python With Examples
  3. Variable Length Arguments (*args), Keyword Varargs (**kwargs) in Python
  4. Python Program to Display Armstrong Numbers
  5. How to Read Excel File in Java Using Apache POI
  6. Association, Aggregation And Composition in Java
  7. ConcurrentHashMap in Java With Examples
  8. Autowiring in Spring Using @Autowired and @Inject Annotations

Sunday, June 5, 2022

Method Overriding in Python

Method overriding is an OOPS concept which provides ability to change the implementation of a method in a child class which is already defined in one of its super class. If there is a method in a super class and method having the same name and same number of arguments in a child class then the child class method is said to be overriding the parent class method.

Method overriding helps in hierarchical ordering where we move from general implementation in the super class to more specific implementation in the child classes.


Method overriding Python example

In the example there is a class Person with fields name and age and a child class Employee with an additional field empId. There is a method displayData in the Person class to display value of the fields. In the Employee class that method is overridden to display empId too.

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def displayData(self):
    print('In parent class displayData method')
    print(self.name)
    print(self.age)

class Employee(Person):
  def __init__(self, name, age, id):
    # calling constructor of super class
    super().__init__(name, age)
    self.empId = id

  def displayData(self):
    print('In child class displayData method')
    print(self.name)
    print(self.age)
    print(self.empId)

#Person class object
person = Person('John', 40)
person.displayData()
#Employee class object
emp = Employee('John', 40, 'E005')
emp.displayData()

Output

In parent class displayData method
John
40
In child class displayData method
John
40
E005

In the example when the displayData() method is called with Person class object, displayData() of the Person class is executed. When displayData() method is called with Employee class object, displayData() of the Employee class is executed. So the appropriate overridden method is called based on the object type, which is an example of Polymorphism.

Calling parent class overridden method from the child class

In the above example in the displayData() method of the child class same fields are printed again causing redundancy. It would be better to call the parent class displayData() method for printing name and age and print empId in the displayData() method of the child class.

To call the overridden method of the super class you can use of the following ways-

  1. Using ClassName.method(self)
  2. Using super()

Calling super class method using class name

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def displayData(self):
    print('In parent class displayData method')
    print(self.name)
    print(self.age)

class Employee(Person):
  def __init__(self, name, age, id):
    # calling constructor of super class
    super().__init__(name, age)
    self.empId = id

  def displayData(self):
    print('In child class displayData method')
    Person.displayData(self)
    print(self.empId)

#Employee class object
emp = Employee('John', 40, 'E005')
emp.displayData()

Output

In child class displayData method
In parent class displayData method
John
40
E005

Calling super class method using super()

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def displayData(self):
    print('In parent class displayData method')
    print(self.name)
    print(self.age)

class Employee(Person):
  def __init__(self, name, age, id):
    # calling constructor of super class
    super().__init__(name, age)
    self.empId = id

  def displayData(self):
    print('In child class displayData method')
    #calling super class method
    super().displayData()
    print(self.empId)

#Employee class object
emp = Employee('John', 40, 'E005')
emp.displayData()

Output

In child class displayData method
In parent class displayData method
John
40
E005

That's all for this topic Method Overriding in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Inheritance in Python
  2. Method Overloading in Python
  3. Name Mangling in Python
  4. Interface in Python
  5. Python break Statement With Examples

You may also like-

  1. Constructor in Python - __init__() function
  2. Python count() method - Counting Substrings
  3. Method Overriding in Java
  4. Difference Between Abstract Class And Interface in Java
  5. How HashSet Works Internally in Java
  6. Installing Hadoop on a Single Node Cluster in Pseudo-Distributed Mode
  7. Sending Email Using Spring Framework Example
  8. Dependency Injection in Spring Framework

Sunday, May 29, 2022

Inheritance in Python

Inheritance is one of the four fundamental OOPS concepts. The other three being-

What is inheritance

Inheritance is a mechanism, by which one class acquires, all the properties and behaviors of another class. The class whose members are inherited is called the Super class (or base class), and the class that inherits those members is called the Sub class (or derived class).


Syntax of inheritance in Python

In Python a derived class can inherit a base class using the following syntax.

class DerivedClass(BaseClass):

Benefits of inheritance

Using inheritance you can write hierarchical code where you move from generic code (in Parent class) to specific code (in child class).

Inheritance OOPS concept relates to removing redundancy and write reusable code. Let’s try to clear it with an example.

Python inheritance example

Suppose we have an Account class with fields name, accountNum and methods to withdraw and deposit. There is another class PrivilegedAccount which has the same fields as in Account and provides the same methods to withdraw and deposit. Apart from that privileged account also provides extra facility to schedule appointment. Using inheritance PrivilegedAccount can inherit fields and methods of Account class (reuse that functionality) and just have extra method for appointment scheduling facility.

class Account:
  def __init__(self, name, acct_num):
    self.name = name
    self.acct_num = acct_num

  def withdraw(self, amount):
    print('Withdrawing amount for ', self.acct_num)

  def deposit(self, amount):
    print('Depositing amount for ', self.acct_num)

class PrivilegedAccount(Account):
  def scheduleAppointment(self):
    print('Scheduling appointment for ', self.acct_num)

#PrivilegedAccount class object
pa = PrivilegedAccount('Ian', 1001)
pa.withdraw(100)
pa.deposit(500)
pa.scheduleAppointment()

Output

Withdrawing amount for  1001
Depositing amount for  1001
Scheduling appointment for  1001

In the example, object of PrivilegedAccount is created since it has inherited the methods of the Super class so withdraw and deposit methods can be called on the PrivilegedAccount class object.

Constructor overriding and method overriding with inheritance

When a class inherits another class in Python, constructor in the super class is also available by default to the child class. You may have some extra fields in the child class which you need to initialize in the child class thus you can override the constructor in the child class to initialize the fields there.

To change the implementation of an already defined method in super class you can override it in child class this concept is known as method overriding.

Suppose there is a class Person with fields name, age and there is a method displayData to display those fields. There is another class Employee with fields name, age, empId and there is a method displayData to display those fields. Employee class is almost similar to Person class except an additional field empId so Employee class reuses Person class by inheriting it.

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def displayData(self):
    print('In parent class displayData method')
    print(self.name)
    print(self.age)

class Employee(Person):
  def __init__(self, name, age, id):
    # calling constructor of super class
    super().__init__(name, age)
    self.empId = id

  def displayData(self):
    print('In child class displayData method')
    #calling super class method
    super().displayData()
    print(self.empId)

#Employee class object
emp = Employee('John', 40, 'E005')
emp.displayData()

Output

In child class displayData method
In parent class displayData method
John
40
E005

As you can see only the empId field is initialized in the __init__() function of the Employee class, for initializing the other two fields __init__() function of the Person class (Base class) is called using the super() method.

Method overriding is also used in this example where the parent class’ displayData() method is overridden in the child class. For calling the displayData() method of the parent class again super() is used.

Types of Inheritance

As per OOPS concepts there are 5 types of Inheritance.

Single Inheritance

In this type of inheritance a sub class is derived from a single Super class. We have already seen Python examples of single inheritance above.

Single Inheritance in Java

Multi-level inheritance

In multi-level inheritance, a subclass inherits from another sub class which in turn may inherit from another subclass thus having levels (parent – child – grand child) of hierarchy.

class Parent:
    ...
    ...
#inherits Parent
class Child(Parent):
    ...
    ...
#inherits Child
class GrandChild(Child):
    ...
    ...
Multi-level inheritance in java

Multiple Inheritance

In multiple inheritance, a sub class is created using more than one super class.

class Parent1:
    ...
    ...
class Parent2:
    ...
    ...
#inherits Parent1 and Parent2
class Child(Parent1, Parent2):
    ...
    ...
Multiple Inheritance

Hierarchical Inheritance

In this type of inheritance more than one sub classes are created from the same super class.

class Parent:
    ...
    ...
#inherits Parent
class Child1(Parent):
    ...
    ...
#inherits Parent
class Child2(Parent):
    ...
    ...
Hierarchical Inheritance

Hybrid inheritance

Hybrid inheritance is the combination of more than one inheritance types. Hence, it may be a combination of Multilevel and Multiple inheritance or Hierarchical and Multilevel inheritance or Hierarchical and Multiple inheritance.

Hybrid inheritance

That's all for this topic Inheritance in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Installation on Windows
  2. Operator Overloading in Python
  3. Abstract Class in Python
  4. Local, Nonlocal And Global Variables in Python
  5. Python return Statement With Examples

You may also like-

  1. self in Python
  2. Removing Spaces From String in Python
  3. Python Program to Display Fibonacci Series
  4. Global Keyword in Python With Examples
  5. Installing Ubuntu Along With Windows
  6. How to Read File From The Last Line in Java
  7. Dependency Injection in Spring Framework
  8. Word Count MapReduce Program in Hadoop

Thursday, May 26, 2022

Abstract Class in Python

An abstract class is a class that contains one or more abstract methods. An Abstract method is a method that generally doesn’t have any implementation, it is left to the sub classes to provide implementation for the abstract methods. Here note that in Python, abstract method can have implementation in the abstract class too but the sub class inheriting that abstract class is still forced to override the abstract methods.


Abstract class in Python

In Python abstract class is created by deriving from the meta class ABC which belongs to the abc (Abstract Base Class) module.

Syntax for creating abstract class in Python

from abc import ABC
Class MyClass(ABC):

From abc module ABC meta class has to be imported and abstract class has to inherit ABC class in order to be considered as an abstract class.

Abstract method in Python

For defining abstract methods in an abstract class method has to be decorated with @abstractmethod decorator. From abc module @abstractmethod decorator has to be imported to use that annotation.

Syntax for defining abstract method in abstract class in Python is as given below.

from abc import ABC, abstractmethod
Class MyClass(ABC):
 @abstractmethod
 def mymethod(self):
  #empty body
  pass

Important points about abstract class in Python

  1. Abstract class can have both concrete methods as well as abstract methods.
  2. Abstract class works as a template for other classes. Using an abstract class you can define a generalized structure without providing complete implementation of every method. Methods which provide common functionality to be used for all derived classes are defined as concrete methods in abstract class where as the methods where implementation may vary are defined as abstract methods.
  3. Abstract class can’t be instantiated so it is not possible to create objects of an abstract class.
  4. Generally abstract methods defined in abstract class don’t have any body but it is possible to have abstract methods with implementation in abstract class. Any sub class deriving from such abstract class still needs to provide implementation for such abstract methods.
  5. If any abstract method is not implemented by the derived class Python throws an error.

Python abstract class example

In the example there is an abstract class with a concrete method common and an abstract method vary. Two sub classes Child1 and Child2 inherit the abstract class Parent and implement the abstract method vary.

from abc import ABC, abstractmethod
class Parent(ABC):
  #common functionality
  def common(self):
    print('In common method of Parent')
  @abstractmethod
  def vary(self):
    pass

class Child1(Parent):
  def vary(self):
    print('In vary method of Child1')

class Child2(Parent):
  def vary(self):
    print('In vary method of Child2')

# object of Child1 class
obj = Child1()
obj.common()
obj.vary()
# object of Child2 class
obj = Child2()
obj.common()
obj.vary()

Output

In common method of Parent
In vary method of Child1
In common method of Parent
In vary method of Child2

As you can see when common method is called the common() method of Parent is invoked. When vary method is called, method defined with in the subclass is invoked.

Python abstract class with abstract method implemented

Even if you provide implementation of abstract method in abstract class sub class is still forced to implement the abstract method.

from abc import ABC, abstractmethod
class Parent(ABC):
  #common functionality
  def common(self):
    print('In common method of Parent')
  @abstractmethod
  def vary(self):
    print('In vary method of Parent')

class Child(Parent):
  pass

# object of Child1 class
obj = Child()
obj.common()
obj.vary()

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Parent.py", line 18, in <module>
    obj = Child()
TypeError: Can't instantiate abstract class Child with abstract methods vary

If you implement vary() method in subclass then it works fine.

from abc import ABC, abstractmethod
class Parent(ABC):
  #common functionality
  def common(self):
    print('In common method of Parent')
  @abstractmethod
  def vary(self):
    print('In vary method of Parent')

class Child(Parent):
  def vary(self):
    print('In vary method of Child')

# object of Child class
obj = Child()
obj.common()
obj.vary()

Output

In common method of Parent
In vary method of Child

Not implementing all abstract methods

If subclass doesn’t implement all the abstract methods defined in the inherited abstract class that also results in an error.

from abc import ABC, abstractmethod
class Parent(ABC):
  #common functionality
  def common(self):
    print('In common method of Parent')
  @abstractmethod
  def vary(self):
    pass
  @abstractmethod
  def test(self):
    pass
    
class Child(Parent):
  def vary(self):
    print('In vary method of Child')

# object of Child class
obj = Child()
obj.common()
obj.vary()

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Parent.py", line 17, in <module>
    obj = Child()
TypeError: Can't instantiate abstract class Child with abstract methods test

Instantiating abstract class in Pyhton

Since abstract class are supposed to have abstract methods having no body so abstract classes are not considered as complete concrete classes, thus it is not possible to instantiate an abstract class.

from abc import ABC, abstractmethod
class Parent(ABC):
  def __init__(self, value):
    self.value = value;
    super().__init__()
  #common functionality
  def common(self):
    print('In common method of Parent', self.value)
  @abstractmethod
  def vary(self):
    pass

class Child(Parent):
  def vary(self):
    print('In vary method of Child')

# trying to instantiate abstract class
obj = Parent(3)
obj.common()
obj.vary()

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Parent.py", line 18, in <module>
    obj = Parent(3)
TypeError: Can't instantiate abstract class Parent with abstract methods vary

That's all for this topic Abstract Class in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Interface in Python
  2. Method Overloading in Python
  3. Inheritance in Python
  4. Abstraction in Python
  5. Python String isdigit() Method

You may also like-

  1. Constructor in Python - __init__() function
  2. String Length in Python - len() Function
  3. raise Statement in Python Exception Handling
  4. Default Arguments in Python
  5. Java Semaphore With Examples
  6. Reverse Each Word in a String Java Program
  7. Bean Scopes in Spring With Examples
  8. Parquet File Format in Hadoop

Tuesday, May 24, 2022

Method Overloading in Python

Method overloading is an OOPS concept which provides ability to have several methods having the same name with in the class where the methods differ in types or number of arguments passed.

Method overloading in Python

Method overloading in its traditional sense (as defined above) as exists in other languages like method overloading in Java doesn’t exist in Python.

In Python if you try to overload a function by having two or more functions having the same name but different number of arguments only the last defined function is recognized, calling any other overloaded function results in an error.

For example in the given class there are two methods having the name sum but number of parameters differ.

class OverloadDemo:
  # first sum method, two parameters
  def sum(self, a, b):
    s = a + b
    print(s)
  # overloaded sum method, three parameters
  def sum(self, a, b, c):
    s = a + b + c
    print(s)

od =  OverloadDemo()
od.sum(7, 8)

Output

File "F:/NETJS/NetJS_2017/Python/Test/OverloadDemo.py", line 10, in <module>
    od.sum(7, 8)
TypeError: sum() missing 1 required positional argument: 'c'

As you can here when calling the method with two parameters an error is thrown as this sum() method is not the latest.

If you call the method having three parameters code runs fine.

class OverloadDemo:
  # first sum method, two parameters
  def sum(self, a, b):
    s = a + b
    print(s)
  # overloaded sum method, three parameters
  def sum(self, a, b, c):
    s = a + b + c
    print(s)

od =  OverloadDemo()
od.sum(7, 8, 9)

Output

24

Process finished with exit code 0

Achieving method overloading in Python

Since using the same method name again to overload the method is not possible in Python, so achieving method overloading in Python is done by having a single method with several parameters. Then you need to check the actual number of arguments passed to the method and perform the operation accordingly.

For example if we take the same method sum() as used above with the capability to pass two or three parameters, in Python this method overloading can be done as shown in the below example.

class OverloadDemo:
  # sum method with default as None for parameters
  def sum(self, a=None, b=None, c=None):
    # When three params are passed
    if a!=None and b!=None and c!=None:
      s = a + b + c
      print('Sum = ', s)
    # When two params are passed
    elif a!=None and b!=None:
      s = a + b
      print('Sum = ', s)

od =  OverloadDemo()
od.sum(7, 8)
od.sum(7, 8, 9)

Output

Sum =  15
Sum =  24

Process finished with exit code 0

That's all for this topic Method Overloading in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Installation on Windows
  2. Python First Program - Hello World
  3. Encapsulation in Python
  4. Name Mangling in Python
  5. Namespace And Variable Scope in Python

You may also like-

  1. Check String Empty or Not in Python
  2. Abstract Class in Python
  3. Concatenating Lists in Python
  4. Python Generator, Generator Expression, Yield Statement
  5. Marker interface in Java
  6. How Linked List class works internally in Java
  7. Race Condition in Java Multi-Threading
  8. What is Hadoop Distributed File System (HDFS)

Thursday, May 12, 2022

Multiple Inheritance in Python

When a sub class is derived from more than one super class it is known as multiple inheritance. In this post we'll see support for multiple inheritance in Python, what all conflicts may occur because of multiple inheritance and what is method resolution order in Python and how it helps in multiple inheritance scenarios.


Python multiple inheritance

Python, unlike Java, supports multiple inheritance. Python has a well designed approach for tackling diamond problem in multiple inheritance using method resolution order.

Here is a figure depicting multiple inheritance where class C inherits from both class A and class B.

Multiple Inheritance

Python syntax for multiple inheritance

A child class DerivedClass inheriting from super classes Parent1, Parent2, Parent3 and so on.

class DerivedClass(Parent1, Parent2, Parent3 ....):

Python multiple inheritance example

class Parent1:
  def display(self):
    print('In display method of Parent1')

class Parent2:
  def display_value(self):
    print('In display method of Parent2')

#inheriting both Parent1 and Parent2
class Child(Parent1, Parent2):
  def display_child(self):
    print('In display method of Child')

obj = Child()
obj.display()
obj.display_value()
obj.display_child()

Output

In display method of Parent1
In display method of Parent2
In display method of Child

Since members of all the parent classes are inherited by the child class so you can access methods in classes Parent1 and Parent2 using an object of class Child.

Conflicts due to multiple inheritance

Example shown above is a simple example of multiple inheritance in Python but in practical world things won’t be that simple. Now is the time to go into diamond problem which can crop up due to multiple inheritance.

Consider the following scenario where you have two super classes and a sub class inheriting both these classes. Each of these classes have their own __init__() method and child class calls the parent class constructor using super. Now the question is which parent class’ constructor would be called.

class Parent1:
  def __init__(self):
    print('In init method of Parent1')
  def display(self):
   print('In display method of Parent1')

class Parent2:
  def __init__(self):
    print('In init method of Parent2')
  def display_value(self):
    print('In display method of Parent2')

#inheriting both Parent1 and Parent2
class Child(Parent1, Parent2):
  def __init__(self):
    super().__init__()
    print('In init method of Child')
  def display_child(self):
    print('In display method of Child')

obj = Child()

Output

In init method of Parent1
In init method of Child

As you can see __init__() method of only Parent1 is called.

Same way if super classes have a method having the same name then which method has to be called?

class Parent1:
  def display(self):
    print('In display method of Parent1')

class Parent2:
  def display(self):
    print('In display method of Parent2')

#inheriting both Parent1 and Parent2
class Child(Parent1, Parent2):
  def display_child(self):
    print('In display method of Child')

obj = Child()
obj.display()
obj.display_child()

Output

In display method of Parent1
In display method of Child

In the example both super classes Parent1 and Parent2 have a method display(), when display() method is called using child class object display() method of Parent1 is called.

If you are wondering how is Python deciding which constructor or which method is to be called in such conflict scenarios you need to know about method resolution order in Python.

Method resolution order in Python

When you have multiple inheritance in Python any member of the class (field or method) is first searched in the child class. If not found there then the search moves to parent classes in depth-first, left to right order without searching the same class twice. This ordering is known as Method Resolution Order (MRO) in Python which works on the following three principles.

  1. Search in the child class first before moving moving higher up to the parent classes.
  2. Search in the parent classes is done in left to right order, for example if class C is inheriting from classes P1 and P2 - class C(P1, P2) then class P1 is searched first then class P2.
  3. No class is visited more than once.

MRO of any class can be viewed using Classname.__mro__ class attribute which returns a tuple or using Classname.mro() method which returns a list.

To understand MRO fully you should also remember that in Python all the classes are derived from the class object. When you write a class definition as class A it is equivalent to class A(object) implicitly it is inheriting from class object.

Calling constructors of all the super classes in multiple inheritance

Now when you understand method resolution order let’s revisit the scenario where constructor of the super class is called from the child class using super(). Now the code is changed keeping MRO in view so that constructors of both Parent1 and Parent2 are called.

class Parent1:
  def __init__(self, x, **kwargs):
    print('In init method of Parent1')
    self.x = x
    super().__init__(**kwargs)
  def display(self):
    print('In display method of Parent1', self.x)

class Parent2:
  def __init__(self, y, **kwargs):
    print('In init method of Parent2')
    self.y = y
    super().__init__(**kwargs)
  def display_value(self):
    print('In display method of Parent2', self.y)

#inheriting both Parent1 and Parent2
class Child(Parent1, Parent2):
  def __init__(self, z, **kwargs):
    print('In init method of Child')
    super().__init__(**kwargs)
    self.z = z

  def display_child(self):
    print('In display method of Child', self.z)

obj = Child(x=10, y='Hello', z=20)

obj.display()
obj.display_value()
obj.display_child()
print(Child.mro())

Output

In init method of Child
In init method of Parent1
In init method of Parent2
In display method of Parent1 10
In display method of Parent2 Hello
In display method of Child 20
[<class '__main__.Child'>, <class '__main__.Parent1'>, <class '__main__.Parent2'>, <class 'object'>]

Following image will help you understand the class hierarchy in the example and to understand how method resolution happens.

method resolution order in python

When object of class Child is created its constructor is called where super().__init__() is encountered which calls the constructor of the super class at the left side (Parent1). With in the constructor of Parent1 again super().__init__() is called, since super class of Parent1 is object so it will try to execute the constructor of object class. But there is no constructor in object class so search moves to right side i.e. Parent2 class and its constructor is executed. There is super().__init__() call in the constructor of Parent2 class too which means again the constructor of object class. Since object class is already visited so execution stops here.

In the example **kwargs (keyword variable arguments) are used to pass the parameters. Using keyword parameters you can identify the parameters by their names.

Same order of execution is also displayed by executing the mro() method for Child class.

Method resolution order with methods in multiple inheritance

If you call parent class method using super() from a child class inheriting from multiple classes then again order of execution is determined by MRO.

class Parent1:
  def display(self):
    print('In display method of Parent1')
    super().display()

class Parent2:
  def display(self):
    print('In display method of Parent2')
    super().display()

#inheriting both Parent1 and Parent2
class Child(Parent1, Parent2):
  def display(self):
    print('In display method of Child')
    super().display()

obj = Child()
obj.display()

Output

In display method of Child
In display method of Parent1
In display method of Parent2

Again by applying method resolution order you can determine the order in which method in each class is executed. Initially display() method of Child class is executed then display() method of Parent1 class is executed as it is on the left side. From Parent1 super().display() call searches display() method in object class (super class of Parent1) which is not found so search continues on the right side class which is Parent2.

That's all for this topic Multiple Inheritance in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Installation on Windows
  2. Method Overriding in Python
  3. Interface in Python
  4. Check String Empty or Not in Python
  5. Python break Statement With Examples

You may also like-

  1. Passing Object of The Class as Parameter in Python
  2. Abstract Class in Python
  3. Python Exception Handling - try,except,finally
  4. Python Program to Check Prime Number
  5. Why no Multiple Inheritance in Java
  6. Race Condition in Java Multi-Threading
  7. Spring Web Reactive Framework - Spring WebFlux Tutorial
  8. Shuffle And Sort Phases in Hadoop MapReduce

Monday, March 28, 2022

Encapsulation in Python

Encapsulation is one of the four fundamental OOPS concepts. The other three being Inheritance, Polymorphism, Abstraction

What is Encapsulation

The concept of Encapsulation is to keep together the implementation (code) and the data it manipulates (variables). Having proper encapsulation ensures that the code and data both are safe from misuse by outside entity. That is done by restricting access to the methods and variables and any change to the variables done only through methods.

Encapsulation in Python

In any object oriented language first step towards encapsulation is the class and encapsulation in Python also starts from a class as the class encapsulates the methods and variables. When a Python class is created it contains the methods and the variables. Since it’s the code in the methods that operates on the variables, in a properly encapsulated Python class, methods should define how member variables can be used.

But that’s where the things differ a bit in Python from a language like Java where we have access modifiers like public, private. In Python there are no explicit access modifiers and everything written with in the class (methods and variables) are public by default.

For example in the class Person there are two variables as you can see those variables are accessed through a method as well as directly.

class Person:
  def __init__(self, name, age=0):
    self.name = name
    self.age = age

  def display(self):
    print(self.name)
    print(self.age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print(person.name)
print(person.age)

Output

John
40
John
40

Access control in Python

If everything inside a class is public then how to have access control and how to have proper encapsulation in Python?

In Python though there are no explicit access modifiers but using underscores (_) you can make a variable private.

Using single underscore

Using a single leading underscore is merely a convention. A name prefixed with an underscore in Python (as example _name) should be treated as a non-public part of the API (whether it is a function, a method or a data member).

As mentioned it is just a convention and a leading underscore doesn’t actually make any variable or method private or protected. It’s just that if you see a variable or method with a leading underscore in Python code you should follow the convention that it should be used internally with in a class.

For example in class Person if age variable is changed and it is prefixed with underscore.

class Person:
  def __init__(self, name, age=0):
    self.name = name
    self._age = age

  def display(self):
    print(self.name)
    print(self._age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print(person.name)
print(person._age)

Output

John
40
John
40

As you can see these variables can still be accessed from outside the class.

Using double underscore (making it private)

If you really want to make a class member (member or variable) private in Python you can do it by prefixing a variable or method with double underscores. Here note that Python provides a limited support for private modifier using a mechanism called name mangling and it is still possible to access such class member from outside the class.

In Python any identifier of the form __var (at least two leading underscores, at most one trailing underscore) is rewritten by the Python interpreter in the form _classname__var, where classname is the current class name. This mechanism of name changing is known as name mangling in Python.

For example in class Person age variable is changed and it is prefixed with two leading underscores.

class Person:
  def __init__(self, name, age=0):
    self.name = name
    self.__age = age

  def display(self):
    print(self.name)
    print(self.__age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print('Trying to access variables from outside the class ')
print(person.name)
print(person.__age

Output

John
40
Trying to access variables from outside the class
John
Traceback (most recent call last):
  File "Person.py", line 16, in <module>
    print(person.__age)
AttributeError: 'Person' object has no attribute '__age'

As you can see variables can still be accessed using the method which is part of the class but age (which is a private variable) can’t be accessed directly from outside now.

Using getter and setter methods to access private variables

To access and change private variables accessor (getter) methods and mutator (setter methods) should be used which are part of the class.

class Person:
  def __init__(self, name, age=0):
    self.name = name
    self.__age = age

  def display(self):
    print(self.name)
    print(self.__age)

  def getAge(self):
    print(self.__age)

  def setAge(self, age):
    self.__age = age

person = Person('John', 40)
#accessing using class method
person.display()
#changing age using setter
person.setAge(45)
person.getAge()

Output

John
40
45

That's all for this topic Encapsulation in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Installation on Windows
  2. Python First Program - Hello World
  3. Method Overriding in Python
  4. Python for Loop With Examples
  5. Difference Between Function and Method in Python

You may also like-

  1. Constructor in Python - __init__() function
  2. self in Python
  3. Python count() method - Counting Substrings
  4. Python Exception Handling - try,except,finally
  5. How to Read File From The Last Line in Java
  6. Marker Interface in Java
  7. How Linked List class works internally in Java
  8. Race Condition in Java Multi-Threading

Saturday, January 16, 2021

Polymorphism in Python

Polymorphism is one of the four fundamental OOPS concepts. The other three being Inheritance, Encapsulation, Abstraction

Polymorphism is a Greek word where poly means many and morph means change thus it refers to the ability of an entity taking many forms. In an object oriented context that means an entity which may be a method, object or operator can represent different types based on the scenario where they are used.

Polymorphism in Python

In an object oriented language you will find support for Polymorphism through-

  • Method overloading
  • Method overriding
  • Operator overloading

Python being an object oriented language also supports Polymorphism but only through Method overriding and operator overloading. Method overloading in its traditional sense is not supported in Python.