I can't seem to find a way to do something that seems straighforward, so I
must have a mental block. I want to reference an object indirectly
through a variable's value.
Using a library that returns all sorts of information about "something", I
want to provide the name of the "something" via a variable (command line
argument). The something is a class in the library and I want to
instantiate an object of the class so I can start querying it. I can't
figure out how to pass the name of the class to the library.
Or, put another way, I can't figure out how to indirectly reference the
value of the command line argument to create the object.
To make it clearer, it's roughly equivalent to this in bash:
Sun="1AU" ; body=Sun; echo ${!body} --> outputs "1AU".
command line:
$ ./ephemeris.py Moon
code:
import ephem
import optparse
# various option parsing (left out for brevity),
# so variable options.body contains string "Moon",
# or even "Moon()" if that would make it easier.
# Want to instantiate an object of class Moon.
# Direct way:
moon1 = ephem.Moon()
# Indirect way from command line with a quasi bashism that obviously fails:
moon2 = ephem.${!options.body}()
Can someone point me in the right direction here?
(The library is PyEphem, an extraordinarily useful library for anyone
interested in astronomy.)
Many thanks,
--
NickC
A direct way is to use:
moon1 = getattr(ephem, 'Moon')()
hth
Jon.
Since Python 'variables' are really keys in a namespace dictionary, it's
fairly straightforward to get at them given a string value -- what you
probably want in this case is the built-in function getattr()
(http://www.diveintopython.org/power_of_introspection/getattr.html)...
So getattr(ephem, "Moon") should give you the class object ephem.Moon,
which you can then instantiate...
--
Rami Chowdhury
"Never attribute to malice that which can be attributed to stupidity" --
Hanlon's Razor
408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)
>>> name='Moon'
>>> m2 = getattr(ephem,name)()
>>> m2.compute(home)
>>> print ephem.localtime(m2.rise_time)
2009-11-11 01:30:36.000002
shows the moon will rise at 1:30am localtime tonight at my home location.
Excellent.
--
NickC
> moon2 = ephem.${!options.body}()
moon2 = getattr(ephem, options.body)()
You can get a little more versatile and even specify the location of
the name (i.e. the module / package name) without pre-importing it,
like this...
def importName(modulename, name=None):
""" Import identifier C{name} from module C{modulename}.
If name is omitted, modulename must contain the name after the
module path, delimited by a colon.
@param modulename: Fully qualified module name, e.g. C{x.y.z}.
@param name: Name to import from C{modulename}.
@return: Requested object.
@rtype: object
"""
if name is None:
modulename, name = modulename.split(':', 1)
module = __import__(modulename, globals(), {}, [name])
return getattr(module, name)
print importName("socket:gethostname")()
This is especially useful if you want to specify factory classes or
the like in a non-python config file. The syntax is the same as that
of setuptools entry points.