Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > class methods vs. functions

Reply
Thread Tools

class methods vs. functions

 
 
beliavsky@aol.com
Guest
Posts: n/a
 
      07-14-2004

What are the pros and cons of defining a method of a class versus defining
a function that takes an instance of the class as an argument? In the example
below, is it better to be able to write
z.modulus() or modulus(z)? Is there a difference between Python and C++ in
this regard?

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

def modulus(z):
return sqrt(z.x**2 + z.y**2)

z = xy(3,4)
print z.modulus()
print modulus(z)



----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
 
Reply With Quote
 
 
 
 
Christopher T King
Guest
Posts: n/a
 
      07-14-2004
On 14 Jul 2004, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> What are the pros and cons of defining a method of a class versus defining
> a function that takes an instance of the class as an argument? In the example
> below, is it better to be able to write
> z.modulus() or modulus(z)? Is there a difference between Python and C++ in
> this regard?


The answer to this, as for most questions in computer science, is "it
depends". The answer (which is partially my opinion) has to do with
interfaces, and what you want to accomplish:

- Case 1 -

All of your objects conform to the 'xy' interface. This interface
requeries that an object has both .x and .y member variables. You can then
define a 'modulus' function that is defined to operate on any object
implementing the 'xy' interface:

> def modulus(z):
> return sqrt(z.x**2 + z.y**2)


Upside:

No matter what the object is, or from where it comes, so long as it
implements the 'xy' interface, you can now take the modulus of it.

Downside:

You can't take the modulus of anything that doesn't implement 'xy'.

- Case 2 -

Some of your objects implement the 'xy' interface, others don't (e.g. they
don't make sense with it). Either way, you want to be able to find their
modulus. You can do this by making all your objects conform to the
'modulus' interface. This interface requires that an object have a
..modulus() member function:

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


Upside:

You can take the modulus of any object you create, regardless of whether
it can implement the 'xy' interface or not.

Downside:

If you aren't the designer of the object, you can't take the modulus of
it, even if it does implement the 'xy' interface.

So, the choice is up to you. You can always provide both, though:

def mymodulus(z):
try:
return z.modulus()
except AttributeError:
return modulus(z)

In case you can't tell, I'm as undecided on the issue as you

 
Reply With Quote
 
 
 
 
Egbert Bouwman
Guest
Posts: n/a
 
      07-15-2004
On Wed, Jul 14, 2004 at 03:38:40PM -0400, Christopher T King wrote:
> On 14 Jul 2004, (E-Mail Removed) wrote:
>
> > What are the pros and cons of defining a method of a class versus defining
> > a function that takes an instance of the class as an argument?


>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.

I suppose that this means that you should treat each name foo of a
data-attribute as if it was called __foo.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
================================================== ======================
 
Reply With Quote
 
Jacek Generowicz
Guest
Posts: n/a
 
      07-15-2004
"(E-Mail Removed)" <beliavsky@127.0.0.1:7501> writes:

> What are the pros and cons of defining a method of a class versus defining
> a function that takes an instance of the class as an argument? In the example
> below, is it better to be able to write
> z.modulus() or modulus(z)?


You're essentially comparing the message-passing paradigm to the
generic function paradigm.

One advantage of message-passing, is that it separates the messages
into namespaces, so you don't have to be as careful about chosing your
message names.

One disadvantage of message-passing, is that it separates the messages
into namespaces, so you are less careful about chosing your message
names, and end up confusing your clients.

One advantage of generic functions is that multiple dispatch is much
more natural (dare I say, easier?).

One disadvantage of generic functions is that, if you are not careful,
your code ends up distributed all over the shop.

 
Reply With Quote
 
Jacek Generowicz
Guest
Posts: n/a
 
      07-15-2004
Egbert Bouwman <(E-Mail Removed)> writes:

> 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,


Message-passing, while being the most common style of OO, is not the
only style of OO.

You should use the object's interface. This may or may not be
implemented via messages.

> ie use methods of this object. So z.modules() seems to be the
> better idea, and modules(z) the worse one.


How do you know (without looking at the implementation of
"modules") that "modules(z)" is not "using a method" ?

This is a rhetorical question, which probably needs a bit of
comment. By "method" I don't necessarily mean "Python class or
instance method". You might like to think about "add(a,b)".

> I suppose that this means that you should treat each name foo of a
> data-attribute as if it was called __foo.


Why treat it as private, if it isn't marked as private? If it isn't
marked as private, then it's part of the interface. If it's part of
the interface, then it is intended for use by clients. If it's
intended for use by clients, then use it.


> my limited studies of object oriented programming taught me


Be careful not to let Java or C++ (or anyone strongly influenced by
them) to shape your understanding of object oriented programming. You
would be doing yourself a disservice.
 
Reply With Quote
 
Egbert Bouwman
Guest
Posts: n/a
 
      07-15-2004
On Thu, Jul 15, 2004 at 02:10:06PM +0200, Jacek Generowicz wrote:

> Why treat it as private, if it isn't marked as private? If it isn't
> marked as private, then it's part of the interface. If it's part of
> the interface, then it is intended for use by clients. If it's
> intended for use by clients, then use it.


My impression is that you can hardly call this OOO:
Object Oriented Orthodoxy. For instance, from the GOF I learned:
- the object's internal state can not be accessed directly
- operations are the only way to change an object's internal state
- requests (or messages) are the only way to get an object
to execute an operation
- a signature consists of an operation's name, parameters and return value
- the interface to an object is the set of all signatures of its operations

It is not easy to find definitions of 'interface' in python books,
but I cannot find descriptions that contradict the GOF.

And now you suggest that everything that is accessible is part
of the interface. I think I prefer the orthodoxy.

I suppose that is what you mean when you say:
> Be careful not to let Java or C++ (or anyone strongly influenced by
> them) to shape your understanding of object oriented programming. You
> would be doing yourself a disservice.

but I need more explanations, arguments, references.

You seem to encourage the following practice:
>>> class C: pass
>>> c = C()
>>> c.x = 9

because the internal state of c is not private,
so it is part of the interface, so it is intended for use,
so I should use it.

I finally got rid of my goto's, and now you do this to me.
egbert

--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
================================================== ======================
 
Reply With Quote
 
Steven Bethard
Guest
Posts: n/a
 
      07-15-2004
Egbert Bouwman <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> 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
 
Reply With Quote
 
Christopher T King
Guest
Posts: n/a
 
      07-15-2004
On Thu, 15 Jul 2004, Egbert Bouwman wrote:

> My impression is that you can hardly call this OOO:
> Object Oriented Orthodoxy. For instance, from the GOF I learned:
> - the object's internal state can not be accessed directly
> - operations are the only way to change an object's internal state
> - requests (or messages) are the only way to get an object
> to execute an operation
> - a signature consists of an operation's name, parameters and return value
> - the interface to an object is the set of all signatures of its operations


Replace .x with .getx() and .y with .gety() if it suits you, but often in
the case where an object is mostly used as a container (similar to a C
struct), direct access to its attributes is considered the norm:

a = 3+5j
a.real # --> 3.0
a.imag # --> 5.0

If you so choose, you can make .x and .y read-only with a little
__setattr__ magic (there's probably an easier way to do this in new-style
classes), as they are in the complex type:

a.real = 4 # --> AttributeError

Sure, it may not fit with "proper OO methodology", but it's a good way of
making visible the fact that "this object is a container, I'm retrieving
one of the variables it contains". If the interface is well-defined, it
doesn't matter how you access it, so long as you follow the interface's
design.

 
Reply With Quote
 
Egbert Bouwman
Guest
Posts: n/a
 
      07-15-2004
On Thu, Jul 15, 2004 at 09:40:53AM -0700, Steven Bethard wrote:
>
> 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).


Yes, I see that in real life access to the internal state of an
object is sometimes necessary. And Python allows it.

But what should i think of systems in which the users actually
have to use that licence ?

egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
================================================== ======================
 
Reply With Quote
 
Egbert Bouwman
Guest
Posts: n/a
 
      07-15-2004
On Thu, Jul 15, 2004 at 02:10:23PM -0400, Christopher T King wrote:
> but often in
> the case where an object is mostly used as a container (similar to a C
> struct), direct access to its attributes is considered the norm:
>
>
> Sure, it may not fit with "proper OO methodology", but it's a good way of
> making visible the fact that "this object is a container, I'm retrieving
> one of the variables it contains". If the interface is well-defined, it
> doesn't matter how you access it, so long as you follow the interface's
> design.
>

I am beginning to see the light. Thank you all.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
================================================== ======================
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
calling class methods from class methods, help? Oltmans Python 6 03-11-2009 07:59 PM
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
difference between class methods and instance methods John M. Gabriele Python 18 02-18-2005 05:17 PM
please help me in distinguish redefining functions, overloading functions and overriding functions. Xiangliang Meng C++ 1 06-21-2004 03:11 AM



Advertisments