Casting out getters and setters
Python Is Not Java by Phillip J. Eby (via Ned) is the most useful article on programming I’ve read in ages. If you have any interest at all in either language, go and read it. It’s all good, but the part that really struck a nerve for me was this:
Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans. Do not write getters and setters. This is what the ’property’ built-in is for. And do not take that to mean that you should write getters and setters, and then wrap them in ’property’. That means that until you prove that you need anything more than a simple attribute access, don’t write getters and setters. They are a waste of CPU time, but more important, they are a waste of programmer time. Not just for the people writing the code and tests, but for the people who have to read and understand them as well.
Writing getters and setters in Java has always bugged me, but I’ve never quite been able to articulate the reason until now. Python’s property syntax (and Ruby’s similar attr_reader and attr_writer methods) are so much more elegant that writing those things by hand, or even auto-generating them with Eclipse, leaves a nasty taste in my mouth.
I'm a bit confused by Python's approach: you still have to write the get and set function by hand, don't you? At least, that's what is showed in the PEP's example. Then, how can you be sure to have your get/set couple non to be called directly? And what's the performance difference, apart to be able (I suppose) to invoke c.size instead of c.get_size()?
As far as I know, Ruby works a little differently: attr_[reader|writer|accessor] generates automatically a one or a couple of methods (C#size and C#size=) to access a field. Then, you can obviously override those if you need to do more computation.
Giulio Piancastelli - 3rd December 2004 17:20 - #
Ryan Tomayko - 3rd December 2004 17:35 - #
While it's true that getters and setters do require additional computational overhead and that writing them can be a chore, there are still two good reasons for writing them:
Of course, these are trade offs. You get these benefits, as long as you are willing to write the extra code, and pay the performance penalty. But, as you know, the tedious code can be generated initially and the performance penalty is very minor.
Bob Owen - 3rd December 2004 17:49 - #
class MyClass: _y = 0 //protected field MyProperty: get: return _y set: _y = valueor you can simplify all the above with:class MyClass: [Property(MyProperty)] _y as intDougHolton - 3rd December 2004 17:53 - #
Only if they do something besides get or set the attribute. Attributes in Python are 'public' by default. As far as encapsulation is concerned, if you need to change the implementation of the class in such a way as you alter the semantics of the attribute that is accessed externally, you can simply rename the attribute to '_foo' rather than 'foo', and provide getter/setter functions for your property at that point. Up until then, you don't need them, so don't bother writing them.
Jim Dabell - 3rd December 2004 17:55 - #
Interesting... Why Nobody Didn't Notice Such Features In Delphi Where They Were For Ages :-)
I Wonder Also If The Next Discussion Around Blogs Will Be Around, Say, Delegation Of Interface Implementation To Properties... Does Python Have It?
Maniac - 3rd December 2004 18:18 - #
Bob, the point is that you don't need getters and setters in Python; the day you find that you need to control access to an attribute, replace it with a property. Client code won't notice the difference.
(the major drawback with Python properties is that code using won't work in older versions. another drawback is that people are abusing them; avoiding property getters and setters doesn't mean that you cannot have methods that are called "getthing" or "setthing" for things that don't really qualify as properties)
Fredrik - 3rd December 2004 19:16 - #
I prefer Mozilla's solution with setters/getters. Not that Java's conventions or Python's syntax are bad, but JavaScript's syntax is just sexy. ;-)
Jimmy Cerra - 4th December 2004 18:38 - #
Sam Newman - 5th December 2004 20:11 - #
Example: drawing "contexts" in Postscript, Java2D etc. have current stroke and fill patterns, current colours, etc. Clients who call "setFg(Color.RED)" are telling the drawing context to draw in red until further notice, not just asking to set the "foreground" attribute to "red", even if setFg were a simple setter.
Lorenzo Gatti - 6th December 2004 14:58 - #
I agree with Bob Owen, especially with point 2 :
For me getter & setter is the good object approach :encapsulating internal implementation. So you can change the implementation and the signature of methods is still good.
An simple example : An object representing a point in a 2D space. You can implement it with x and y coordinates in the space. So you create the setter and getter setX/getX and getY/getY.
But it's not the only way to implement that Object. It can be implemented by an angle from line y=0 and distance from point (0,0). So getX is a calculation from to angle and the distance and setX calculates new values for angle and distance (with current y position : not value).
Pascal - 7th December 2004 13:14 - #
Is there an echo in here? "...the point is that you don't need getters and setters in Python; the day you find that you need to control access to an attribute, replace it with a property. Client code won't notice the difference."
In java, an exposed member set (obj.x = 1) is different client code than a setter (obj.setX = 1).
In Python an exposed member set (obj.x = 1) is exactly the same client code as a setter (obj.x = 1).
The whole point is that in Python, you can implement a setter when you discover that you need it. There's no worrying about figuring out what accessors you might need some day, or otherwise making it policy to create spurious accessors because your language punishes you for deciding to do so later.
Clearer this time?
Jeremy Dunck - 7th December 2004 17:01 - #
Phillip J. Eby - 8th December 2004 00:28 - #
qwq - 27th April 2005 08:43 - #