Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a clean, Pythonic way to have multiple constructors in Python?

I can't find a definitive answer for this. As far as I know, you can't have multiple __init__ functions in a Python class. So how do I solve this problem?

Suppose I have a class called Cheese with the number_of_holes property. How can I have two ways of creating cheese objects...

  1. One that takes a number of holes like this: parmesan = Cheese(num_holes = 15).
  2. And one that takes no arguments and just randomizes the number_of_holes property: gouda = Cheese().

I can think of only one way to do this, but this seems clunky:

class Cheese():     def __init__(self, num_holes = 0):         if (num_holes == 0):             # Randomize number_of_holes         else:             number_of_holes = num_holes 

What do you say? Is there another way?

like image 268
winsmith Avatar asked Mar 25 '09 17:03

winsmith


People also ask

Can you have multiple init in Python?

As far as I know, you can't have multiple __init__ functions in a Python class.

What is the __ str __ method in Python?

Python __str__() This method returns the string representation of the object. This method is called when print() or str() function is invoked on an object. This method must return the String object.

What is __ init __ in Python?

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.

Can you overload constructors 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.


1 Answers

Actually None is much better for "magic" values:

class Cheese():     def __init__(self, num_holes = None):         if num_holes is None:             ... 

Now if you want complete freedom of adding more parameters:

class Cheese():     def __init__(self, *args, **kwargs):         #args -- tuple of anonymous arguments         #kwargs -- dictionary of named arguments         self.num_holes = kwargs.get('num_holes',random_holes()) 

To better explain the concept of *args and **kwargs (you can actually change these names):

def f(*args, **kwargs):    print 'args: ', args, ' kwargs: ', kwargs  >>> f('a') args:  ('a',)  kwargs:  {} >>> f(ar='a') args:  ()  kwargs:  {'ar': 'a'} >>> f(1,2,param=3) args:  (1, 2)  kwargs:  {'param': 3} 

http://docs.python.org/reference/expressions.html#calls

like image 91
vartec Avatar answered Sep 22 '22 23:09

vartec