A matter of style: class.foo = bar vs. class.set_foo(bar)

Peter Hansen peter at engcorp.com
Sat Nov 11 17:57:16 CET 2000


Steve Lamb wrote:
> 
>     OK, when setting a variable from program logic is it acceptable to set it
> directly or should one create a method to set the variable?

If it's purely style you are asking about, that's mostly a personal
question.  Some people appreciate the simplicity of "spam.foo = bar"
while others (coming from a different background likely) appreciate the
benefits of "spam.setFoo(bar)" in reducing problems during maintenance. 
(And if you are really interested in style, I've just opened the
question of setFoo() versus set_foo(), but that's another story...)

In other languages I've used, I found the best solution was generally to
go with spam.setFoo(bar) because that allowed me easily to add code to
support special situations that might arise in the future.  

Some languages (e.g. Object Pascal in Delphi) support the idea of
properties which although they *look* like a variable assignment are
actually causing a method to be invoked.  Some programmers in these
environments tend to make *everything* a property and while they claim
to be increasing the readability of their code, I find it makes it
difficult to work with because you *never* know what is just a variable
and what is invoking code which could do anything from a simple
assignment to launching the space shuttle.  Yes, from the outside it is
probably simpler, but the implementation will definitely have bugs (it
*is* software) and therefore I'm guaranteed to have to dive into it at
some point and face a nightmare of complexity.

Other languages (e.g. Java) define a convention for such things and say
that it's best always to use "accessor methods" such as setX() and
getX() to access object data, although you aren't forced to.  I've
generally agreed with that philosophy, as it doesn't try to hide the
fact that methods are being invoked, and yet allows the maintenance
burden to be reduced.  The tradeoff is readability, to some extent, but
it's worth it.

Finally, we come to wonderful Python.  Unlike many other languages, the
emphasis is on pragmatism.  First of all, you can do either spam.foo =
bar or spam.setFoo(bar).  Or you can implement properties ala Delphi, by
using __setattr__ and __getattr__, and although the internal
implementation of the class is uglier, from the outside it works the
same.  As in Delphi.

With Python, what I've started doing is perhaps inspired by a few
thoughts from eXtreme Programming, in the area of "don't build it if you
don't need it now".  I just use spam.foo = bar, when I don't have a
strong feeling I'll need to add associated magic behaviour.  In other
cases I use spam.setFoo(bar), making it obvious that I am doing more
than just assignment, or that I expect to.

But best of all is that in the worst case, when I guess wrong about
spam.foo = bar and find I have to change the functionality
significantly, probably to work around a design flaw or something, I can
always pull out __setattr__ and redirect the assignment to a method
call.  Rather than rewriting piles of code that used the original
simpler assignment, risking injection of new bugs, I quietly fix the
problem and carry on with my work.  

And come to think of it, with Delphi I probably had the same option, but
it was Python (plus a little XP) which inspired this most pragmatic
approach.

That's one person's "style", anyway.  :-)

-- 
Peter Hansen



More information about the Python-list mailing list