Multiple constructors: the Pythonic way? [duplicate] Multiple constructors: the Pythonic way? [duplicate] python python

Multiple constructors: the Pythonic way? [duplicate]


You can't have multiple methods with same name in Python. Function overloading - unlike in Java - isn't supported.

Use default parameters or **kwargs and *args arguments.

You can make static methods or class methods with the @staticmethod or @classmethod decorator to return an instance of your class, or to add other constructors.

I advise you to do:

class F:    def __init__(self, timestamp=0, data=None, metadata=None):        self.timestamp = timestamp        self.data = list() if data is None else data        self.metadata = dict() if metadata is None else metadata    @classmethod    def from_file(cls, path):       _file = cls.get_file(path)       timestamp = _file.get_timestamp()       data = _file.get_data()       metadata = _file.get_metadata()              return cls(timestamp, data, metadata)    @classmethod    def from_metadata(cls, timestamp, data, metadata):        return cls(timestamp, data, metadata)    @staticmethod    def get_file(path):        # ...        pass

⚠ Never have mutable types as defaults in python. ⚠ See here.


You can't have multiple constructors, but you can have multiple aptly-named factory methods.

class Document(object):    def __init__(self, whatever args you need):        """Do not invoke directly. Use from_NNN methods."""        # Implementation is likely a mix of A and B approaches.     @classmethod    def from_string(cls, string):        # Do any necessary preparations, use the `string`        return cls(...)    @classmethod    def from_json_file(cls, file_object):        # Read and interpret the file as you want        return cls(...)    @classmethod    def from_docx_file(cls, file_object):        # Read and interpret the file as you want, differently.        return cls(...)    # etc.

You can't easily prevent the user from using the constructor directly, though. (If it is critical, as a safety precaution during development, you can analyze the call stack in the constructor and check that the call is made from one of the expected methods.)


Most Pythonic would be what the Python standard library already does. Core developer Raymond Hettinger (the collections guy) gave a talk on this, plus general guidelines for how to write classes.

Use separate, class-level functions to initialize instances, like how dict.fromkeys() isn't the class initializer but still returns an instance of dict. This allows you to be flexible toward the arguments you need without changing method signatures as requirements change.