Accessors in Python (getters and setters)

M

Marc 'BlackJack' Rintsch

mystilleef said:
Python doesn't have any philosophy with regards to naming identifiers.

But the python community has one. Pythonistas prefer readable source code
so they tend to think about good names. As The Zen of Python says
“Readability counts.â€
Right, and what if I want to change a private API to a public one. How
does that solve my naming issues.

Then you have to change all references to that private attribute. What's
the problem here? As it was private I would expect to find all the
references "nearby" in the same module or class.
The reverse is hardly ever true. 90% of public APIs in almost all
languages are methods or functions.

Except the ones with properties where ordinary "attributes" may be just
calls in disguise.

Python is not almost all other languages and in Python code you usually
won't find those trivial getters and setters because we have properties if
the access might become a bit more complex in the future.

Ciao,
Marc 'BlackJack' Rintsch
 
B

Bruno Desthuilliers

mystilleef wrote:
(snip)
Python doesn't have any philosophy with regards to naming identifiers.

Yes it does.
Right, and what if I want to change a private API to a public one.

Then you provide a public API on top of the private one.

class MyClass(object):
def __init__(self, ...):
self._attr = XXX

# seems like we really have enough use
# cases to justify exposing _imp_attr
@apply
def attr():
def fget(self):
return self._attr
def fset(self):
self._attr = attr
return property(**locals())


def _method(self, ...):
# code here

# seems like we really have enough use
# cases to justify exposing _imp_method
method = _impmethod

Note that none of this actually breaks encapsulation.
How
does that solve my naming issues.

How could this solve *your* naming issue ? This is totally unrelated.
You choose a bad name for a *public* symbol.
The reverse is hardly ever true.

So what are computed attributes ?
90% of public APIs in almost all
languages are methods or functions.

"allmost all languages" lacks computed attributes.
 
M

mystilleef

Bruno said:
Well, it's surely not as descriptive as 'temporary_buffer'


Too bad for you.

Thank you, that was helpful.
So why did you name it that way at first ?

What does it matter? There are 10 million and one reasons from given
identifiers bad names.
But 'tmp' actually *is* an accessor.

I didn't say it wasn't.
Err... do you find:

obj.set_temporary_buffer(val)
val = obj.get_temporary_buffer()

really more readable than:

obj.temporary_buffer = val
val = obj.temporary_buffer

I didn't name the attribute temporary_buffer, I named it tmp.
Indeed. In both the class and client code.


You still fail to get the point. You actually choose a crappy name for a
*public* property. It's *exactly* as if, in Java, you had named your
getter/setter 'get_tmp' and 'set_tmp'.

No, it isn't. In Java there's a clear distinction between attributes
and methods.
Indeed. But it's *your* responsability to choose good names for the API.

I choose good names for most of my APIs. But there cases when you never
know an attribute will actually be an API before hand.
or 'tmp'.


s/developpers/you/

Ha, right! I bet you are perfect developer.
Once again, in Python, there is *no* such thing as 'data attributes'.
*All* attributes are *objects* - some of them callable.

I didn't say attributes weren't objects.
Don't confuse encapsulation with data-hiding.

I don't see the confusion.
That's true for each and every name in a program.


Too bad for you.

Thank you.
Then mark them as being implementation (ie : prefix them with a single
underscore).

I thought that too was unpythonic.
Nope. You have the class API, and the class implementation. Both made of
both callable and non-callable attributes.
Or objects have state and behavior. Data attributes represent state and
methods represent behavior.
Mystilleef, I do share your pain (really - been here, done that,
etc...), and I understand that grasping Python requires some mental
adjustments when coming from Java and friends (been here, done that,
etc...). But you seriously can't blame the language for your own mistakes.

You don't share my pain. You seem to mock it. I'm not new to Python
either. I've been using it for over 2 years in several capacities. I
only recently decided to use it for a large project.
If you intented 'tmp' to be part of the API, then you're responsible for
the bad naming.

I never intended it to be part of the API. It evolved to be an
important part of the system.
If you didn't, then you're responsible for breaking the
encapsulation - FWIW, following the convention (single leading
underscore) could have make it clearer to you.
In both cases, you
happily used a bad name in 27 KLOC - so you really had a lot of time and
occasions to notice something wrong with this.
That's nonsense. I only just noticed because I was trying to implement
a plug-in system and I needed to expose an important class. I would not
have considered the issue a problem without this requirement. Except
you are a prophet, you sometimes can't know before hand how certain
classes will end up being used especially if requirements suddenly
change. Saying it's my fault to make yourself feel better about your
favorite language doesn't help solve my problem. I didn't come here to
be berated. I came here to learn the Pythonic way to implementing
accessors. And of course how to deal with issues like the one I have in
medium size to large scale projects. People make mistakes, we deal with
an move on. Sheesh
 
M

mystilleef

Marc said:
But the python community has one. Pythonistas prefer readable source code
so they tend to think about good names. As The Zen of Python says
"Readability counts."
I'm glad I'm in tune with the "python community."
Then you have to change all references to that private attribute. What's
the problem here? As it was private I would expect to find all the
references "nearby" in the same module or class. Right, but tmp isn't private.

Except the ones with properties where ordinary "attributes" may be just
calls in disguise.

Crap! Even in Python too most Public APIs are methods and functions.
Python is not almost all other languages and in Python code you usually
won't find those trivial getters and setters because we have properties if
the access might become a bit more complex in the future.

Ha! I bet you haven't read too many Python codes.
 
B

Bruno Desthuilliers

Gerhard said:
I'm not sure about which languages you are talking (pretty much all that
allow public methods also allow public attributes), but in general I think
you should get away from the distinction attribute vs method (which doesn't
make much sense in any language)

And even less when one have first-class functions and computed
attributes... In Python, a method is nothing more than a callable attribute.
and start looking at the distinction
public vs private

Since "public" and "private" are now strongly connoted with
"language-inforced access restriction", I'd rather talk of "interface vs
implementation"
(which is what you really are talking about) -- and start
giving the appropriate care to naming public entities, no matter /what/
they are. (Besides, I don't know many coding rules that say that creating
an accessor get/setTemporaryBuffer that acts on the private member tmp is
good style.)

I'm just starting to get started with Python, but it seems that the leading
underscore marks private entities.

Yes, it means "implementation, don't touch or you're on your own".
So why don't you precede everything with
an underscore that doesn't have a name that fulfills your criteria for a
decent public name -- no matter what kind of entity it is?

It seems you are basically complaining that you used a crappy name in a
public API.

Obviously... And blaming the language for this won't help.
Well... you shouldn't, not in Python, and not in any other
language :) And there's no way around it, not in Python, and not in any
other language, than to rename that entity in the public API. Which can be
a major hassle, close to impossible. There are all kinds of public APIs
with crappy names (using accessors and all :) that got created early on and
never changed. Stuff happens.

Maybe you didn't know about the underscore way to mark private entities.
Maybe this doesn't work as I think it does

If you think that single leading underscores have a special meaning for
the compiler/interpreter, then you got it wrong. It's a convention. Like
using ALL_CAPS for pseudo-constants. Nothing prevents you from accessing
implementation or modifying "constants" - but then you're on your own
and must not complain when something breaks.
 
F

Fredrik Lundh

mystilleef said:
Right, and what if I want to change a private API to a public one. How
does that solve my naming issues.

if your code is as muddled as your rhetorics, your only solution might be
to give up programming.

</F>
 
M

mystilleef

Bruno said:
mystilleef wrote:
(snip)

Yes it does.

No it doesn't.
Then you provide a public API on top of the private one.

class MyClass(object):
def __init__(self, ...):
self._attr = XXX

# seems like we really have enough use
# cases to justify exposing _imp_attr
@apply
def attr():
def fget(self):
return self._attr
def fset(self):
self._attr = attr
return property(**locals())


def _method(self, ...):
# code here

# seems like we really have enough use
# cases to justify exposing _imp_method
method = _impmethod

Note that none of this actually breaks encapsulation.

Ha! Just as bad as getters and setter.
How could this solve *your* naming issue ? This is totally unrelated.
You choose a bad name for a *public* symbol.

My point exactly! It doesn't solve my problem!
So what are computed attributes ?


"allmost all languages" lacks computed attributes.
*sighs*
 
M

mystilleef

Fredrik said:
if your code is as muddled as your rhetorics, your only solution might be
to give up programming.

</F>
There's no correlation between rhetorics and programming. That's like
me saying if you are trying to be sarcastic your only solution might be
to give up programming.
 
B

Bruno Desthuilliers

mystilleef said:
(snip)


Right, but tmp isn't private.

Right, but that's your choice. Would you complain about "almost any
other language" if you had to hunt a badly named public method thru 27KLOC ?

(snip)
Ha! I bet you haven't read too many Python codes.
I have read tens of thousands LOC of Python in the seven past years.
Computed attributes came in with 2.2x IIRC, so there's a lot of 'legacy'
code that uses getters and setters. Porting this code to a
computed-attribute style would break all client code. Having the two
schemes coexisting would make for bloated APIs and
too-many-ways-to-do-it. So we live with this until Py3K. And none of
these considerations contradicts the point that there's no more use for
javaish getters/setters in Python, nor that javaish getters/setters are
not pythonic.
 
M

mystilleef

Bruno said:
Right, but that's your choice. Would you complain about "almost any
other language" if you had to hunt a badly named public method thru 27KLOC ?
Methods are used to perform actions. Data attributes usually aren't. We
are on different planes.
(snip)

I have read tens of thousands LOC of Python in the seven past years.
Computed attributes came in with 2.2x IIRC, so there's a lot of 'legacy'
code that uses getters and setters. Porting this code to a
computed-attribute style would break all client code. Having the two
schemes coexisting would make for bloated APIs and
too-many-ways-to-do-it. So we live with this until Py3K. And none of
these considerations contradicts the point that there's no more use for
javaish getters/setters in Python, nor that javaish getters/setters are
not pythonic.
I never made any contradictory points regarding the matter. I wanted to
know the pythonic way of using accessors in Python. That's all. You are
the person making wild assumptions about my queries, programming
background and code.
 
F

Fredrik Lundh

mystilleef said:
There's no correlation between rhetorics and programming. That's like
me saying if you are trying to be sarcastic your only solution might be
to give up programming.

sarcasm doesn't imply lack of intelligence.

</F>
 
F

Fredrik Lundh

mystilleef said:
Pretending to be intelligent does, however.

so the real reason you've written a few hundred posts saying basically "I pick
bad names, which proves... uh... whatever" is to impress people by pretending
to be something you're not ?

</F>
 
B

Bruno Desthuilliers

mystilleef said:
Thank you, that was helpful.

What am I supposed to say ? You choose a bad name for a public symbol,
used it in 27000 lines of Python code (which certainly took some time to
write), and all of a sudden you realize the name is bad and proceed to
fix the problem. If you know of any other way than a massive
find/replace, please share. But blaming the language for your error
won't help.
What does it matter? There are 10 million and one reasons from given
identifiers bad names.

And how many reasons to use a bad name in 27000 LOCs before deciding to
fix the problem ?
I didn't say it wasn't.

Yes you did. May I quote ?
"""
"tmp" is obvious to me, but not necessarily to others. Now compare that
to the accessors. Not only do they improve readability at the expense
of more code, they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.
"""

This obviously implies that you don't understand 'tmp' as being an accessor.
I didn't name the attribute temporary_buffer, I named it tmp.

You didn't name the *accessor* 'temporary_buffer', you named it 'tmp'.
You are *exactly* in the same situation as if you had used getter/setter
named "get_tmp" and 'set_tmp". And your point about getters/setters
"improving readability" is moot.
No, it isn't.

May I quote what wou wrote a few lines above in this very same post ?
"""
I didn't say it wasn't.
"""

Don't you see any contradiction here ?
In Java there's a clear distinction between attributes
and methods.

Yes, and that's a big weakness of Java. But that's another point, and
absolutely irrelevant here. Failing to understand a language semantics
gives no right to complain about the language.

I choose good names for most of my APIs. But there cases when you never
know an attribute will actually be an API before hand.

Then don't make it part of the API. And anyway, 27000 lines of Python
take some time to write, so you had the opportunity to address the
problem long ago - FWIW, you could have fixed it as soon as you noticed
you were accessing this attribute in client code.
Ha, right! I bet you are perfect developer.

Certainly not, but I wouldn't confuse my own problems with a general
rule. Note FWIW that I wouldn't blame a language (or my lack of
understanding of that language) for my own errors.
I didn't say attributes weren't objects.

Nope, but you constantly bring that false "data/method" dichotomy in
your justifications for having badly named a public symbol.
I don't see the confusion.

Was just an advice against a very common mistake.
Thank you.

For what ? You "don't hold data attributes to such standard". As a
consequence (and as a result of not having addressed the problem
sooner), you end up fixing 27000 lines of code. Too bad for you then.
Some would haved learned from the mistake, which then would have turned
into experience. Seems more and more obvious that you prefer to come
whining here instead and blaming the language for your own errors. Too
bad for you again.
I thought that too was unpythonic.

It's a well-known convention, as you would have noticed if you had read
some existing python code, read PEP8, or just looked/asked for Python
naming conventions. FWIW, that's one of the first thing I learned with
Python.
Or objects have state and behavior. Data attributes represent state and
methods represent behavior.

Is a getter "behaviour" ? If yes, how does this differ from public
"data" attributes from a semantic POV ?

You don't share my pain.

Are you me to know what I feel ?
You seem to mock it.

Compassion doesn't imply agreeing on wrong arguments.
I'm not new to Python
either.

New enough to not understand how Python's object model, semantic and
overall philosophy strongly differs from Java/C++.
I've been using it for over 2 years in several capacities. I
only recently decided to use it for a large project.



I never intended it to be part of the API.

So you should not have used it outside the class.
It evolved to be an
important part of the system.

Then you had plenty of occasions to address the problem.
That's nonsense.

Your opinion. Facts tell otherwise.
I only just noticed because I was trying to implement
a plug-in system and I needed to expose an important class. I would not
have considered the issue a problem without this requirement. Except
you are a prophet, you sometimes can't know before hand how certain
classes will end up being used especially if requirements suddenly
change.

Yes, that's something I'm well aware of. And that's why I pay attention
to naming and to interface/implementation separation.
Saying it's my fault to make yourself feel better about your
favorite language doesn't help solve my problem.

I don't say it's your fault to "make (myself) feel better about (my)
favorite language, but because the problem is entirely and only yours.
Python has it's share of warts, and I'm not denying it.
I didn't come here to
be berated.

Nope, but you came here blaming the language for your own errors, and
constantly refuse to aknowledge that *you* got it wrong.
I came here to learn the Pythonic way to implementing
accessors.

With public attributes when there's no processing to do, with computed
attributes (based on descriptors, property being the most commonly used)
else. But this is totally unrelated to the issue with badly chosen
public names.
And of course how to deal with issues like the one I have in
medium size to large scale projects. People make mistakes, we deal with
an move on.

When one makes mistake, one can either choose to aknowledge the fact and
learn from it, or to find something/someone else to blame and not learn
anything.
 
B

Bruno Desthuilliers

mystilleef said:
Methods are used to perform actions. Data attributes usually aren't. We
are on different planes.

Please explain the profound *semantic* difference between:

val = obj.getVal()
obj.setVal(val)

and

val = obj.val
pbj.val = val


I never made any contradictory points regarding the matter. I wanted to
know the pythonic way of using accessors in Python.

Yes, and you had the answer.
That's all. You are
the person making wild assumptions about my queries,
programming background and code.

Which "wild assumptions" ? I'm only replying to things you post here.

Namely, you wrote this:
"
I decided to change the name of an attribute. Problem is I've used the
attribute in several places spanning thousands of lines of code. If I
had encapsulated the attribute via an accessor, I wouldn't need to do
an unreliable and tedious search and replace accross several source
code files to achieve my goal.
"

As anyone here has tried to explain, this assertion is plain wrong. I
agree that Diez's post (you were responding too) was a bit aggressive,
but that doesn't make your assertion more valid.
 
M

mystilleef

Fredrik said:
so the real reason you've written a few hundred posts saying basically "I pick
bad names, which proves... uh... whatever" is to impress people by pretending
to be something you're not ?

</F>

Choosing bad identifiers is not a measure of intelligence. Given your
standing in the Python community, I expect more from you. If your only
contribution to this thread is snide and derisive remarks, you leave me
no choice but to ignore you.
 
B

Bruno Desthuilliers

mystilleef said:
No it doesn't.




Ha! Just as bad as getters and setter.

What point are you trying to make here ? Of course a computed attribute
is just syntactic sugar for getters and setters - what else could it be?

The difference is that you don't need to write explicit getters/setters
beforehand, nor to use a "behaviour" semantic.
My point exactly! It doesn't solve my problem!

What do you hope ? Something that cures cancer ? Please enlighten us and
explain how explicit getters/setters would have solved the problem of
badly named getters/setters ?
 
M

mystilleef

Bruno said:
What am I supposed to say ? You choose a bad name for a public symbol,
used it in 27000 lines of Python code (which certainly took some time to
write),

This is a __baseless__ statement. For all you know I could have used
the attribute twice in those 27000 lines of code. Even then searching
for and replacing the attribute is tedious and error prone.
and all of a sudden you realize the name is bad and proceed to
fix the problem.

Yes, the same way many programmers suddenly realize their class,
function, method, project, etc is poorly designed even after using it
for months and proceed to fix the problem. Shit happens.
If you know of any other way than a massive
find/replace, please share.

I wouldn't have started the topic if I did. Apparently the only
solution is to rereference the attribute with a better name and pray
and hope third party developers will use the better name. Or search and
replace!
But blaming the language for your error won't help.

I did no such thing, you are making that up.
And how many reasons to use a bad name in 27000 LOCs before deciding to
fix the problem ?

Do you really think I used the name 27000 times in 27000 lines of code?
Maybe I'm not making myself clear. Having to search 27000 lines of code
to replace an identifier name is tedious and error prone.
Yes you did. May I quote ?
"""
"tmp" is obvious to me, but not necessarily to others. Now compare that
to the accessors. Not only do they improve readability at the expense
of more code, they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.
"""

This obviously implies that you don't understand 'tmp' as being an accessor.

You are quoting me out of context. I was speaking with respect to real
accessors, not Python's latent implementation mechanisms.
You didn't name the *accessor* 'temporary_buffer', you named it 'tmp'.
You are *exactly* in the same situation as if you had used getter/setter
named "get_tmp" and 'set_tmp". And your point about getters/setters
"improving readability" is moot.

No I'm not. Naming attributes and naming methods are entirely different
situations.
May I quote what wou wrote a few lines above in this very same post ?
"""
"""

Don't you see any contradiction here ?


Yes, and that's a big weakness of Java. But that's another point, and
absolutely irrelevant here. Failing to understand a language semantics
gives no right to complain about the language.

I never complained about either languages. You are making that up.
Then don't make it part of the API. And anyway, 27000 lines of Python
take some time to write, so you had the opportunity to address the
problem long ago - FWIW, you could have fixed it as soon as you noticed
you were accessing this attribute in client code.

Yes, I fixed it then. Which was 27000 lines of code later.
Certainly not, but I wouldn't confuse my own problems with a general
rule. Note FWIW that I wouldn't blame a language (or my lack of
understanding of that language) for my own errors.

Can you point me to exactly where I blamed Python for anything?
Nope, but you constantly bring that false "data/method" dichotomy in
your justifications for having badly named a public symbol.

There is a dichotomy between data and methods. Yes even in Python.
Was just an advice against a very common mistake.


For what ? You "don't hold data attributes to such standard". As a
consequence (and as a result of not having addressed the problem
sooner), you end up fixing 27000 lines of code. Too bad for you then.
Some would haved learned from the mistake, which then would have turned
into experience. Seems more and more obvious that you prefer to come
whining here instead and blaming the language for your own errors. Too
bad for you again.

That's just silly. I openly admitted to making a mistake. I asked a
query as how to prevent such mistakes in the future, and all I get is
how I'm a dumb programmer and how Python is not Java and how I'm not
intelligent among other rubbish, and how I'm at fault, yaddi yadda.
Only two people actually took the time to "address" my problem.
It's a well-known convention, as you would have noticed if you had read
some existing python code, read PEP8, or just looked/asked for Python
naming conventions. FWIW, that's one of the first thing I learned with
Python.

I know. Many people still think the private/public classification is
unpythonic.
Is a getter "behaviour" ? If yes, how does this differ from public
"data" attributes from a semantic POV ?

Yes, a getter is a behavior. It instructs the object to perform an
action. All methods are message channels to an object. A data attribute
does not perform any action. It just holds data for an object. Even
though methods are attributes, attributes aren't necessarily methods.
This is basic OO, I don't see anything semantically complex about it.
Are you me to know what I feel ?


Compassion doesn't imply agreeing on wrong arguments.


New enough to not understand how Python's object model, semantic and
overall philosophy strongly differs from Java/C++.

This isn't an issue about object models and semantics, this is a
design/architecture issue with regards to eliminating the chances of
errors in large source code.
So you should not have used it outside the class.

The fact that I did, means I should have.
Then you had plenty of occasions to address the problem.

And how did you come up with that?
Your opinion. Facts tell otherwise.

What facts?
Yes, that's something I'm well aware of. And that's why I pay attention
to naming and to interface/implementation separation.

Good for you.
I don't say it's your fault to "make (myself) feel better about (my)
favorite language, but because the problem is entirely and only yours.
Python has it's share of warts, and I'm not denying it.


Nope, but you came here blaming the language for your own errors, and
constantly refuse to aknowledge that *you* got it wrong.


With public attributes when there's no processing to do, with computed
attributes (based on descriptors, property being the most commonly used)
else. But this is totally unrelated to the issue with badly chosen
public names.


When one makes mistake, one can either choose to aknowledge the fact and
learn from it, or to find something/someone else to blame and not learn
anything.

I still don't know what or who I blamed.
 
M

mystilleef

Bruno said:
What point are you trying to make here ? Of course a computed attribute
is just syntactic sugar for getters and setters - what else could it be?

The difference is that you don't need to write explicit getters/setters
beforehand, nor to use a "behaviour" semantic.


What do you hope ? Something that cures cancer ? Please enlighten us and
explain how explicit getters/setters would have solved the problem of
badly named getters/setters ?
I did already. If I had used Java, Eiffel, Smalltalk or C++, I would
have easily changed tmp to temporary_buffer without having search and
replace or grep 27000 lines of code. The point of accessors in those
languages is encapsulation. Which means I can change any detail of
implementation, yes including names of attributes, without breaking
code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top