Multiple constructors in python?


Question

Possible Duplicate:
What is a clean, pythonic way to have multiple constructors in Python?

Is it not possible to define multiple constructors in Python, with different signatures? If not, what's the general way of getting around it?

For example, let's say you wanted to define a class City

I'd like to be able to say someCity = City() or someCity = City("Berlin"), where the first just gives a default name value, and the second defines it.

1
189
5/23/2017 12:34:39 PM

Accepted Answer

Unlike Java, you cannot define multiple constructors. However, you can define a default value if one is not passed.

def __init__(self, city="Berlin"):
  self.city = city
252
1/29/2010 6:41:42 PM

If your signatures differ only in the number of arguments using default arguments is the right way to do it. If you want to be able to pass in different kinds of argument I would try to avoid the isinstance-based approach mentioned in another answer, instead using keyword arguments. If using just keyword arguments becomes unwieldy you can combine it with classmethods (the bzrlib code likes this approach). This is just a silly example, but I hope you get the idea:

class C(object):

    def __init__(self, fd):
        # Assume fd is a file-like object.
        self.fd = fd

    @classmethod
    def fromfilename(cls, name):
        return cls(open(name, 'rb'))

# Now you can do:
c = C(fd)
# or:
c = C.fromfilename('a filename')

Notice all those classmethods still go through the same __init__, but using classmethods can be much more convenient than having to remember what combinations of keyword arguments to __init__ work.

isinstance is best avoided because python's duck typing makes it hard to figure out what kind of object was actually passed in. For example: if you want to take either a filename or a file-like object you cannot use isinstance(arg, file) because there are many file-like objects that do not subclass file (like the ones returned from urllib, or StringIO, or...). It's usually a better idea to just have the caller tell you explicitly what kind of object was meant, by using different keyword arguments.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon