5

Simply, what is the cleanest or most commonly used way in which constructors are overloaded in Python?

I have experience in C# and am new to Python, so I'm still learning what is best practice in Python.

C# has a very clean way of overloading constructors, so that I can handle different data types being passed as arguments on initialization. I have seen a lot of different answers in how similar results can be achieved in Python, and I don't NOT want default parameters or logic within my constructor to handle different data types!!! And I can not understand why people are recommending this as an alternative.

Here is some C# code, and I basically want to do the same in Python.

class SomeClass{

    int a;
    double b;
    string c;

    public SomeClass(int value1, double value2)
    {
        a = value1
        b = value2
    }

    public SomeClass(int value1, string value2)
    {
        a = value1
        c = string
    }
}

The above code is just an example. I know there are hacks, like testing argument type and adding this logic to my constructor or accepting that Python is not strongly typed and writing logic in my class methods for how value2 may be handled for different types.

However, the code I am writing is not as simple as the above. I want to handle how arguments of different objects or data types are handled. I would like to overload my constructor for handling objects of different classes and data type i.e. I could pass an object of MyObject<MyObjectClass> or a JSON file or text file/CSV file, etc.

And I do not want a hacky if statement to test if a JSON file is passed. This is because potentially my constructor for passing a CSV file will contain further arguments and/or different arguments from passing a JSON file.

I find the way in which C# handles overloading constructors much cleaner as I can easily add further arguments to my JSON file constructor in the future and I only need to fiddle with the one constructor!

I'm sure Python has a very clean way of achieving the same...?

It just hit me that overloading is probably non-existent in Python as it is not statically typed. And therefore I am assuming class methods are best suited for my purpose._

class SomeClass(object)

    @classmethod
    def fromtextfilename(cls, textfile):
        # Logic here
        return cls(data)

    @classmethod
    def fromtextfilename(cls, jsonfile):
        # Logic here
        return cls(data)

    __int__(self,data)
        # Use data to populate properties

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Soggy
  • 142
  • 1
  • 15
  • Python doesn't have method overloading. Usually, you would use alternate constructors using `@classmethod` – juanpa.arrivillaga Sep 28 '19 at 02:18
  • 1
    Take a look here: [Overloading constructors in Python](https://stavshamir.github.io/python/2018/05/26/overloading-constructors-in-python.html) – accdias Sep 28 '19 at 02:20
  • 1
    Also, Python is *strongly* typed, it's just dynamically as opposed to statically typed. – juanpa.arrivillaga Sep 28 '19 at 02:20
  • @Dennis Yer I did read this first... there were quite a few alternative answers and I didn't pick up the most voted answer, did have the answer I needed, the class methods just didn't include any arguments, which I think got me confused... – Soggy Sep 28 '19 at 02:29

1 Answers1

8

Let's say, you have a class Book:

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

Now, you wish to consume a web API that returns book data and want to instantiate a Book object directly from the API’s JSON response. You'll have to change the init method and add a check.

class Book:
    def __init__(self, title = None, author = None, pages = None, book_as_json = None):
    if book_as_json:
        book = json.loads(book_as_json)
        self.title = book['title']
        self.author = book['author']
        self.pages = book['pages']
    else:
        self.title = title
        self.author = author
        self.pages = pages

But this kind of approach is not good as per industry standards. Hence, use can try using the @classmethod decorator

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    @classmethod
    def from_json(cls, book_as_json):
        book = json.loads(book_as_json)
        return cls(title=book['title'], author=book['author'], pages=book['pages'])

For detailed description, see this link.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
taurus05
  • 2,491
  • 15
  • 28
  • To those who confused about the weird semi colons and `->`, those are [type hints](https://stackoverflow.com/questions/32557920/what-are-type-hints-in-python-3-5), and basically don't affect the code in any way in this case. – Lord Elrond Sep 28 '19 at 03:01
  • To make it much clear, as most people aren't familiar with type hints, i've removed it. Thanks for pointing that out! – taurus05 Sep 28 '19 at 03:03
  • 1
    That was going to be my original comment "recommending that you remove them", but I ending up learning about them as a result. Anyways +1 – Lord Elrond Sep 28 '19 at 03:06
  • 2
    The link is broken (404). – Peter Mortensen Jan 28 '21 at 21:37
  • 1
    @Deadpool I'd have kept the type hints. For the purpose of writing readable code, they should definitely be used. – rasmus91 May 12 '21 at 07:58