Hi, suppose a C++ class has several constructors which are overloaded according the number and type and sequences of their respective parameters, for example, constructor(int x, int y)
and constructor(float x, float y, float z)
, I think these two are overloaded methods, which one to use depends on the parameters, right? So then in python, how could I create a constructor that can work like this? I notice that python has the def method(self, *args, **kwargs):
, so can I use it like: def _init_(self, *args)
, then I check the length of *args
, like if len(args) == 2:
, then construct according to the 2-parameters constructor, if len(args) == 3
, then use the 3-parameters constructor, etc. So, does that work? Or is there any better way to do it with python? Or should I think in other ways that could take the advantage of python feature itself? thanks~
views:
76answers:
4I think these two are overloaded methods, which one to use depends on the parameters, right?
Sorry, if I seem to be nitpicking, but just thought of bringing this difference out clearly.
The term parameters and arguments have very specific meaning in C++
argument: an expression in the comma-separated list bounded by the parentheses in a function call expression, a sequence of preprocessing tokens in the comma-separated list bounded by the parentheses in a function-like macro invocation, the operand of throw, or an expression, type-id or template-name in the commaseparated list bounded by the angle brackets in a template instantiation. Also known as an actual argument or actual parameter.
parameter: an object or reference declared as part of a function declaration or definition, or in the catch clause of an exception handler, that acquires a value on entry to the function or handler; an identifier from the commaseparated list bounded by the parentheses immediately following the macro name in a function-like macro definition; or a template-parameter. Parameters are also known as formal arguments or formal parameters
This article talks about how a multimethod decorator can be created in Python. I haven't tried out the code that they give, but the syntax that it defines looks quite nice. Here's an example from the article:
from mm import multimethod
@multimethod(int, int)
def foo(a, b):
...code for two ints...
@multimethod(float, float):
def foo(a, b):
...code for two floats...
@multimethod(str, str):
def foo(a, b):
...code for two strings...
Usually, you're fine with any combination of
- slightly altered design
- default arguments (
def __init__(self, x = 0.0, y = 0.0, z = 0.0)
) - use of polymorphism (in a duck-typed language, you don't need an overload for SomeThing vs SomeSlightlyDifferentThing if neither inherits from the other one, as long as their interfaces are similar enough).
If that doesn't seem feasible, try harder ;) If it still doesn't seem feasible, look at David's link.
It really depends on what you want to do. The args/*kwargs method works fairly well, as does the default arguments that delnan suggests.
The main difference between C++ and Python in this case is the what and why of what you are trying to do. If you have a class that needs floats, just try casting the arguments as floats. You can also rely on default arguments to branch your logic:
class Point(object):
def __init__(self, x=0.0, y=0.0, z=None):
# Because None is a singleton,
# it's like Highlander - there can be only one! So use 'is'
# for identity comparison
if z is None:
self.x = int(x)
self.y = int(y)
self.z = None
else:
self.x = float(x)
self.y = float(y)
self.z = float(z)
p1 = Point(3, 5)
p2 = Point(1.0, 3.3, 4.2)
p3 = Point('3', '4', '5')
points = [p1, p2, p3]
for p in points:
print p.x, p.y, p.z
You don't, of course, have to assign self.z = None
, that was simply for the convenience of my example.
For the best advice about which pattern to use,
In [17]: import this
The Zen of Python, by Tim PetersBeautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
...
If your pattern is beautiful, explicit, and simple, it just may be the right one to use.