Accessors in Python (getters and setters)

Bruno Desthuilliers onurb at xiludom.gro
Thu Jul 20 13:18:44 EDT 2006


mystilleef wrote:
> Bruno Desthuilliers wrote:

>>>>>>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++.
>>>>
>>>
>>>
>>>OMG!
>>
>>It's common knowledge.
>>
> I ask how your solution is robust,

This is definitively not a problem with "my solution". Python has *no*
access restriction. Anyone can do what he wants with any attribute of
your Python classes.

> and you go off talking about Java
> and C++. 

Whose access restriction is Joke.

> 
>>>>>>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.
>>>>
>>>
>>>Sure, but calling users idiots for as result of your laziness or poor
>>>design or lack of robustness is equally idiotic.
>>
>>Ok, then 99.99% of Python programmers are lazy, have poor design skills
>>and are unable to write a robust application. So they are idiotic too.
>>
> If you say so.

Logical derivation from your above statement.

> 
>>>>>>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.
>>>>
>>>
>>>Hey, I didn't write that code. You did! You deal with it. My input on
>>>__your__ code at this point is irrelevant.
>>
>>It's totally relevant, and you're still unable to come with any valid
>>reason to prefer the first solution over the second. I'm totally
>>confident that if there was *any* defendable reason to favor the first
>>approach, you'd have chosen to answer instead of playing dumb.
>>
>  
> Chosen what answer? First of all, I have no idea what you are trying to
> do. 

Make you understand why, in Python, it is *totally* useless to mark an
attribute as implementation and add read/write accessors to it. But it's
obviously hopeless.

> Secondly, I wouldn't code like that. So asking for my input on
> some code that I believe has no purpose is irrelevant. In your class,
> Complicated, why are your accessors private?

They are not "private", they are implementation details - in this case,
support for a property.

> Why is the attribute the
> accessors are modifying public?

It is not public, it is marked as implementation detail - in this case,
support for a property.

> In your second class, can data afford
> to be modified by anyone? 

Obviously - just like in the first example.

>Does doing that cause any corruption, bugs,
> indiscrepancies in the system? You can't just throw code at me, out of
> context, and tell me to choose which is better. It's just premature.

If you are unable to understand such a simple code then you are totally
clueless. Since your are obviously not totally clueless, it's just bad
faith from you. So I'm obviously wasting my time and bandwidth.

(snip)
>>>>>See! I'm controlling access.
>>>>
>>>>You are not controlling *anything*
>>>>
>>>>r = Robust()
>>>>r._Robust__is_active = True
>>>>
>>>
>>>
>>>*sighs*
>>>
>>>You keep coming up with these unrealistic and impractically delusional
>>>theories
>>
>>Pardon ? Which "unrealistic and impractically delusional theories" ?
>>Please try the code above instead of getting to big words...
>> 
> 
> Doesn't that fall under the "DO NOT DO THIS AT HOME KIDS" in the FAQ
> section or somewhere?

Nope. It falls under the "dont do this unless you really need to and
know exactly what you are doing and accept all possible consequences -
IOW you're on your own" section.

>>
>>>Sure Python lets your do that,
>>>but that's an implementation detail almost all Python developers could
>>>give a damn about. How many times do I have to tell you I don't care
>>>for latent semantic implementation details of Python? Anybody who does
>>>what you just did should be laughed at derisively and ignored.
>>
>>Believe it or not, but there are times someone may have a perfectly
>>valid reason to do so (probably not with your example, but that's
>>another point).
>>  
> I have never seen any Python code do that.

I have.

> I will certainly reject code
> like that in my project. 
> But if people do it without any ill effects,
> good for them. I don't do it, I don't know any Python developer that
> does.

Never heard of the sys._getframe() hack ?

>>>>
>>>>>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' ?
>>>>
>>>
>>>But I don't want to. I wanna change implementation not interface.
>>
>>Changing implementation from direct attribute access to property doesn't
>>require changing the interface, so there's no reason to use a property
>>for simple read/write access. period.
>>
> 
> 
> There is. The name issues already afore-mentioned elsewhere.

Lol. The "name issue" you talk about is
1/ exactly a case of changing *interface*
2/ only due to the fact that you're confusing state with non-callable
attributes.

>>>>>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.
>>>>
>>>
>>>That's just silly. If a third party plugin is crashing your app,
>>
>>Not my responsability.
>>
> 
> 
> You enjoy pointing fingers, don't you?

Nope. But I refuse to be responsible for someone else's stupidity
(unless this 'someone else' happens to be my son).

> 
>>>guess
>>>who's gonna get the emails and bug reports? That's right you!
>>
>>And ?
>> 
> You have to investigate it?
> 
> 
>>>And that
>>>is after hours of trying to reproduce the bug on your system
>>>unsuccessfully
>>
>>If the app runed fine and all of a sudden starts to crash, I'll suspect
>>something specific to the user system.
>> 
> There you go again pointing fingers. It has to be the stupid idiotic
> users fault.

Your words. Not mines. As far as I'm concerned, I can accept that some
change in the user's environment can impact my program - sometimes in
very very strange ways. I've had a case recently involving Trac, SQLite,
mod_python and PHP5.

> 
>>>because you don't have the bloody plug-in installed and
>>>they user doesn't know a random plug-in he downloaded is the root of
>>>the problem.
>>
>>"Hi Mr User... Just a question about your problem : did you change
>>anything in your system recently ? Like installing a new plugin ?"
>>
> Yeah, now you have 20/20 hindsight.

Of course - I cheated. At least with the last question. But FWIW, if my
app was pluggable and I had a similar case, one of the very first thing
I'd ask would be the detailed and exhaustive list of installed plugins.

>>>>>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 ?
>>>>
>>>
>>>Yes, it can be.
>>>
>>
>>I definitively give up trying to understand you.
>>
> 
> 
> I guess you haven't got bug reports that make you feel like shit.

No. I don't allow a bug report to "make me feel like shit". I sometimes
felt really dumb and sorry when I found out how evident the bug was, but
that's another problem.

(snip)
>>>My users are not just end users they are also developers.
>>
>>Developpers are supposed to know enough to fill in useful bug reports...
>>and possibly do some prior research on the problem by themselves.
>>
> Developers extend your application in ways you hadn't originally
> anticipated, thus exposing bugs.

I know, I do a lot of work on existing apps so they fit my customers needs.

> And no, it's not the developers fault.

Which developper ? The author of the app, or the one extending it ?

> I know that's where you are going. There are several reasons why this
> can happen, including me not protecting object's state properly.

If you exposed as part of the interface some highly critical attribute
then yes, you are responsible. If it's the other developper messing with
your implementation, then it's by no way your responsability - but it
may be a sign that your code could need some support for a use case you
had not anticipated.

(snip)
>>>
>>>Your example
>>
>>Which one ?
>>
>>
>>>actually requires more code,
>>>is looks complex and it's
>>>ugly
>>
>>
>>You mean:
>>
>>class Pythonic(object):
>>    def __init__(self):
>>      self._is_active = True
>>
>>    @apply
>>    def is_active():
>>      def fget(self): return self._is_active
>>      def fset(self): raise SomeException('sorry, read-only')
>>      return property(**locals())
>>
>>
>>
(snip)
> Yes, that.

Then you find Python complex and ugly. But what I find surprising is
that you could make a judgement on "my example" before I wrote it...


(snip)
>>>What book are we talking about again? I made these rules from my
>>>experience writing programs in Python, not from any book.
>>
>>I fail to see how your view of "data = state / methods = behaviour" or
>>your advice to "make all data attributes private" comes from experience
>>writing Python code.
>> 
> 
> Then I can't help you.

That's an understatement.

>>>But for a lot of people over here who claim they've been
>>>programming for X number of years, some of them certainly do need to
>>>hit the books again. I don't believe I spent an inordinate amount of
>>>time explaining state and behavior or the benefits or techniques for
>>>reducing coupling or why anyone would need accessors, among other
>>>things.
>>
>>Do you really believe you taught me anything about these topics ?
>>
> 
> 
> No, but I surprised some of the terms I use confuse you.

The only term that confused me was actually "contaminated".

> Or why you
> would question why anyone would need to use accessors.

Where did I question this ? Chapter and verse, please.

> And that you
> consider data hiding and encapsulation harmful and unnecessary.

I consider language-inforced access restriction as harmful and
unnecessary. And it has very few to do with encapsulation.

> However, I'll give you the benefit of the doubt.

How nice from you. But given the views you expressed about "sound
software engineering principles" and your understanding of concepts such
as state, behaviour, coupling and encapsulation, please consider me as
definitively wasted.

>>>>>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).
>>>>
>>>
>>>Sure, if it makes you feel better.
>>
>>Alas, not. Seeing someone inflicting himself pain because of misbelief
>>or misunderstanding does not "make me feel better". Too bad you take it
>>this way.
>>
> 
> 
> I feel a lot more pain when I have to investigate bugs that I could
> have prevented easily if only I had adhered to sound software
> engineering principles as opposed to drinking philosophical Kool Aid.

Exactly. Here, the "sound software engineering principles" is to pay a
minimal attention to naming of interface elements, and the
"philosophical Kool Aid" confusing non-callable attributes with
implementation detail.

> I'm in tune with most of Python's philosophies. But one needs to know
> when to make exceptions as opposed to blindly reciting and following
> ingrained mantras.

Exact once again. Here, the mantra is "state is data is private,
behaviour is method is public". That may be true for Smalltalk, but not
for Python.


-- 
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