Reputation: 33243
What is a clean way to declare multiple constructors for one class?
For example, let's say I have an Item
class. One way to create an Item (for example is)
item = Item(product_id, name, description,price)
another way to do the same thing might
item = Item(otherItem)
And then another way to do this.. maybe in some cases I don't have the price so I want to pass just
item = Item(product_id, name,description)
and yet another case might be
item = Item(product_id,price)
The other question I have is:
There are some private variables which might be initialized during runtime.
Let's say I have some random variable itemCount
and I want to keep a track of it internally.
How do I declare it that I dont have to put it in initialization mode, but rather, somewhere in the run time.. I can do something like
self._count +=1
Thanks
Upvotes: 2
Views: 657
Reputation: 49085
You could use default arguments:
class Item(object):
def __init__(self, product_id = None, name = None, description = None, price = None)
... implementation ...
You can substitute in any value you want for None
, if the default value should be something different.
Example usage:
item1 = Item(product_id = 4, price = 13) # use the field name!
item2 = Item(name = "hammer", description = "used to belong to Thor")
For the copy constructor, item = Item(otherItem)
, @Raymond's suggestions of class methods and factory functions may be the most Pythonic way to go.
Update: here's a question about multiple constructors in Python. It also mentions using *args
and **kwargs
.
Upvotes: 1
Reputation: 601609
Copying is usually done by a copy()
method on instances instead of by providing a "copy constructor", so it's
item = other_item.copy()
instead of
item = Item(other_item)
All the other constructor signatures you mentioned easily be handled by default arguments and keyword arguments:
def __init__(self, product_id, name=None, description=None, price=None):
...
If you want another constructor with completely different code, than a classmethod
is the right approach -- see the answer by Raymond Hettinger.
Upvotes: 1
Reputation: 226316
The two most common approaches for providing multiple constructors are:
Here is an example taken from the standard library showing how collections.OrderedDict uses a classmethod to implement fromkeys() as an alternate class constructor:
@classmethod
def fromkeys(cls, iterable, value=None):
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
If not specified, the value defaults to None.
'''
self = cls()
for key in iterable:
self[key] = value
return self
As an example of the other common approach, here's a factory function used in symtable.py in the standard library:
class SymbolTableFactory:
def __init__(self):
self.__memo = weakref.WeakValueDictionary()
def new(self, table, filename):
if table.type == _symtable.TYPE_FUNCTION:
return Function(table, filename)
if table.type == _symtable.TYPE_CLASS:
return Class(table, filename)
return SymbolTable(table, filename)
Upvotes: 4