Need advice on subclassing code

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rusty Shackleford

    #1

    Need advice on subclassing code

    Hi --

    We have some code that returns an object of a different class, depending
    on some parameters. For example:

    if param x is 1 and y is 1, we make an object of class C_1_1.
    if param x is 1 and y is 2, we make an object of class C_1_2.

    C_1_1 and C_1_2 share a common C ancestor, and in practice may be
    identical, but theoretically, could have the same function name with two
    different implementations underneath.

    We have a file where all the C_X_Y classes are defined. It looks sort
    of like this:

    class C_1_1(C):
    """Creates a x=1 and y=1 class"""
    def __init__(self):
    C.__init__(self , 1, 1)

    class C_1_2(C):
    """Creates a x=1 and y=2 class"""
    def __init__(self):
    C.__init__(self , 1, 2)

    99% of the specific classes do the exact same thing. For a tiny few,
    the class definition looks like this:

    class C_3_5(C):
    """Creates a x=3, y=5 class."""
    def __init__(self):
    C.__init__(self , 3, 5)

    def foo(self):
    """Redefine the default C.foo() function."""
    return 99

    The reason for this is that we want to allow different classes to do
    non-standard behavior. In practice, however, it turns out that most of
    the time, we don't need anything special.

    Is this the best solution? Is there some way of doing a default vs.
    non-default deal, without having to manually hardcode all the different
    possible subclasses?

    Thanks for the help.

    --
    A better way of running series of SAS programs:

  • wittempj@hotmail.com

    #2
    Re: Need advice on subclassing code

    Would the approach of using a switch to decide to instatite which class
    good for you, like:

    py> class C:
    py. name = 'C'
    py.
    py> class D:
    py. name = 'D'
    py.
    py> switch = { (1, 1): C, (1,2): D }
    py> x = 1
    py> y = 2
    py> c = switch[(x,y)]()
    py> print c.name
    D
    py>

    Comment

    • bruno at modulix

      #3
      Re: Need advice on subclassing code

      Rusty Shackleford wrote:[color=blue]
      > Hi --
      >
      > We have some code that returns an object of a different class, depending
      > on some parameters. For example:
      >
      > if param x is 1 and y is 1, we make an object of class C_1_1.
      > if param x is 1 and y is 2, we make an object of class C_1_2.
      >
      > C_1_1 and C_1_2 share a common C ancestor, and in practice may be
      > identical, but theoretically, could have the same function name with two
      > different implementations underneath.
      >
      > We have a file where all the C_X_Y classes are defined. It looks sort
      > of like this:
      >[/color]
      (snip)
      [color=blue]
      > 99% of the specific classes do the exact same thing. For a tiny few,
      > the class definition looks like this:
      >[/color]
      (snip same code with minor differences...)[color=blue]
      >
      > The reason for this is that we want to allow different classes to do
      > non-standard behavior. In practice, however, it turns out that most of
      > the time, we don't need anything special.
      >
      > Is this the best solution?[/color]

      No, of course - but I guess you knew it already !-)
      [color=blue]
      > Is there some way of doing a default vs.
      > non-default deal, without having to manually hardcode all the different
      > possible subclasses?[/color]

      Here are the pieces of the puzzle:
      - A dict is usually the best choice for lookups.
      - A tuple can serve as key for a dict.
      - A (reference to) a class object can be stored in a dict (or the name
      of the class, as a string).
      - the get() method of a dict allow for an optional default value to be
      use if the requested key is not found

      And here's a first go:

      def get_object(x, y):
      specials = {
      (1, 2): C_1_2,
      (33, 42): C_33_42,
      }
      # assume class C is the default class
      klass = specials.get((x , y), C)
      return klass()

      Now if you store the class names as strings, ie :


      specials = {
      (1, 2): "C_1_2",
      (33, 42): "C_33_42",
      }

      you can use a config file (ini, XML, Yaml, or even plain old python) to
      store the 'specials' mapping and the default class name, and have
      get_object() read from that config file. The trick is to get the class
      from the class's name, which is solved with getattr():

      def get_object(x, y):
      specials = {
      (1, 2): "C_1_2",
      (33, 42): "C_33_42",
      }
      # assume class 'C' is the default class
      class_name = specials.get((x , y), "C")

      # from class name to class:
      klass = getattr(module_ where_classes_l ive, class_name)
      return klass()


      I think you should be able to solve your problem with this.

      A last thing: the name of the module storing the classes can also be
      stored in a conf file. Use __import__() to get the module object from
      it's name.


      HTH
      --
      bruno desthuilliers
      python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
      p in 'onurb@xiludom. gro'.split('@')])"

      Comment

      • Kent Johnson

        #4
        Re: Need advice on subclassing code

        Rusty Shackleford wrote:[color=blue]
        > Hi --
        >
        > We have some code that returns an object of a different class, depending
        > on some parameters. For example:
        >
        > if param x is 1 and y is 1, we make an object of class C_1_1.
        > if param x is 1 and y is 2, we make an object of class C_1_2.
        >
        > C_1_1 and C_1_2 share a common C ancestor, and in practice may be
        > identical, but theoretically, could have the same function name with two
        > different implementations underneath.
        >
        > We have a file where all the C_X_Y classes are defined.
        > Is this the best solution? Is there some way of doing a default vs.
        > non-default deal, without having to manually hardcode all the different
        > possible subclasses?[/color]

        How are you instantiating the correct class? You should be able to provide a default behaviour. For example if the classes are all defined in module C you could have a factory like this:

        import C
        def makeC(x, y):
        subtype = 'C_%d_%d' % (x, y)
        cls = getattr(C, subtype, C.C)
        return cls(x, y)

        Then in module C just define the subtypes you need to specialize; all other values of x and y will get the base class C.C.

        Kent

        Comment

        • Michael Spencer

          #5
          Re: Need advice on subclassing code

          Kent Johnson wrote:[color=blue]
          > Rusty Shackleford wrote:[color=green]
          >> ...
          >> C_1_1 and C_1_2 share a common C ancestor, and in practice may be
          >> identical, but theoretically, could have the same function name with two
          >> different implementations underneath.
          >>
          >> ...[/color]
          >
          > How are you instantiating the correct class? You should be able to provide a default behaviour. For example if the classes are all defined in module C you could have a factory like this:
          >
          > import C
          > def makeC(x, y):
          > subtype = 'C_%d_%d' % (x, y)
          > cls = getattr(C, subtype, C.C)
          > return cls(x, y)
          >
          > Then in module C just define the subtypes you need to specialize; all other values of x and y will get the base class C.C.
          >
          > Kent[/color]

          Or, if you actually want different classes for each set of parameters (say for
          debugging or introspection), you could compose the default ones on the fly:


          import C
          def makeC(x, y):
          subtype = 'C_%d_%d' % (x, y)
          cls = getattr(C, subtype, None)
          if not cls:
          # No specialized class found, so compose a default
          # This requires C.C to be a new-style class
          cls = type(subtype, (C.C,), {"__autogenerat ed__": True})
          return cls(x, y)

          Michael



          Comment

          Working...