accessor/mutator functions

Andrew Dalke dalke at dalkescientific.com
Mon Feb 28 21:27:03 EST 2005


Me:
>> What's wrong with the use of attributes in this case and how
>> would you write your interface?

Dan Sommers:
> I think I'd add a change_temperature_to method that accepts the target
> temperature and some sort of timing information, depending on how the
> rest of the program and/or thread is structured.

Hmmm.  I wonder if this is mostly a question of how the
process decomposition occurs.  I think in objects ("thingys
with state") whereas you think in tasks ("thingys that do stuff")?
I say that somewhat surprisingly in that I'm not a deep OO
person - functions are fine with me and I don't like the
Java/Ruby "everything is in a class" world view.

> It might turn into two
> or three methods, depending on whether I can afford to block while
> waiting, or what kind of intermediate feedback and/or error handling I
> want (or one method with some carefully chosen default arguments).

In the case I'm hypothesizing (haven't worked with a temperature
controller in about 15 years) it's hard to put a layer above
everything because there could be so many different protocols
(chemical protocols, not I/O ones) with different rates.  Eg,
it could be an exponential decay, or step-wise approximation
thereof.

The note about errors is interesting.  For example, if the
cable to the controller was disconnected then someone, especially
someone used to memory lookups for attributes, might not expect

  temp_controller.current

to possibly raise an I/O error exception.  On the other hand,
at the C level that could be memory mapped I/O, so that

  int x = temp_controller.current;

could also have all sorts of side effects.  That case
is dangerous in C because of its poor exception mechanism.
I think in Python it's much less of a problem.


> I don't know how that device driver works, but it might look something
> like this:
> 
>     def change_temperature_to( self, target, seconds_between_checks ):
>         print 'target temperature:', target
>         tell_the_device_to_change( )
>         while 1:
>             current = read_the_temperature_from_the_device( )
>             print 'current temperature:', current
>             if abs( current - target ) < 0.1:
>                 break
>             time.sleep( seconds_between_checks )

Your "tell_the_device_to_change" is my "self.target" and your
"read_the_temperature_from_the_device" is "self.current_temperature".
In some sense it comes down to style.

BTW, had I done this for real I would have two layers, one
which is communications oriented ("send 'get current temperature'
message to device") and my object model which uses the messaging
interface underneath.

>  I think part of my thinking
> comes from my old Pascal days, when it made me cringe to think that
> "x:=b;" might actually execute a subroutine rather than just copy some
> memory around.

To give a more recent example for me, which I covered here some
years back, I wrote an OO interface to an "OO-ish" C library
for doing chemistry.  In the data model, atoms have an atomic
symbol, a charge and a list of bonds (and many other things).
Bonds have a bond type and the two atoms at the ends of the bonds
(and many other things).

I liked being able to say:

print atom.symbol, "with charge", atom.charge, "has", \
      len(atom.bonds), "bonds"

for i, bond in enumerate(bonds):
  print "bond", i, "has type", bond.bondtype

To me this is a very natural way of querying the data and
traversing the data structure.

Now underneath the covers it looks like this:

  atom.charge fails so use __getattr__(atom, "charge")
  __getattr__ uses a dispatch table to get the underlying C function
      which is "dt_getcharge"
  return dt_getcharge(self.handle)

where "handle" is the handle used by the C library.

I figured though that this example might be more esoteric
than my PID controller example, though in retrospect it
looks like it might be a better justification.

			Andrew
			dalke at dalkescientific.com




More information about the Python-list mailing list