[Tutor] instantiating subclass by parameter

Karl Fast karl.fast at pobox.com
Tue Oct 28 15:58:14 EST 2003


> You can have a "factory" function that calls the proper class

Ahh, a factory function is what I need. Being new to python and
somewhat new to OOP I wasn't aware of the factory thing. Was trying
to replicate a CPAN perl module that works like I described.

It works. Here's a cookbook style writeup.

However, I still have one small question (at the very end).


PROBLEM:

You've got a class with various subclasses and you want some generic
code that will instantiate the proper subclass based on a variable
instead of a classname.

A SOLUTION:

You need a factory function. The following code has a master class
(WebSearch) with two subclasses (Altavista, AlltheWeb). 

You can create new objects by calling these classes directly. But
the point is to call the factory function instead which returns an
an object instance based on the keyword you supply.


class WebSearch:
   def __init__(self, engine):
       self.name = engine
         
   def foo(self):
       return "inherited foo"
         
   def bar(self):
       return "inherited bar"
         
class Altavista(WebSearch):
   def __init__(self):
       WebSearch.__init__(self, 'altavista')
         
   def foo(self):
       return "altavista foo"
         
class AlltheWeb(WebSearch):
   def __init__(self):
       WebSearch.__init__(self, 'alltheweb')
         
   def bar(self):
       return "alltheweb bar"

def factory (engine):
   if engine == 'altavista':
       return apply(Altavista)
   elif engine == 'alltheweb':
       return apply(AlltheWeb)

if __name__ == '__main__':
   alpha = factory('altavista')
   beta  = factory('alltheweb')
   print "alpha.name  = %s" % alpha.name
   print "alpha.foo() = %s" % alpha.foo()
   print "alpha.bar() = %s" % alpha.bar()  
   print "beta.name   = %s" % beta.name
   print "beta.foo()  = %s" % beta.foo()
   print "beta.foo()  = %s" % beta.bar()  

If you run this you'll get the following, which is what you want:
   
   alpha.name  = altavista
   alpha.foo() = altavista foo
   alpha.bar() = inherited bar
   beta.name   = alltheweb
   beta.foo()  = inherited foo
   beta.foo()  = alltheweb bar


QUESTION, if anyone read this far....   

Instead of doing this:

   alpha = factory('altavista')
   beta  = factory('alltheweb')

I'd rather have a dict with the desired object names and use that to
call the factory function. Kinda like this (which doesn't work).

     create = {'alpha': 'altavista', 'beta': 'alltheweb'}
     for key in create:
         key = factory(create[key])

The assignment clearly fails. The idea is to wind up with objects
called alpha and beta, which you can do things like alpha.foo() and
beta.name.
         
My current solution is to build a dict of objects created by the
factory, where the keynames are the desired object names.

     create = {'alpha': 'altavista', 'beta': 'alltheweb'}
     obj = {}
     for key in create:
         obj[key] = factory(create[key])
     for key in obj:
         print obj[key]
         print obj[key].name
         print obj[key].foo()
         print obj[key].bar()
                                               
Again, I suspect there is an easy answer, I'm just lacking enough
knowledge of python.

--karl



More information about the Tutor mailing list