Like overloading __init__(), but how?

J

John M. Gabriele

I know that Python doesn't do method overloading like
C++ and Java do, but how am I supposed to do something
like this:

--------------------- incorrect ------------------------
#!/usr/bin/python

class Point3d:
pass

class Vector3d:
"""A vector in three-dimensional cartesian space."""

def __init__( self ):
"""Create a Vector3d with some reasonable default value."""
x, y, z = 0.0, 0.0, 0.0


def __init__( self, x_from, y_from, z_from,
x_to, y_to, z_to ):
"""Create a Vector3d from x-y-z coords."""
# ...
pass


def __init__( self, point_from, point_to ):
"""Create a Vector3d from two Point3d objects."""
# ...
pass


def __init__( self, same_as_this_vec ):
"""Create a Vector3d from a copy of another one."""
# ...
pass

p = Point3d()
p2 = Point3d()
# v = Vector3d( p2, p ) -- Nope. Only the last __init__() counts.

---------------------- /incorrect -------------------------------

Thanks.
 
S

Steven Bethard

John said:
class Vector3d:
def __init__(self):
...
def __init__(self, x_from, y_from, z_from, x_to, y_to, z_to):
...
def __init__(self, point_from, point_to):
...
def __init__(self, same_as_this_vec):
...

My preferred option is to break these into different methods. I pick
the xyz-coords (and the empty coords) __init__ as the most basic cases,
but if you find one of the other cases to be more basic, the
modification should be pretty simple.

class Vector3d(object):
# define init to take only xyz coords (missing coords default to 0)
# this covers your first two cases, I think
def __init__(self, x_from=0.0, y_from=0.0, z_from=0.0,
x_to=0.0, y_to=0.0, z_to=0.0):
...

# define a classmethod that creates a Vector3d from points
# this covers your third case
@classmethod
def from_points(cls, point_from, point_to):
...
return cls(x_from=..., y_from=..., ...)

# define copy as an instance method, not a constructor
# this covers your fourth case
def copy(self):
...
return type(self)(x_from=..., y_from=..., ...)


Another possibility is to play around with *args:

class Vector3d(object):
def __init__(self, *args):
if not args:
# constructor with no arguments
elif len(args) == 6:
# constructor with xyz coords
elif len(args) == 2:
# constructor with points
elif len(args) == 1:
# copy constructor
else:
raise TypeError('expected 0, 1, 2 or 6 args, got %i' %
len(args))

But this can get really ugly really quick.

HTH,

STeVe
 
J

John M. Gabriele

[snip]
Another possibility is to play around with *args:

class Vector3d(object):
def __init__(self, *args):
if not args:
# constructor with no arguments
elif len(args) == 6:
# constructor with xyz coords
elif len(args) == 2:
# constructor with points
elif len(args) == 1:
# copy constructor
else:
raise TypeError('expected 0, 1, 2 or 6 args, got %i' %
len(args))

But this can get really ugly really quick.

HTH,

STeVe

Thanks STeVe. I think, for now, I'll probably stick with
the easier but less elegant way of checking *args. I guess
I could compare args[0].__class__.__name__ against 'Point3d',
'Vector3d', or just 'float'.

Didn't realize this topic came up recently. Sorry for the
duplication.

---J
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top