1

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?

Smith Dwayne
  • 2,675
  • 8
  • 46
  • 75
  • Have you looked at how Python stores an object's methods and properties? This behavior will make sense if you do. – tehhowch Feb 16 '19 at 11:53
  • Within your class you define two methods with the same name `__init__`. Whichever is the second is what you end up with and respectively - what arguments are expected or not. – buran Feb 16 '19 at 12:00

4 Answers4

1

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
        ... 
miraculixx
  • 10,034
  • 2
  • 41
  • 60
0

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

adil zakarya
  • 220
  • 1
  • 4
  • 14
0

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

0

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
Udesh
  • 2,415
  • 2
  • 22
  • 32