Why would I want to use an attribute in Python, where I would use
getters and setters in Java?
Oh boy! I've just come out of a rather long thread about that very issue.
If you care enough to read a bunch of people arguing past each other,
check the thread "Another newbie question", especially the posts about the
so-called Law of Demeter.
But for the short summary: suppose I write a class:
class Parrot:
def __init__(self, x):
self._x = x
print "please use instance.getx() and setx()"
def getx(self):
return self._x
def setx(self, x):
self._x = x
What if I want to export methods of x other than get and set? Perhaps x
is a numeric value: now I have to export a whole series of arithmetic
operators: addx, subx, mulx, etc. And there may be other attributes I need
to export as well...
When I write getter and setter methods for an attribute, I make myself
responsible for maintaining everything about that attribute. I create
extra functions that need to be tested, debugged and documented. I expect
my class users to learn how to use my class, and every method is another
method they have to learn about. Writing getter and setter methods have
costs -- I pay some of those costs, and my users pay some of those costs.
Then I get fed up and write this class instead:
class NorwegianBlue:
def __init__(self, x):
self.x = x
print "please use public attribute instance.x"
NorwegianBlue is a much smaller class. That means less development time
for me, less test code to write, less documentation, less time needed for
my users to learn the API -- they already know what the API for x is,
because they supplied it. The costs to both class designer and class
user are much less, the flexibility is greater, and I finish writing the
class quicker.
Is there a disadvantage to NorwegianBlue? Yes -- I am now locked in to one
particular interface. I can't even do something as trivial as change the
name of attribute x. But then I can't change the name of Parrot.getx
either, not without breaking people's code.
But still, sometimes I know that I will want to -- or even that I might
want to -- radically change the implementation of my class. Perhaps x is a
list now, but later it will be a binary tree. How much effort will be
needed to fix the breakage if NorwegianBlue changes? If the expected
effort to fix the breakage is more than the effort to write setters and
getters, then it makes sense to write setters and getters.
But contrariwise, if it will take less effort to fix the problem than to
defend against it, then why defend against it? Getters and setters are
insurance against you changing the private interface. You wouldn't pay
$20,000 a year to protect a $20,000 car. You might not even pay $1,000 a
year.
So do your trade-offs, and make your decision.
I know that encapsulation is actually just
a hack in Python (common, "hiding" an implementation detail by prefixing
it with the classname so you can't access it by its name anymore? Gimme
a break...),
I'll give you a much better break in C++:
#def private = public
So much for encapsulation, hey?
Java makes it harder, but not that much more:
http://www.informit.com/articles/article.asp?p=174217&seqNum=3&rl=1
but is that a reason to only write white box classes? ^^
Why would you want to write black box classes?
Python is not a bondage and discipline language. Remember kids, whips and
chains are only for mummies and daddies who love each other very much.
Python includes tools for preventing people *accidentally* shooting
themselves in the foot. But the philosophy of the language is to allow,
even to encourage, people to tinker under the hood. If that means that
somebody *deliberately* shoots themselves in the foot, well, that's the
price you pay for freedom: some people make stupid decisions.
I look at it this way: as the class designer, I have ZERO idea what
attributes and methods of my class will be just the perfect thing to solve
somebody's problem, so it is rude of me to lock them up as private --
especially since they *will* find a way to hack my class and access my
private attributes and methods anyway. All I'm doing is making their life
miserable by making them go out and buy books like "Hacking Private
Attributes In Java" or something.
But as a class designer, I know perfectly well which of my class members
are free for anyone to touch (instance.public), which should be considered
private by convention (instance._private) and which need a great big sign
on the door saying "Enter At Own Risk! Don't touch this unless you know
what you are doing!!!" (instance.__mangled).