Need advice on subclassing code
bruno at modulix
onurb at xiludom.gro
Tue Nov 15 11:33:03 EST 2005
Rusty Shackleford wrote:
> 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:
>
(snip)
> 99% of the specific classes do the exact same thing. For a tiny few,
> the class definition looks like this:
>
(snip same code with minor differences...)
>
> 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?
No, of course - but I guess you knew it already !-)
> Is there some way of doing a default vs.
> non-default deal, without having to manually hardcode all the different
> possible subclasses?
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_live, 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 at xiludom.gro'.split('@')])"
More information about the Python-list
mailing list