selecting base class from user input

danielx danielwong at berkeley.edu
Mon Aug 14 17:07:05 EDT 2006


Jackson wrote:
> Thanks for the reply.
>
> danielx wrote the following on 2006-08-13 19:49:
> > Is your declaration of ABC supposed to have some_super as one of the
> > base classes? Your constructor has some_super as a parameter. What is
> > this supposed to mean in light of the declaration for ABC?
>
> Indeed, my goal is to have the base class of ABC determined dynamically
> via a parameter passed into the constructor.
> >
> > If you are trying to customize the base class of ABC by passing an
> > argument to the constructor of ABC, you should probably reconsider. If
> > constructing one instance of ABC can change ABC (the class) itself,
> > then the behavior of other instances will be affected as well. No
> > programmer can stay sane if he creates instances of a class that could
> > suddenly change its behavior (due to someone else's code).
>
> Fortunately, the ABC class is not very useful.  In fact, it was mostly
> just to be used to store particular examples of the user-specified base
> class.  So all method calls would be from the base class only.
>
> >
> > What you could do instead is to create a function which constructs
> > classes based on the arguments it recieves. Then, you'll be able to
> > create instances of the generated classes (all this meta-thinking is
> > huring my brain ;). I am talking about something like this:
> >
> > def createClass(name, base):
> >   exec "class %s(%s): pass" % (name, base)
> >   return eval( "name" )
>
> In fact, this is exactly what I ended up doing.
>
> def example(base):
>   if base == SomeClass:
>     # call SomeClass.__init__(self)
>     # build example as it would look in SomeClass
>
>   elif base == SomeOtherClass:
>     # call SomeOtherClass.__init__(self)
>     # build example as it would in SomeOtherClass
>
> > Can you please tell us why you are doing this? My curiosity is killing
> > me!
> >
>
> So here is a good example:
>
> I have 4 classes:
>
> Lion(Animal):
> Ant(Animal):
> Bee(Animal):
> Human(Animal):
>
> which are all subclasses of some superclass called Animal.  Now I want
> to define an occupation. For example, Worker.  A worker can exist as any
> of the 4 classes above.  Their constructors are different and I might
> want to add certain features.
>
> My first thought was to create a class called "Worker" and have the base
> class determined by a variable which is passed into the constructor.

What you should keep in mind though, is the "is-a" relationship that
subclasses are supposed to have with their parents. "worker is a lion"
does not make sense. What you want instead is LionWorker. You'll end up
doing only a little more typing than if you had a general Worker class,
but I don't think it will be much more.

If your *Worker classes have really simple bodies, you might be able to
automate the creation of your *Worker classes by doing something like
the createClass function (ie, by creating the classes dynamically
instead of using the class statement).

I also discovered another way to dynamically create classes, described
in this article (the article talks about other things as well):

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html

I'm not sure if this will help you, but it's definitely interesting.

> Most of the method calls will come from the Animal superclass anyway,
> but some method calls might come from the Lion class, for example.
>
> Now I realize this would drive a programmer crazy...because a Lion might
> have a roar() method whereas a Human might have a holler() method. But
> so long as the user knew which argument they passed in, it shouldn't be
> too difficult to keep track of it.
>
> So for example (again, I know what I am typing doesn't actually work)...
>
> Worker(some_animal):
>   def __init__(self,some_animal):
> 	# change the base class to some_animal
>
> 	if some_animal == Lion:
> 		# give the lion a big mane
>
> 	if some_animal == Ant:
> 		# make the ant dumb
>
> 	if some_animal == Bee:
> 		# make the bee know how to dance
>
> 	if some_animal == Human
> 		# give the human a hardhat
>
>   def work(self, hours):
> 	# tell the animal to work for the specified number of hours
> 	if some_animal == Lion:
> 		self.cat_nap(hours)
> 	if some_animal == Ant:
> 		self.walk_back_and_forth(hours)
> 	if some_animal == Bee:
> 		self.buzz_and_dance(hours)
> 	if some_animal == Human:
> 		self.use_hammer_on_coworker(hours)
> 	# notice, a Human does not have a cat_nap method
>
>   def take_lunch(location):
>
> ....
>
> and so on. So the thought is that a Worker can exist in many different
> forms: as a lion, as an ant, as a bee, and as a human.  And I might want
> a single worker class that represents them all.
>
> Hopefully this makes sense.
>
> > Another meta-thought: Hopefully I've beaten everyone else to the punch
> > about that question. Is it just me, or will a reply with such a
> > question always tell the original poster that what he wants to do MUST
> > be flawed? I hope I have been gentler than this.
> >
>
> :-) There is no need to be too gentle.  We are all here to learn (or
> help).  So I am fairly happy with the def solution...any comments on

True, but that doesn't mean you have to stand a rude response. I'm just
hoping for a little more courtesy than what I've seen.

> this? But a Worker is an noun, and it seems like the proper way to do
> this is to make the Worker into a class...so that I can define methods
> like "work", "take_lunch", etc.  However, I have no idea how I should do
> this.  Perhaps someone can recommend a procedure.
> 
> thanks.




More information about the Python-list mailing list