Search code examples
pythonclassconstructor

What is a clean "pythonic" way to implement multiple constructors?


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?


Solution

  • 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