Smith Dwayne
Smith Dwayne

Reputation: 2797

Constructor overloading in python with default arguments

I defined a class in python as following.

class myclass:
    def __init__(self,edate,fdate=""):
        print("Constructors with default arguments...")

    def __init__(self):
        print("Default Constructor")

I created an object for this class,

obj = myclass()

It works fine. And I expected the following object creation will work,

obj1 = myclass("01-Feb-2019")

But It throws an error saying,

Traceback (most recent call last):
  File "class.py", line 9, in <module>
    obj = myclass("01-Feb-2019")
TypeError: __init__() takes 1 positional argument but 2 were given

But If I change the definition of the class as follows,

class myclass:
    def __init__(self):
        print("Default Constructor")
    def __init__(self,edate,fdate=""):
        print("Constructors with default arguments...")

Now obj1 = myclass("01-Feb-2019") works. But obj = myclass() throws the following error,

Traceback (most recent call last):
  File "class.py", line 10, in <module>
    obj = myclass()
TypeError: __init__() missing 1 required positional argument: 'edate'

Could we define a constructor overloading in Python? Could I define a constructor which accepts the empty argument as well as one argument?

Upvotes: 1

Views: 1059

Answers (4)

user8234870
user8234870

Reputation:

Use multipledispatch(link) module to overload methods

Installation:

python3 -m pip install multipledispatch

A Dispatcher object stores and selects between different implementations of the same abstract operation. It selects the appropriate implementation based on a signature, or list of types. We build one dispatcher per abstract operation.

The dispatch decorator hides the creation and manipulation of Dispatcher objects from the user.

Using @dispatch wrapper to overload methods:

from multipledispatch import dispatch


class Shape:
    @dispatch(int)
    def __init__(self, length):
        self.length = length
        self.dimension = 1

    @dispatch(float)
    def __init__(self, length):
        self.length = length
        self.dimension = 1

    @dispatch(int, int)
    def __init__(self, length, width):
        self.length = length
        self.width = width
        self.dimension = 2
        self._getArea = lambda: self.length * self.width

    @dispatch(float, float)
    def __init__(self, length, width):
        self.length = length
        self.width = width
        self.dimension = 2
        self._getArea = lambda: self.length * self.width

    @dispatch(int, int, int)
    def __init__(self, length, width, height):
        self.length = length
        self.width = width
        self.height = height
        self.dimension = 3
        self._getArea = lambda: 2 * (self.length * self.width + self.length * self.height +
                                     self.width * self.height)
        self._getVolume = lambda: self.length * self.width * self.height

    @dispatch(float, float, float)
    def __init__(self, length, width, height):
        self.length = length
        self.width = width
        self.height = height
        self.dimension = 3
        self._getArea = lambda: 2 * (self.length * self.width + self.length * self.height +
                                     self.width * self.height)
        self._getVolume = lambda: self.length * self.width * self.height

    def getLength(self):
        return self.length

    def getArea(self):
        if self.dimension == 1:
            raise Exception(f"Shapes with {self.dimension} dimensions have no area")
        return self._getArea()

    def getVolume(self):
        if self.dimension < 3:
            raise Exception(f"Shapes with {self.dimension} dimensions have no volume")
        return self._getVolume()


if __name__ == "__main__":
    line = Shape(3)
    curve = Shape(5.5)
    rectangle = Shape(5.5, 100.1)
    cuboid = Shape(23, 22, 10)

    print(line.getLength())
    print(curve.getLength())
    print(rectangle.getArea())
    print(cuboid.getVolume(), cuboid.getArea())
    
    #will raise Exception since rectangles don't have volume
    print(rectangle.getVolume())

Output:

3
5.5
550.55
5060 1912
Traceback (most recent call last):
....
  Exception: Shapes with 2 dimensions have no volume

Upvotes: 0

miraculixx
miraculixx

Reputation: 10349

As others have written, Python does not support multiple constructors *). However you can emulate them easily as follows:

class MyClass:
    def __init__(self, edate=None, fdate=""):
        if edate:
            print("Constructors with default arguments...")
        else:
            print("Default Constructor")

Then you can do

obj1 = MyClass("01-Feb-2019")
=> Constructors with default arguments...
obj2 = MyClass()
=> Default Constructor

*) except if you go for multi-dispatch - making use of Python's powerful inspection features

Note that assigning default values in the method declaration should be done very reluctantly as it may work differently than one thinks coming from another language. The proper way to define default values would be using None and assign default values like this

class MyClass:
    def __init__(self, edate=None, fdate=None):
        if edate:
           fdate = "" if fdate is None else fdate
        ... 

Upvotes: 1

Elad Shtilerman
Elad Shtilerman

Reputation: 23

Python doesn't have multiple constructors - see Multiple constructors in python?

Upvotes: 0

adil zakarya
adil zakarya

Reputation: 220

Unlike Java or C#, you cannot define multiple constructors. However, you can define a default value if one is not passed.

Upvotes: 0

Related Questions