Accessors in Python (getters and setters)

Bruno Desthuilliers onurb at xiludom.gro
Thu Jul 20 06:48:54 EDT 2006


mystilleef wrote:
> Bruno Desthuilliers wrote:
> 
>>mystilleef wrote:
>>
>>>Bruno Desthuilliers wrote:
>>>
>>>
>>>>mystilleef wrote:
>>
>>(snip)
>>
>>>>>>>Of course using setters for the sake of just using them is pointless.
>>>>>>
>>>>>>Indeed.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>The reason to use them is if pre-conditions or post-conditions need to
>>>>>>>be met. Or to control access to an objects states.
>>>>>>
>>>>>>Then why advocate *systematic* use of them ?
>>>>>>
>>>>>>(snip)
>>>>>
>>>>>I never advocated anything.
>>>>
>>>>You advocated
>>>>"""
>>>>1). Make all attributes of a class private/protected .
>>>>2). If a "non-callable" attribute is going to be used outside a class,
>>>>think about making it a property and name the property well, because
>>>>you never know...
>>>>"""
>>>>
>>>
>>>
>>>You use accessors when you need to control access to a data attribute.
>>
>>Indeed. And when you don't need too ? (the second 'o' is not a typo)
>>
> 
> 
> You make the attribute private/protected.

doh :(

Let's talk about psychorigid mindset...

> 
>>>That's not advocacy, that's common sense.
>>
>>I'm afraid we don't use the same definition of "common sense". Writing
>>useless code is not part of my definition of "common sense".
>>
>>(snip)
>>
>>>>>I agree. And I already told you I think in terms of state and behavior
>>>>>and not language dependent semantics.
>>>>
>>>>Then why do you advise "(making) all attributes of a class
>>>>private/protected" and systematically using properties ?
>>>>
>>>
>>>
>>>Because you don't want third parties illegimately tampering with an
>>>object's internal data and thus crashing your system?
>>
>>Let's try again...
>>
>>point 1 : there's *no* language-inforced access restriction in Python.
>>Just a *convention*.
>>
> 
> 
> Huh? What are properties for then?

To allow attribute syntax when you really have computation behind. Which
 1/ let you start with the simplest case (a simple attribute) and change
your mind latter
2/ offer the possibility to use an attribute syntax (instead of a method
call syntax) when it seems more natural.

> 
>>point 2 : so anyone *can* "illegimately tampering with an object's
>>internal data" at will.
>> 
> 
> And this is robust how?
> 

You can do just the same in Java or C++.

>>point 3 : anyway it's not *my* system that will then crash - but the
>>system of the one who "illegimately" played with my package's objects
>>internals. And as far as I'm concerned, it's none of my problem - they
>>were marked as implementation, so anyone playing with them is on it's
>>own. FWIW, I suspect that if someone want to muck with implementation,
>>he certainly has a good legitimate reason to do so, and will do her best
>>to not break anything. Else he's a complete idiot and there's no cure
>>for this.
>>
> 
> 
> You can't be serious. Please tell me you are joking.

I'm deadly serious and definitively not joking. There's no cure for
idiocy, and there's definitively nothing like an idiot-proof system.

> 
>>point 4 : since we have computed attributes, turning a "public data
>>attribute" (to use your idiom) into a "private/protected data attribute
>>with accessors" *without breaking the interface* is not even a non-brainer.
>>
>>Now, please, can you explain the difference between :
>>
>>class Complicated(object):
>>  def __init__(self, data):
>>    self.data = data
>>  def _get_data(self):
>>    return self._data
>>  def _set_data(self, data):
>>    self._data = data
>>
>>and
>>
>>class Pragmatic(object):
>>  def __init__(self, data)
>>    self.data = data
>>
>>
>>and find any *valid* reason to use the first solution instead of the
>>second ? ('that's what the book says' not being a valid reason).
>>
> 
> 
> I don't know it's your code not mine.

IOW : you're unable to find any valid reason to use the second solution
instead of the first (of course : there's none), but refuse to admit it.

> 
> class Robust(object):
> 
> 	def __init__(self):
> 		# Arbitrarily changing this state to False will crash app or will
> 		# corrupt the whole event system.
> 		self.__is_active = True
> 
> 	def get_is_active(self):
> 		return self.__is_active
> 
> 	buffer_is_active = property(get_is_active, doc="True if buffer is
> editable")
> 
> 	def monitor_events(self):
> 		# Only methods of this class can change __is_active.
> 		# Add code to change __is_active here.
> 		return

Yuck.

> See! I'm controlling access.

You are not controlling *anything*

r = Robust()
r._Robust__is_active = True

As I told you, there's no cure for idiocy.

> Whee! And if one sober morning I want to
> change the name __is_active to __buffer_is_active, I won't have to hunt
> down 27000 lines of code to do it. 

And what if you want to change 'buffer_is_active' to 'is_active' ?

> Also a naive third party won't crash
> my system by changing Robust's state arbitrarily.

Lol. cf above. And, may I repeat : you're getting the "my/3rd part"
stuff the wrong way. If someone uses your code in it's app, then it's
*her* system, and *your* code is the '3rd part'. Whether someone wants
to do idiotic things with your code that will result in a crash is none
of *your* concern. Just like if someone buy a hammer and bangs his head
with, it's not the concern of the guy who made the hammer.

> Because in the real
> world when your program is buggy, you get bug reports, nasty emails
> among other forms of ridicule.

So you see receiving a bug report as a form of ridicule ?

Now FWIW, I have lot of python apps in production, very few bug reports
[1], and none of them being the result of the problem you seems to fear
that much.

[1] The very first release of one of them is in production for more than
6 monthes now, is daily used by a dozen non-computer-savy users, and not
a *single* bug report - actually, the only return we had is "it's
perfect, it works like a charm, and we have some other stuff for you guys"


> And your supposed solution to my problem
> is me saying, "but...but...I told you not change is_active."

In my example (which was not intended as a "solution to a problem"),
is_active is clearly part of the API. So your argument is moot.

OTOH, if I need to control access to is_active, I can easily change it's
implementation - ie by using a property (or any custom descriptor). So
my "solution to the problem" is functionally equivalent to yours, and
requires much less code - which contributes to making it more robust.

> Ha! And if
> you can't figure out why anyone would do this, 

Oh yes, I can :
- too much exposure to B&D languages
- lack of ability to criticize "what's in the Book"
- confusion between state/behaviour concepts and the (mostly inexisting
in most hi-level languages) data/function dichotomy
- control-freak mindset

> then I'm not wasting my
> time here anymore. 

You're wasting your time because you refuse to escape from your "what's
in the book" mindest and insist on writing Java in Python. I had the
same problem when I came from Java to Python, then I had the "aha"
moment where I realized I was overdoing it, writing uselessly
complicated code to do simple things that would just have worked without
all this mumbo/jumbo control freak stuff. But it seems you prefer to
stick to your masochistic approach for no other reason than
misunderstood concepts, so we can't help you here.

> Someday you'll learn the hard way.

Lol. I actually did *un*learn the hard way.

Mystilleef, I've started programing 17 years ago, and have done it
professionnaly for almost 10 years now. I do not pretend to be a good
programmer, but please believe that I do know my job. I've read the Book
too, I've tried applying it blindly, then I used my brain. Once you
understand the real reasons behind a "rule", you also understand when
and how to apply or not apply it.

> Thanks to the people who exposed me to Python's properties.

The problem is that you definitively *failed* to understand how to use
them (or actually how to *not* use them when not needed).

-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list