470,600 Members | 1,466 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,600 developers. It's quick & easy.

dynamic class/module use? (like Java's forName)

Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.

As a pseudocode example, I'm looking for the following ability:
classIWantToInstantiate = "packagenamehere.classNameHere"

anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
parameters[])

# now anInstanceOfThatClass refers to an instantied
# packagenamehere.classNameHere object!

thanks
alex
Jul 18 '05 #1
14 2021
Alex Hunsley wrote:
Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.

As a pseudocode example, I'm looking for the following ability:
classIWantToInstantiate = "packagenamehere.classNameHere"

anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
parameters[])

# now anInstanceOfThatClass refers to an instantied
# packagenamehere.classNameHere object!

thanks
alex


Oops.. I goggled but not hard enough obviously! I found my answer on
google groups:

http://shorterlink.com/?N2HPGU

alex
Jul 18 '05 #2
In article <_O*****************@fe2.news.blueyonder.co.uk>,
Alex Hunsley <la**@tardis.ed.ac.molar.uk> wrote:
Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.


Just out of curiosity, why do you want to do that?

The google link you provided talked about eval and exec. My experience
is that when I first started using Python (about 7 years ago), I used
eval and exec a lot. Now, I can't remember the last time I ever wanted
to use either.

Can you give us an example of what you're trying to do? My guess,
having not yet seen it, is that there's probably a better way to do it
than what you're asking.
Jul 18 '05 #3
On Sat, 17 Jul 2004 18:00:26 GMT, rumours say that Alex Hunsley
<la**@tardis.ed.ac.molar.uk> might have written:
Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.


[snip]

Have you already considered the 'new' module? If not, give it a try.
--
TZOTZIOY, I speak England very best,
"Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek
Jul 18 '05 #4
Roy Smith wrote:
In article <_O*****************@fe2.news.blueyonder.co.uk>,
Alex Hunsley <la**@tardis.ed.ac.molar.uk> wrote:

Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.

Just out of curiosity, why do you want to do that?

The google link you provided talked about eval and exec. My experience
is that when I first started using Python (about 7 years ago), I used
eval and exec a lot. Now, I can't remember the last time I ever wanted
to use either.

Can you give us an example of what you're trying to do? My guess,
having not yet seen it, is that there's probably a better way to do it
than what you're asking.


Ok, the situation is that I am parsing a file that has "actions" (or
commands) embedded in it. Different actions cause different things to
happen to the file which is being preprocessed for something. Now, since
I will have many actions, and want my python to be extensible so other
users can add their own actions, rather than hard coding each action
like so:

if (actionString == "blah"):
blahThang = blah(constructor stuff)
blahThang.doSomething()
else if (actionString == "blah2"):
blahThang2 = blah2(constructor stuff)
blahThang2.doSomething()
else if (actionString == "blah3"):
blahThang3 = blah3(constructor stuff)
blahThang3.doSomething()
else if (actionString == "blah2"):
# etc etc

.... I can have a different python class (and hence source file) for each
action, and the code for launching an action becomes generic (i.e.
creates instance of the class based on the command string and calls
agreed methods on it). I prefer this to the altyernative of hardcoding
each action with an 'if', as above, and then getting another user who
wants to extend my project have to add yet another if clause as well as
some code.
Another advantage of this generic approach is that it encourages other
users extending my code to put actions in seperate files, one per
action, rather than adding 'magic' code into the above 'if' chaos.

Basically, modular actions is the idea!

I'd be keen to hear peoples thoughts on my approach.

thanks
alex


Jul 18 '05 #5
Roy Smith wrote:
In article <_O*****************@fe2.news.blueyonder.co.uk>,
Alex Hunsley <la**@tardis.ed.ac.molar.uk> wrote:

Does python provide a way to dynamically use modules and/or classes?
I'm thinking in the vein of Java's Class.forName.

Just out of curiosity, why do you want to do that?


p.s. to my last response:

I've just read Robert Brewer's reply, and to rephrase myself as I to
him: I'm trying to do the strategy pattern in a modular fashion. (i.e.
no big string of 'ifs' and hardcoded actions.)

alex
Jul 18 '05 #6

"Alex Hunsley" <la**@tardis.ed.ac.molar.uk> wrote in message
news:8g******************@fe2.news.blueyonder.co.u k...

if (actionString == "blah"):
blahThang = blah(constructor stuff)
blahThang.doSomething()
else if (actionString == "blah2"):
blahThang2 = blah2(constructor stuff)
blahThang2.doSomething()
else if (actionString == "blah3"):
blahThang3 = blah3(constructor stuff)
blahThang3.doSomething()
else if (actionString == "blah2"):
# etc etc


The Python idiom for something like the above is to use a dict instead of
if/else.
It is especially useful when you want to add alternatives at runtime.
Something like

actions = { 'blah':blah, 'blah2', blah2, 'blah3':blah3, ...}
# easily extended at runtime
....
actions[actionString](constructor_stuff).doSomething

Terry J. Reedy

Jul 18 '05 #7
"Alex Hunsley" <la**@tardis.ed.ac.molar.uk> wrote in message
news:8g******************@fe2.news.blueyonder.co.u k...
<snip>
Ok, the situation is that I am parsing a file that has "actions" (or
commands) embedded in it. Different actions cause different things to
happen to the file which is being preprocessed for something. Now, since
I will have many actions, and want my python to be extensible so other
users can add their own actions, rather than hard coding each action
like so:

if (actionString == "blah"):
blahThang = blah(constructor stuff)
blahThang.doSomething()
else if (actionString == "blah2"):
blahThang2 = blah2(constructor stuff)
blahThang2.doSomething()
else if (actionString == "blah3"):
blahThang3 = blah3(constructor stuff)
blahThang3.doSomething()
else if (actionString == "blah2"):
# etc etc

<snip>

Alex,

Have a look at how pyparsing (http://pyparsing.sourceforge.net) supports the
attachment of actions to parse expressions within a grammar.

-- Paul
Jul 18 '05 #8
Roy Smith <ro*@panix.com> writes:

Just out of curiosity, why do you want to do that?


in order to be more flexible,
allowing code to be integrated that is available
only at run time of the program

Klaus Schilling
Jul 18 '05 #9
Terry Reedy wrote:
"Alex Hunsley" <la**@tardis.ed.ac.molar.uk> wrote in message
news:8g******************@fe2.news.blueyonder.co.u k...
if (actionString == "blah"):
blahThang = blah(constructor stuff)
blahThang.doSomething()
else if (actionString == "blah2"):
blahThang2 = blah2(constructor stuff)
blahThang2.doSomething()
else if (actionString == "blah3"):
blahThang3 = blah3(constructor stuff)
blahThang3.doSomething()
else if (actionString == "blah2"):
# etc etc

The Python idiom for something like the above is to use a dict instead of
if/else.
It is especially useful when you want to add alternatives at runtime.
Something like

actions = { 'blah':blah, 'blah2', blah2, 'blah3':blah3, ...}
# easily extended at runtime
...
actions[actionString](constructor_stuff).doSomething

Terry J. Reedy


Interesting, I hadn't thought of using a dict.
Using a dict would be better than 'if's, but would still require a
central part of the code to know about all the actions!
My way allows new classes to be presented and used without altering
existing code.
Also my method forces new actions to interface with 'central' code via
the available official interface, rather than having new actions
potentially put in the central code and hence have access to things
directly (which isn't a good OO design).

Jul 18 '05 #10
Paul McGuire wrote:
"Alex Hunsley" <la**@tardis.ed.ac.molar.uk> wrote in message
news:8g******************@fe2.news.blueyonder.co.u k...
<snip>
Ok, the situation is that I am parsing a file that has "actions" (or
commands) embedded in it. Different actions cause different things to
happen to the file which is being preprocessed for something. Now, since
I will have many actions, and want my python to be extensible so other
users can add their own actions, rather than hard coding each action
like so:

if (actionString == "blah"):
blahThang = blah(constructor stuff)
blahThang.doSomething()
else if (actionString == "blah2"):
blahThang2 = blah2(constructor stuff)
blahThang2.doSomething()
else if (actionString == "blah3"):
blahThang3 = blah3(constructor stuff)
blahThang3.doSomething()
else if (actionString == "blah2"):
# etc etc
<snip>

Alex,

Have a look at how pyparsing (http://pyparsing.sourceforge.net) supports the
attachment of actions to parse expressions within a grammar.

-- Paul

Interesting, Paul! thanks for link.
lex

Jul 18 '05 #11
On Sat, 17 Jul 2004, Alex Hunsley wrote:
classIWantToInstantiate = "packagenamehere.classNameHere"

anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
parameters[])

# now anInstanceOfThatClass refers to an instantied
# packagenamehere.classNameHere object!


getattr is probably the best way to go about this:

packagename,classname = classIWantToInstantiate.split('.')
myclass = getattr(locals()[packagename], classname)

Or, if you want to support nested classes:

classnames = classIWantToInstantiate.split('.')
myclass = locals()[classnames[0]]
for classname in classnames[1:]:
myclass = getattr(myclass, classname)

Then you can just instantiate the class with myclass().

(Question for those in the know: why isn't there a way you can reference
the current module, i.e. so getattr(current_module,something) would be
equivalent to locals()[something]?)

Jul 18 '05 #12
Am Sonntag, 18. Juli 2004 20:52 schrieb Alex Hunsley:
Interesting, I hadn't thought of using a dict.
Using a dict would be better than 'if's, but would still require a
central part of the code to know about all the actions!
My way allows new classes to be presented and used without altering
existing code.
Also my method forces new actions to interface with 'central' code via
the available official interface, rather than having new actions
potentially put in the central code and hence have access to things
directly (which isn't a good OO design).


What I always do when I'm in your position to have an extendable API is to
create a Registry with which the possible actions can register, a general
parsing engine, which just does a dictionary lookup on some word (the
dictionary being maintained by the module which contains the Registry), and
then calls of into the appropriate code. All other modules can also use the
Registry.

Something like this:

====
Registry.py

pluginDict = {}

def registerPlugin(name,plugincallable):
pluginDict[name] = plugincallable

def queryPlugin(name):
return pluginDict[name]()

====
Plugins/__init__.py

pass

====
Plugins/Module1.py

import Registry

class Callable1(object):
def __init__(self):
print "Instantiating Callable1."

def test_method(self,*args,**kwargs):
print "In test_method."
print args, kwargs

Registry.register("callable1",Callable1)

====
Plugins/Module2.py

import Registry

class Callable2(object):
def __init__(self):
print "Instantiating Callable2."

Registry.register("callable2",Callable2)

====
Plugins.py

import os

for fname in os.listdir("Plugins"):
try:
__import__("Plugins.%s" % fname[-3],globals(),locals(),[])
except:
print "Warning: Couldn't import plugin:", fname

====
Main.py

import Registry
import Plugins

mod1 = Registry.queryPlugin("callable1")
print mod1
mod2 = Registry.queryPlugin("callable2")
print mod2

====
ParseCommand.py

import Registry

command = "callable1.test_method test 123 how are you?"
cmd = command.split(" ")
mod, attr = cmd[0].split(".",1)
mod = Registry.queryPlugin(mod)
getattr(mod,attr)(*cmd[1:])
This code only requires you to put all plugin modules into the subdirectory
Plugins of the main program directory, and could easily be extended by
rewriting Plugins.py to accomodate on demand loading/reloading of plugins,
etc. ParseCommand.py can also easily be made more "intelligent" concerning
the parsing of the actual command-line.

Is this extensible enough? ;)

HTH!

Heiko.
Jul 18 '05 #13
Am Montag, 19. Juli 2004 19:54 schrieb Heiko Wundram:
...
Something like this:
Err, that code was untested, please substitute:
====
Plugins/Module1.py

import Registry

class Callable1(object):
def __init__(self):
print "Instantiating Callable1."

def test_method(self,*args,**kwargs):
print "In test_method."
print args, kwargs
- Registry.register("callable1",Callable1)
+ Registry.registerPlugin("callable1",Callable1)
====
Plugins/Module2.py

import Registry

class Callable2(object):
def __init__(self):
print "Instantiating Callable2."

- Registry.register("callable2",Callable2)
+ Registry.registerPlugin("callable2",Callable2)

....

HTH!

Heiko.
Jul 18 '05 #14
Am Montag, 19. Juli 2004 19:54 schrieb Heiko Wundram:
Something like this:
And another bug... Hmmm... I should never post code which I don't intend to
test in the interpreter...
====
ParseCommand.py

import Registry

+ import Plugins

....

Heiko.
Jul 18 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Roger Vandervort | last post: by
8 posts views Thread by Fu Bo Xia | last post: by
2 posts views Thread by Vijay Singh | last post: by
3 posts views Thread by Jeff Poste | last post: by
4 posts views Thread by vasavimaruthi | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.