Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overload __init__ method based on argument type?

Let's say I have a class that has a member called data which is a list.

I want to be able to initialize the class with, for example, a filename (which contains data to initialize the list) or with an actual list.

What's your technique for doing this?

Do you just check the type by looking at __class__?

Is there some trick I might be missing?

I'm used to C++ where overloading by argument type is easy.

like image 409
Baltimark Avatar asked Sep 26 '08 19:09

Baltimark


People also ask

Can we overload Init method in Python?

Python does not support Constructor overloading; it has no form of function. In Python, Methods are defined solely by their name, and there can be only one method per class with a given name.

Can we overload constructors or methods in Python?

Like other languages (for example, method overloading in C++) do, python does not support method overloading by default.

How do you overload a method in Python?

There isn't any method overloading in Python. You can however use default arguments, as follows. When you pass it an argument, it will follow the logic of the first condition and execute the first print statement. When you pass it no arguments, it will go into the else condition and execute the second print statement.

What is the use of __ Init__ method give example?

The __init__ method is the Python equivalent of the C++ constructor in an object-oriented approach. The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.


1 Answers

A much neater way to get 'alternate constructors' is to use classmethods. For instance:

>>> class MyData: ...     def __init__(self, data): ...         "Initialize MyData from a sequence" ...         self.data = data ...      ...     @classmethod ...     def fromfilename(cls, filename): ...         "Initialize MyData from a file" ...         data = open(filename).readlines() ...         return cls(data) ...      ...     @classmethod ...     def fromdict(cls, datadict): ...         "Initialize MyData from a dict's items" ...         return cls(datadict.items()) ...  >>> MyData([1, 2, 3]).data [1, 2, 3] >>> MyData.fromfilename("/tmp/foobar").data ['foo\n', 'bar\n', 'baz\n'] >>> MyData.fromdict({"spam": "ham"}).data [('spam', 'ham')] 

The reason it's neater is that there is no doubt about what type is expected, and you aren't forced to guess at what the caller intended for you to do with the datatype it gave you. The problem with isinstance(x, basestring) is that there is no way for the caller to tell you, for instance, that even though the type is not a basestring, you should treat it as a string (and not another sequence.) And perhaps the caller would like to use the same type for different purposes, sometimes as a single item, and sometimes as a sequence of items. Being explicit takes all doubt away and leads to more robust and clearer code.

like image 66
Thomas Wouters Avatar answered Oct 03 '22 00:10

Thomas Wouters