tom fowle
tom fowle

Reputation: 1

How do I access ephem.body fields using python and pyephem and getattr() method?

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

Answers (2)

Brandon Rhodes
Brandon Rhodes

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.

  1. For the events like 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.
  2. Especially when doing 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.
  3. Instead of stacking the two 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

Barmar
Barmar

Reputation: 782409

Just call getattr() again.

for a in altaz:
    print(a, getattr(getattr(ephem,body)(o), a)

Upvotes: 0

Related Questions