Reputation: 1
I am happy with the first part of my code which displays location events OK.
The second part, which uses the eval() method as well as getattr() to display ephem.Body() fields, seems 'unpythonic' to me, and perhaps a little clunky.
Is there a better way of using getattr() without invoking eval() as well to display the Body() fields ?
import ephem
o = ephem.Observer()
o.lat, o.long = '-38','144'
o.date = ephem.now()
# first part
body = getattr(ephem,'Sun')()
events = ['next_rising','next_transit']
for event in events:
print(event,getattr(o,event)(body))
# second part
body = 'Sun'
altaz = ['alt','az']
for a in altaz:
print(a,eval('getattr(ephem,body)(o).' + a))
Upvotes: 0
Views: 144
Reputation: 89565
Another answer has already pointed out that getattr()
can be called twice, but stacking two getattr()
calls on top of each other is a bit harder to read than typical ‘Pythonic’ code, so here are a few more thoughts.
next_rising
, note that getattr()
isn't necessary — object methods are first-class objects in Python, so if you wanted you could just put the methods themselves in your list. You would then have to ask them their __name__
, though, to see which is which.getattr()
, code can get very confusing if you don't distinguish a thing from the name of that thing. So, if what you have isn't a body but the name of the body like 'Sun'
, then call it body_name
— that will make it clearer in the code that body_name
can only do the things a string can do in Python, but can't do any of the things a PyEphem body can do.getattr()
calls into a single line, use several lines, giving useful names to the intermediate results.For more about naming, see my talk The Naming of Ducks, on which my advice here is based. Here's how your code might look afterwards:
import ephem
o = ephem.Observer()
o.lat, o.long = '-38','144'
o.date = ephem.now()
body_name = 'Sun'
# first part
body = getattr(ephem, body_name)()
events = [o.next_rising, o.next_transit]
for event in events:
print(event.__name__, event(body))
# second part
altaz = ['alt', 'az']
for a in altaz:
BodyClass = getattr(ephem, body_name)
body = BodyClass(o)
print(a, getattr(body, a))
Upvotes: 1
Reputation: 782409
Just call getattr()
again.
for a in altaz:
print(a, getattr(getattr(ephem,body)(o), a)
Upvotes: 0