[Tutor] instantiating subclass by parameter

Lloyd Kvam pythontutor at venix.com
Tue Oct 28 16:54:10 EST 2003


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

This doesn't need to use apply.  Simply:
	return Altavista()	# the () calls the class to get an instance
or
	return AlltheWeb()


Here you need something to hold the objects that you are creating.
      create = {'alpha': 'altavista', 'beta': 'alltheweb'}
      for key in create:
          key = factory(create[key])
The name key is bound to each object in turn and winds up bound to the
last one.  The alpha/altavista object is created and lost because it
is not bound (tied to) any name.

The folowing code where you use a dictionary named obj to hold the objects
with the specified key names (alpha, beta) looks like it should work.

What's going wrong?


Karl Fast wrote:

>>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
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 

-- 
Lloyd Kvam
Venix Corp.
1 Court Street, Suite 378
Lebanon, NH 03766-1358

voice:	603-653-8139
fax:	801-459-9582




More information about the Tutor mailing list