Constructor overloading

Discussion in 'Python' started by Sergey Krushinsky, Jun 9, 2004.

  1. Hello all,

    Is there a common way to emulate constructor overloading in Python class?

    For instanse, I have 3 classes:
    1/ Polar - to hold polar coordinates;
    2/ Cartesian - to hold cartesian coordinates;
    3/ Coordinates3D, which holds synchronized instances of the both in
    __p__ and __c__ fields respectively.

    I want to design Coordinates3D so that when instantiated with Polar
    argument, self.__p__=argument passed to constructor, and self.__c__ is
    calculated. When argument is Cartesian, self.__c__=argument, and
    self.__p__ is calculated. Runtime type checking works, but maybe there
    is a better way?

    Thanks in advance,
    Sergey
     
    Sergey Krushinsky, Jun 9, 2004
    #1
    1. Advertising

  2. Sergey Krushinsky

    John Roth Guest

    "Sergey Krushinsky" <> wrote in message
    news:...
    > Hello all,
    >
    > Is there a common way to emulate constructor overloading in Python class?
    >
    > For instanse, I have 3 classes:
    > 1/ Polar - to hold polar coordinates;
    > 2/ Cartesian - to hold cartesian coordinates;
    > 3/ Coordinates3D, which holds synchronized instances of the both in
    > __p__ and __c__ fields respectively.
    >
    > I want to design Coordinates3D so that when instantiated with Polar
    > argument, self.__p__=argument passed to constructor, and self.__c__ is
    > calculated. When argument is Cartesian, self.__c__=argument, and
    > self.__p__ is calculated. Runtime type checking works, but maybe there
    > is a better way?


    Depends on what you think is "better." Checking the paramter
    types at run time is the clearest way of doing it. The only other
    way I know is to use a static method as a constructor, instantiate
    an instance of object(), change its class and initialize it to suit
    yourself.

    The biggest problem with that is that it's totally non-obvious
    unless your team does it a lot, and you've got decent naming
    conventions so you know what's happening.

    John Roth
    >
    > Thanks in advance,
    > Sergey
    >
     
    John Roth, Jun 9, 2004
    #2
    1. Advertising

  3. Sergey Krushinsky

    Peter Otten Guest

    Sergey Krushinsky wrote:

    > Hello all,
    >
    > Is there a common way to emulate constructor overloading in Python class?
    >
    > For instanse, I have 3 classes:
    > 1/ Polar - to hold polar coordinates;
    > 2/ Cartesian - to hold cartesian coordinates;
    > 3/ Coordinates3D, which holds synchronized instances of the both in
    > __p__ and __c__ fields respectively.
    >
    > I want to design Coordinates3D so that when instantiated with Polar
    > argument, self.__p__=argument passed to constructor, and self.__c__ is
    > calculated. When argument is Cartesian, self.__c__=argument, and
    > self.__p__ is calculated. Runtime type checking works, but maybe there
    > is a better way?
    >
    > Thanks in advance,
    > Sergey


    Given that Polar and Cartesian could easily grow the missing attributes via
    properties, Coordiantes3D seems to be mainly a speed hack and should not
    influence the design too much. One approach would be to make a unified
    Point class that takes keyword arguments for x, y, z, r, phi, theta and
    calculates the missing parameters either immediately in __init__() or
    lazily on attribute access (I use 2D examples througout):

    class LazyPoint(object):
    def getX(self):
    try:
    return self._x
    except AttributeError:
    self._x = self.r * math.cos(self.phi)
    return self._x
    x = property(getX)

    Another option would be to add calculated attributes, e. g. x, y, z to
    Polar, (without caching) and construct the CachingPoint aka Coordinates3D
    using these:

    class Point(object):
    """ Shared implementation for Polar, Cartesion, and CachingPoint """
    r = property(lambda self: self._r)
    phi = property(lambda self: self._phi)
    x = property(lambda self: self._x)
    y = property(lambda self: self._y)
    def __str__(self):
    return "r=%s, phi=%s, x=%s, y=%s" % \
    (self.r, self.phi, self.x, self.y)

    class Polar(Point):
    def __init__(self, r, phi):
    self._r = r
    self._phi = phi
    x = property(lambda self: self.r * math.cos(self.phi))
    y = property(lambda self: self.r * math.sin(self.phi))

    class Cartesian(Point):
    def __init__(self, x, y):
    self._x = x
    self._y = y
    r = property(lambda self: math.sqrt(self.x*self.x+self.y*self.y))
    phi = property(lambda self: math.atan2(self.y, self.x))

    class CachingPoint(Point):
    def __init__(self, point):
    # as both Polar and Cartesion support the full
    # attribute set, no type checking is needed here
    self._x = point.x
    self._y = point.y
    self._r = point.r
    self._phi = point.phi

    if __name__ == "__main__":
    p = Polar(1.0, math.pi/4.0)
    print p
    print CachingPoint(p)
    print "---"
    p = Cartesian(3.0, 4.0)
    print p
    print CachingPoint(p)
     
    Peter Otten, Jun 9, 2004
    #3
  4. Sergey Krushinsky

    Carl Banks Guest

    Sergey Krushinsky <> wrote in message news:<>...
    > Hello all,
    >
    > Is there a common way to emulate constructor overloading in Python class?
    >
    > For instanse, I have 3 classes:
    > 1/ Polar - to hold polar coordinates;
    > 2/ Cartesian - to hold cartesian coordinates;
    > 3/ Coordinates3D, which holds synchronized instances of the both in
    > __p__ and __c__ fields respectively.
    >
    > I want to design Coordinates3D so that when instantiated with Polar
    > argument, self.__p__=argument passed to constructor, and self.__c__ is
    > calculated. When argument is Cartesian, self.__c__=argument, and
    > self.__p__ is calculated. Runtime type checking works, but maybe there
    > is a better way?



    Polar and Cartesian could both have methods cart() and polar().

    x.cart() would return the cartesian representation whether x is
    Cartesian, Polar, or the Coordinates3D. If x is Polar, it makes the
    conversion.

    x.polar() would do likewise returning polar representation.

    Then, to initialize Coordinates3D, it could set _p and _c thusly:

    self._p = x.polar()
    self._c = x.cart()

    This will work regardless of whether x is a Polar or Cartesian. You
    should define these methods for Coordinates3D, too. (Note: you
    shouldn't use variables of the form __xxx__ for regular variables; see
    Naming Conventions at http://www.python.org/peps/pep-0008.html)

    OTOH, I could see why you might not want to do that. If the point of
    having three separate classes is so that you use a polar as a polar,
    then maybe you wouldn't want to have it return a cartesian. If that's
    so, then just check the types. It won't kill you.


    --
    CARL BANKS
     
    Carl Banks, Jun 9, 2004
    #4
  5. Thanks to all :)
    I realize that Coordinates3D was not a perfect example, especially in
    respect of its design. Anyway, I have learned from your postings some
    smart design concepts, which could hardly be implemented in languages
    other than Python.

    With best regards,
    Sergey
     
    Sergey Krushinsky, Jun 11, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,451
    Fredrik Lundh
    Sep 30, 2005
  2. Fredrik Lundh
    Replies:
    0
    Views:
    477
    Fredrik Lundh
    Sep 30, 2005
  3. Steve Holden
    Replies:
    0
    Views:
    453
    Steve Holden
    Sep 30, 2005
  4. Iyer, Prasad C
    Replies:
    4
    Views:
    603
    John J. Lee
    Sep 30, 2005
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,353
Loading...

Share This Page