class methods vs. functions

Steven Bethard steven.bethard at gmail.com
Thu Jul 15 18:40:53 CEST 2004


Egbert Bouwman <egbert.list at hccnet.nl> wrote in message news:<mailman.423.1089880140.5135.python-list at python.org>...
> From a technical point of view Christopher's explanation seems to be OK,
> but my limited studies of object oriented programming taught me that
> from outside an object you should not use its data-attributes directly.
> Rather you should send the object messages, ie use methods of this object.
> So z.modules() seems to be the better idea, and modules(z) the worse one.

This argument usually stems from the idea that only calls to methods
are "sent messages".  This is true in a language like C++  or Java
where a class like:

class XY {
    double x, y;
    double modulus();
}

allocates space for two doubles (x and y) and then puts the modulus
method in its method lookup table. The concern is that, if the owner
of class XY determines that there is a better way of representing the
data portions of the class, e.g.:

class XY {
    double radians, length;
    double modulus();
}

then anyone who used the XY class's data-attributes directly will then
be in trouble (since they have been removed).  This is why in a
language like C++ or Java you'll usually see these fields declared as
private, and thus only the methods are considered to be part of the
class's interface.

In Python, we can avoid some of this issue because of the getattr and
setattr type functionality.  Imagine I have the class:

class xy:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def modulus(self):
        return sqrt(self.x**2 + self.y**2)

And then imagine I've decided I would rather represent the class with
the radians, length formulation:

class xy:
    def __init__(self, radians, length):
        self.radians = radians
        self.length = length
    def modulus(self):
        return ... # calculation in radians

Now I have to make Christopher's decision.  If I believe that users of
my class never access the x and y variables, only the modulus method,
(i.e. if I envision this class with Christopher's "Case 2" interface)
then I'm done.  On the other hand, if I believe that x and y are part
of the interface I've presented to users of the class, (i.e.
Christopher's "Case 1" interface), I need to continue to provide
access to these "attributes".  In Python, we can continue to make such
attributes available, even if we don't actually have an 'x' or 'y'
field in the class anymore, using the getattr/setattr functionality:

    def __getattr__(self, name):
        if name == 'x':
            return ... # calculation of x from radians and length
        if name == 'y':
            return ... # calculation of y from radians and length
    def __setattr__(self, name):
        ... # set radians or length based on x or y

So if you decide that your data attributes need to change, you haven't
destroyed compatibility with users of your class, even if your data
attributes were publicly available.  Continuing to support the older
attributes isn't necessarily trivial, but at least it's /possible/
(unlike C++ or Java).

Steve



More information about the Python-list mailing list