I have a container class that holds data. When the container is created, there are different methods to pass data.
In Java, I would create three constructors. Here's how it would look like if it were possible in Python:
class Container: def __init__(self): self.timestamp = 0 self.data = [] self.metadata = {} def __init__(self, file): f = file.open() self.timestamp = f.get_timestamp() self.data = f.get_data() self.metadata = f.get_metadata() def __init__(self, timestamp, data, metadata): self.timestamp = timestamp self.data = data self.metadata = metadata
In Python, I see three obvious solutions, but none of them is pretty:
A: Using keyword arguments:
def __init__(self, **kwargs): if 'file' in kwargs: ... elif 'timestamp' in kwargs and 'data' in kwargs and 'metadata' in kwargs: ... else: ... create empty container
B: Using default arguments:
def __init__(self, file=None, timestamp=None, data=None, metadata=None): if file: ... elif timestamp and data and metadata: ... else: ... create empty container
C: Only provide constructor to create empty containers. Provide methods to fill containers with data from different sources.
def __init__(self): self.timestamp = 0 self.data = [] self.metadata = {} def add_data_from_file(file): ... def add_data(timestamp, data, metadata): ...
Solutions A and B are basically the same. I don't like doing the if/else, especially since I have to check if all arguments required for this method were provided. A is a bit more flexible than B if the code is ever to be extended by a fourth method to add data.
Solution C seems to be the nicest, but the user has to know which method he requires. For example: he cant do c = Container(args)
if he doesn't know what args
is.
Whats the most Pythonic solution?
Python does not support explicit multiple constructors, yet there are some ways using which the multiple constructors can be achieved. If multiple __init__ methods are written for the same class, then the latest one overwrites all the previous constructors.
In c++, there are multiple constructors in a class under the same name but a different list of arguments. This concept of constructor overloading in c++ is quite similar to function overloading. Usually, you should create more than one constructor in a class to initialize member variables differently for objects.
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.
The technique of having two (or more) constructors in a class is known as constructor overloading. A class can have multiple constructors that differ in the number and/or type of their parameters. It's not, however, possible to have two constructors with the exact same parameters.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With