473,385 Members | 1,351 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

class methods vs. functions


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 =---
Jul 18 '05 #1
15 2460
On 14 Jul 2004, be*******@aol.com 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 ;)

Jul 18 '05 #2
On Wed, Jul 14, 2004 at 03:38:40PM -0400, Christopher T King wrote:
On 14 Jul 2004, be*******@aol.com 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
================================================== ======================
Jul 18 '05 #3
"be*******@aol.com" <be*******@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.

Jul 18 '05 #4
Egbert Bouwman <eg*********@hccnet.nl> 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.
Jul 18 '05 #5
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
================================================== ======================
Jul 18 '05 #6
Egbert Bouwman <eg*********@hccnet.nl> wrote in message news:<ma*************************************@pyth on.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
Jul 18 '05 #7
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.

Jul 18 '05 #8
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
================================================== ======================
Jul 18 '05 #9
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
================================================== ======================
Jul 18 '05 #10
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


What you're missing is that, in Python, attribute access
*is* an operation, on the same footing as calling a method.
The object can be programmed to respond to it in any
desired way. So, exposing an attribute as part of the
public interface in no way limits the current or future
implementation.

This is in contrast to languages such as C++ and Java,
where attribute access cannot be overridden, so you
are forced to use accessor methods for everything in
order to keep interface and implementation separate.
The rules as you have learned them were designed for
those languages.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #11

On 15 Jul 2004, at 18:00, Egbert Bouwman wrote:
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:


Aaah, the dear GOF book. You do realize that the GOF book is, to a
lange extent, a book about the shortcomings of C++, don't you?

For example, think about how you would implement the Decorator and the
State patterns in Python.

I would advise against basing your understanding of what object
oriented programming is about, on the GOF book.
- the object's internal state can not be accessed directly
This is blatantly false, as your code snippet below clearly
demonstrates. (You probably meant "should not" rather that "can not".
The "should not" is a dogma. Understand its motivation, and decide for
yourself to what extent you want to buy it.)
- operations are the only way to change an object's internal state
Ditto. (... "are the only way" -> "should be the only way" ...)
- requests (or messages) are the only way to get an object
to execute an operation
Read up about properties in Python.

Strictly speaking, it's not an object which executes an operation;
rather methods carry out operations on objects. And it's certainly not
true that messages are the only way to get a method to carry out an
operation on objects ... put differently: generic functions exist.
It is not easy to find definitions of 'interface' in python books,
How about "Anything that does not start with an underscore" ?

(One can argue about the details of this proto-definition, but in terms
of value per word, it's pretty good, I'd say.)
And now you suggest that everything that is accessible is part
of the interface.
No. I suggest that everything that is part of the interface is part of
the interface. Put in other terms, everything that is not marked as
private, is part of the interface (or in some languages, everything
that is marked as public, is part of the interface --- though "private"
and "public" might not be the words which are used to describe a
similar concept in those languages). Some languages (notably C++ and
Java) consider that marking things as private is not good enough (I
guess that the assumption is that people who program in those languages
are too stupid to understand the importance of interfaces and to
respect them), and such languages attempt to make the private parts
inaccessible.

Encapsulation and access restriction are orthogonal concepts, which
have been conflated in Java and C++. That doesn't make them any less
orthogonal, as concepts ... so don't make the (all too common mistake)
of believing that they are actually one and the same.
I think I prefer the orthodoxy.
Into bondage, are you ? :-)
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.


Well, in terms of explanations and arguments, I was steering you
towards a discussion of the generic-function OO paradigm ... but you
seem not to have followed that up.

In terms of references ... try looking into some languages which
support OO, which predate Java and C++ (or which are otherwise not
influenced by them, or, at least, look very different from them.) You
could try Smalltalk, or Common Lisp, for example.
You seem to encourage the following practice:
class C: pass
c = C()
c.x = 9

Absolutely.
the internal state of c is not private,


This is not generally true, but it is true in this case.

For example, I would discourage the following:

class C:
def __init__(self):
self._x = 3

c = C()
c._x = 9

Note that I would not forbid it. In fact, I would encourage it, in some
situations. For example

a) You are debugging your application, or investigating its behaviour

b) The author of C hadn't anticipated some perfectly valid use you wish
to make of C, and didn't provide you with an adequate interface

Jul 18 '05 #12
Egbert Bouwman <eg*********@hccnet.nl> writes:
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.


Let's just think about this statement. In real life, access to the
internal state of an object is _always_ necessary. What would be the
point of the internal state, if there were no means of accessing it ?

(Yes, I'm being pedantic, but we are talking about programming
computers, and computers are pedantic in the extreme ... so you'd
better be used to expressing yourself accurately :-)
And Python allows it.
So does C++:

class A {
public:
int i;
};

A a;
a.i;

OK, this goes against C++ dogma, so you might prefer this:

class A {
private:
int i;
public:
int getx() { return this->i; }
void seti(int i) { this->i = i; }
};

A a;
a.i;

You're still accessing the internal state. And it doesn't have to be
that trivial:

class complex {
private:
double r;
double i;
public:
double get_modulus() {
return sqrt(i*i + r*r);
}
...
};
C c;
c.get_modulus();

You're still accessing internal state. The whole point of internal
state is that it be accessed somehow; if you couldn't access it, it
would be a waste of memory. Now, you might wish to debate _how_ it
should or should not be acessed ...
But what should i think of systems in which the users actually
have to use that licence ?


Maybe you want to refine your question.

As I said elsewhere ... you should probably think about the point of
interfaces (others have addressed this point upthread); you should
understand the concept of data abstraction. If you understand that,
you should be able to judge for yourself what is a good idea and what
is not. Dogmas are for people who can't think for themseleves.

I guess I could summarize my message thus:

Don't just repeat words; understand the concepts behind the words.
Jul 18 '05 #13
"be*******@aol.com" <be*******@127.0.0.1:7501> wrote
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)


In the example given the use of a function is IMHO a straightforward
mistake. The rivers will not run with blood if you do this, but it is
nonetheless a clear violation of basic OO design.

By using a function you're implying that it will work, if not with all
objects then with some wide range of semi-generic or base objects. But
most objects will not have x and y attributes. In other cases an
object may have such attributes but store string values or possess
attributes that could be sensibly used as arguments to a modulus
function but have the wrong names. A fundamental insight of the OO
approach is the benefit of associating a data structure with a set of
methods that work with that data structure. By incorporating modulus
as a method in the xy class you avoid the problems mentioned above.

It makes sense to have functions that work with all objects, such as
the id() function or they work with basic Python types such as numeric
values. A modulus function would be fine if it took two numeric values
and returned the square root of the sum of their squares, but it would
then be just the math.hypot function.

Python does place a premium on rapid prototyping and in consequence
possesses an OO implementation that doesn't get in the way of coding.
The joy of Python is that you can usually concentrate on the problem
and not be distracted by the need to satisfy additional requirements
of OO purity. However Python is an OO language; all of the standard
concepts still apply and all of the usual guidelines should still be
followed. You still write to the interface, you still encapsulate your
data and you still associate methods with data structures. This isn't
a matter of OO orthodoxy but of practical design that led to the
development of OO.

A B Carter
Jul 18 '05 #14
Egbert Bouwman <eg*********@hccnet.nl> wrote in message news:<ma*************************************@pyth on.org>...
My impression is that you can hardly call this OOO:
Object Oriented Orthodoxy. For instance, from the GOF I learned:


Excuse me, but what is "GOF"?

I thought of Good Old Fortran, but them I am an odd duck :).
Jul 18 '05 #15
On Fri, 16 Jul 2004 04:52:50 -0700, beliavsk wrote:
Excuse me, but what is "GOF"?


GOF = Gang of Four = Gamma, Helm, Johnson, Vlissides
authors of the seminal work on design patterns
N.
Jul 18 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Robert | last post by:
Python doesn't know the class of a method when container not direct class attribute: >>> class X: .... def f():pass .... g=f .... l= .... >>> X.g <unbound method X.f>
2
by: Jerry | last post by:
My "main" class is getting a bit long...Is it possble to split a class definition into several files and then import the pieces to get the whole definition? Jerry
11
by: Roger Leigh | last post by:
The C++ book I have to hand (Liberty and Horvath, Teach yourself C++ for Linux in 21 Days--I know there are better) states that "static member functions cannot access any non-static member...
23
by: patang | last post by:
When I create my own class, to use the functions of that class I have to create an object of that class and then I can access the functions of that class, for example: dim obj1 as myclass...
10
by: David Hirschfield | last post by:
Here's a strange concept that I don't really know how to implement, but I suspect can be implemented via descriptors or metaclasses somehow: I want a class that, when instantiated, only defines...
22
by: John Salerno | last post by:
I might be missing something obvious here, but I decided to experiment with writing a program that involves a class, so I'm somewhat new to this in Python. Anyway, what is the best way to create...
17
by: Fabry | last post by:
Hi All, I'm new of this group and I do not know if this is the correct group for my question. I have a DLL with its export library (.lib) wrote in Borland C++ 6. In borland everything is OK and...
1
by: sk.rasheedfarhan | last post by:
Hi , I am using C# I am having 4 classes. like below. public class A { String m_strRuleName; String m_strRuleGuid; // Some member functions. public Object NextItem; }
1
by: Bushido Hacks | last post by:
A private utility function using a function pointer sounds ideal to me. I want to simpify writing the same set of loops. While there are a few functions that can't use it, setting and modifying...
61
by: Sanders Kaufman | last post by:
I'm wondering if I'm doing this right, as far as using another class object as a PHP class property. class my_baseclass { var $Database; var $ErrorMessage; var $TableName; var $RecordSet;...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.