Another newbie question

Mike Meyer mwm at mired.org
Thu Dec 8 20:46:33 EST 2005


Steven D'Aprano <steve at REMOVEMEcyber.com.au> writes:
> Paul Rubin wrote:
>> Steven D'Aprano <steve at REMOVETHIScyber.com.au> writes:
>>>> Yes. Reaching through objects to do things is usually a bad idea.
>>>I don't necessarily disagree, but I don't understand why you say this. Why
>>>it is bad?
>> The traditional OOP spirit is to encapsulate the object's entire
>> behavior in the class definition.
> Uh huh. Say I have:
>
> class Coordinate:
>      def __init__(self, x=0.0, y=0.0):
>          self.x = x
>          self.y = y
>
> pt = Coordinate(1.0, 2.5)
> Presumably then I also need add_y_ord, sub_y_ord, rsub_y_ord,
> div_y_ord, and so on for every method that floats understand, plus
> *another* set of methods that do the same thing for the x
> ordinate. And in every case, these Coordinate methods are trivial
> one-liners.
> Do people really do this?

Yes, but usually with better API design. For instance, your Coordinate
class might have scale, translate, rotate and move methods. These are
still relatively simple, but they aren't one-liners. The import thing
is that these methods capture common, Coordinate-level operations and
bundle them up so that clients don't have to, for instance, do the
trig needed to rotate a point themselves. They can just use the rotate
method.

> Yes, I could encapsulate the lot with a factory function that applied
> a specified operator to a specified attribute, and populate the class
> at runtime. But why would I want to?

You don't. You're thinking about things at the wrong level. You don't
want to think about "things you do to a Coordinate's attribute". You
want to think about "things you do to a Coordinate".

> Now, as I see it, the whole point of encapsulation is that you *don't*
> need to fill your class definition with meaningless helper
> functions.

Correct. That's where you went wrong - your methods were essentially
meaningless. They just manipulated the attributes, not the
Coordinate. Your methods should be meaningful for the object, not just
the attributes.

> If an attribute of a instance is a float, you can just call
> float methods on the attribute and it should work. If the attribute is
> a list, list methods will work. If the attribute is an instance of a
> custom class, the same general technique will still work.

So, if we expand your Coordinate class to have attriutes r and theta
(the same coordinate expressed in polar form), which are also floats,
does it make sense to write: pt.r *= 2? For that matter, does it
*still* make sense to write pt.x *= x?

Ok, my design philosophy is that you don't do those things.  However,
Python is powerful enough that you can do those things and have them
work right. You just have to make x, y, theta and r properties, so you
can run code when someone sets or reads them.

And finally, there are times when your class is really just a
convenient way to bundle data together (because it's easier to write
"pt.x" than pt['x']), so there really aren't any applicable high-level
methods. In that case, all you do is tweak the attributes; you might
as well do it directly.

   <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list