Is this an OK design?

Discussion in 'Python' started by urnerk@qwest.net, Apr 15, 2004.

  1. Guest

    Partly because I'm doing OpenOffice PowerPoint (not much room on a slide),
    I'm breaking what could be a single class into a succession of tiny
    "version" classes, each inheriting from the one before, and each adding
    more functionality.

    I'm also separating each version into a module of its own, such that each
    successive version keeps the same name (say P), and inherits from module.P

    Part of the goal is to demonstrate inheritance, so it's OK to evolve my P
    class over several versions.

    Here's a skeletal outline, where --- separates modules:

    ---- pv1.py ----

    class P(object):
    def __init__(self, amap)
    self.amap = amap

    --- pv2.py ---

    import pv1
    class P(pv1.P):

    def __invert__(self):
    # newmap = inverted self.amap
    return P(newmap)

    def __mul__(self,other): etc.

    --- pv3.py ---

    import pv2
    class P(pv2.P):
    def __div__(self,other):
    return self * ~other

    ---

    Note that only the base class has a constructor, while the subclasses add
    additional methods.

    The above design had a problem though:

    >> import pv1, pv2, pv3
    >> from pv3 import P
    >> p1 = P(map)
    >> q = ~p1 # invokes __invert__ in pv2
    >> q/p1

    Error about / not defined for instance, instance
    >> isinstance(q,pv3.P)

    False
    >> isinstance(q,pv2.P)

    True

    The problem was __invert__, being defined in pv2, would return an instance
    of pv2.P, which doesn't yet know about __div__ (that comes in the next
    version).

    So the need is to have methods that return a P, to return a P of the same
    version, e.g. if p1 is of type pv3.P, then __invert__, even though defined
    in the parent, should return a pv3.P when invoked.

    My solution was:

    ---- pv1.py ----

    class P(object):
    def __init__(self, amap)
    self.amap = amap
    self.P = self.__class__ # <-- store type of instance

    --- pv2.py ---

    import pv1
    class P(pv1.P):

    def __invert__(self):
    # newmap = inverted self.amap
    return self.P(newmap) # <--- class is now object attribute

    def __mul__(self,other): etc.

    --- pv3.py ---

    import pv2
    class P(pv2.P):
    def __div__(self,other):
    return self * ~other

    ---

    Now when I go:

    >> from pv3 import P
    >> p1 = P(map)
    >> q = ~p1 # invokes __invert__
    >> q/p1

    <answer>
    >> isinstance(q,pv3.P)

    True
    >> isinstance(q,pv2.P)

    True

    i.e. q/p1 succeeds, because ~p1 returns a pv3.P type, which understands
    about __div__.

    What I'd like to know is: is my solution perverse or Pythonic? Is there a
    better way?

    Kirby
     
    , Apr 15, 2004
    #1
    1. Advertising

  2. wrote:
    > ---- pv1.py ----
    >
    > class P(object):
    > def __init__(self, amap)
    > self.amap = amap
    > self.P = self.__class__ # <-- store type of instance
    >
    > --- pv2.py ---
    >
    > import pv1
    > class P(pv1.P):
    >
    > def __invert__(self):
    > # newmap = inverted self.amap
    > return self.P(newmap) # <--- class is now object attribute

    ....
    > What I'd like to know is: is my solution perverse or Pythonic?
    > Is there a better way?


    Whenever I've had to do the same thing, I'd just say:

    return self.__class__(newmap)

    Or make a specialized method, like:

    def new(self, *args):
    return self.__class__(*args)

    In other words, say it directly without the indirection of a class
    attribute.

    Unless, of course, you want to modify the attribute for some
    reason. Even then, I'd change the name to be more
    self-documenting.

    -- David Goodger
     
    David Goodger, Apr 15, 2004
    #2
    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. ZackS
    Replies:
    5
    Views:
    6,829
    Just an Illusion
    Jul 9, 2004
  2. SpamProof
    Replies:
    3
    Views:
    655
    SpamProof
    Dec 1, 2003
  3. dave
    Replies:
    5
    Views:
    602
    William Brogden
    Jul 17, 2004
  4. Tim Smith
    Replies:
    2
    Views:
    864
    Tim Smith
    Dec 15, 2004
  5. trint
    Replies:
    1
    Views:
    364
    trint
    Nov 21, 2006
Loading...

Share This Page