newbie-question: more then one constructor in a python-class?

Alex Martelli aleax at aleax.it
Sun Jul 7 12:05:58 EDT 2002


T. Kaufmann wrote:

> Hi python-experts,
> 
> is there a way to have more (then one) constructors in a python-class
> (like in Java)?

No, because the constructor is the one and only method named __init__,
and a class can't have more than one method with a given name.

However, you can obtain much the same effect with factory idioms.

Remember, this is Python, a multi-paradigm language: you don't have
to express *everything* as methods of some class or other, but rather
you choose such expression only if and when you find it more clear
and productive than alternatives.


> I mean something like this in Java:
> 
> 
> public class MyClass {
> 
> public MyClass() {
> ... do anything here
> }
> 
> public MyClass(String param) {
> ... do anything here
> }
> 
> public MyClass(String param, StringBuffer param) {

I don't think this is legal Java (two parameters with the same name),
it's surely not legal Python, so I'll make believe the second one
is named param2:-).

> ... do anything here
> }

Most often, here, you would use arguments with default values:

class MyClass:

    def __init__(self, param=None, param2=None):
        if param is None:
            assert param2 is None
            dowhatyoulikewithnoargs(self)
        elif param2 is None:
            dowhatyoulikewithonearg(self, param)
        else:
            dowhatyoulikewithtwoargs(self, param, param2)


For more flexibility, however, in other cases you can arrange
that client-code never instantiates the class by calling the
class itself directly: rather, it calls factory functions,
each of which initializes the instance differently.  E.g.:

class Feep(object):
    def __init__(self):
        raise RuntimeError, "don't build Feep instances directly!"

def makeIntFeep(anint):
    result = Feep.__new__(Feep)
    result.anint = anint
    return result

def makeStringFeep(astring):
    result = Feep.__new__(Feep)
    result.astring = astring
    return result

x = makeIntFeep(23)
print x.anint

y = makeStringFeep('twenty-three')
print y.astring


etc, etc.  This needs Python 2.2 (for the __new__ call) -- you can
get the same effect in Python 2.1 but it needs a more roundabout
approach, and there's really no reason to do things the 2.1 way --
2.2 is better and gives you substantial advantages.

It's very rare for the factory idioms to be actually required, but
when you DO need total flexibility, factories of various kinds
really let you have it (build objects of different types according
to the supplied arguments, etc, etc) in ways that calling classes
directly can never fully match.  So, it's a good design pattern to
have up your sleeve for those very rare cases in which you need it.


Alex




More information about the Python-list mailing list