[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