By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,267 Members | 1,808 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,267 IT Pros & Developers. It's quick & easy.

Accessors in Python (getters and setters)

P: n/a
Hello,

What is the Pythonic way of implementing getters and setters. I've
heard
people say the use of accessors is not Pythonic. But why? And what is
the alternative? I refrain from using them because they smell
"Javaish."
But now my code base is expanding and I'm beginning to appreciate the
wisdom behind them. I welcome example code and illustrations.

Regards

Jul 10 '06 #1
Share this Question
Share on Google+
112 Replies


P: n/a
mystilleef <my********@gmail.comwrote:
What is the Pythonic way of implementing getters and setters.
Using public members and turning them into properties when needed
I've
heard
people say the use of accessors is not Pythonic. But why?
Because there's no need to have them everywhere
But now my code base is expanding and I'm beginning to appreciate the
wisdom behind them. I welcome example code and illustrations.
Search for "python property"

--
Lawrence - http://www.oluyede.org/blog
"Nothing is more dangerous than an idea
if it's the only one you have" - E. A. Chartier
Jul 10 '06 #2

P: n/a
mystilleef wrote:
Hello,

What is the Pythonic way of implementing getters and setters. I've
heard
people say the use of accessors is not Pythonic. But why? And what is
the alternative? I refrain from using them because they smell
"Javaish."
But now my code base is expanding and I'm beginning to appreciate the
wisdom behind them. I welcome example code and illustrations.
Which wisdom do you mean? The wisdom that a language that has no property
mechanism and thus can't intercept setting and getting of instance members
needs a bulky convention called JAVA Beans, so that _all_ uses of
properties are tunneled through some code, even if only a few percent of
these actually need that?

Or the wisdom that strangling developers by putting access modifiers with
approx. a dozen different rules in place is an annoyance to adult
developers to say the least?

These are the reasons they are not pythonic. We can intercept property
access (see the property descriptor, http://pyref.infogami.com/property),
and we trust in developers being able to judge form themselves if messing
with internals of code is a good idea or not.

Regards,

Diez

Jul 10 '06 #3

P: n/a
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. I could simply change the name of the
attribute and move on. Well, I'm glad python has properties. It's a
feature that should be advertised more, especially for large scale
python development.

Diez B. Roggisch wrote:
mystilleef wrote:
Hello,

What is the Pythonic way of implementing getters and setters. I've
heard
people say the use of accessors is not Pythonic. But why? And what is
the alternative? I refrain from using them because they smell
"Javaish."
But now my code base is expanding and I'm beginning to appreciate the
wisdom behind them. I welcome example code and illustrations.

Which wisdom do you mean? The wisdom that a language that has no property
mechanism and thus can't intercept setting and getting of instance members
needs a bulky convention called JAVA Beans, so that _all_ uses of
properties are tunneled through some code, even if only a few percent of
these actually need that?

Or the wisdom that strangling developers by putting access modifiers with
approx. a dozen different rules in place is an annoyance to adult
developers to say the least?

These are the reasons they are not pythonic. We can intercept property
access (see the property descriptor, http://pyref.infogami.com/property),
and we trust in developers being able to judge form themselves if messing
with internals of code is a good idea or not.

Regards,

Diez
Jul 10 '06 #4

P: n/a
Ant

mystilleef wrote:
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. I could simply change the name of the
attribute and move on.
You could, but then you'd be left with crap names for your accessors!
In your equivalent Java code, you'd typically have used the accessors
in several places throughout the code (or else why bother using them?),
so you wouldn't be any better off!

The main benefit for having accessors in Java is not that you can
change the *name* of an attribute, but that you can change the
implementation of the attribute - i.e. change the what actually happens
to when the accessor is called. Which you can do in Python with
properties.

Jul 10 '06 #5

P: n/a
mystilleef wrote:
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. I could simply change the name of the
attribute and move on. Well, I'm glad python has properties. It's a
feature that should be advertised more, especially for large scale
python development.
Ergh, I don't see how the name-changing of an attribute makes any difference
with respect to the application of getters/setters.

Where is the difference in searching my_attribute vs. getMyAttribute
throughout your code?

Or do you mean that you changed

def getFoo(self):
return self.foo

to something like

def getFoo(self):
return self.fooSomething

? I'd say that whatever reasoning which inspired you to change foo to
fooSomething applies to getFoo as well.

Regards,

Diez
Jul 10 '06 #6

P: n/a
mystilleef wrote:
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
find and grep are usually mostly reliable for this kind of tasks.
accross several source
code files to achieve my goal. I could simply change the name of the
attribute and move on.
Why did you change the name of the attribute ? If it was to better
reflect the semantic, then it's a change in the API and getters/setters
wouldn't have help (you'd have to do the same "tedious and unreliable"
search/replace dance). If it's about implementation, then it was time to
use a property - that's what they are for.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 10 '06 #7

P: n/a

mystilleef wrote:
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. I could simply change the name of the
attribute and move on. Well, I'm glad python has properties. It's a
feature that should be advertised more, especially for large scale
python development.

Diez B. Roggisch wrote:
mystilleef wrote:
Hello,
>
What is the Pythonic way of implementing getters and setters. I've
heard
people say the use of accessors is not Pythonic. But why? And what is
the alternative? I refrain from using them because they smell
"Javaish."
But now my code base is expanding and I'm beginning to appreciate the
wisdom behind them. I welcome example code and illustrations.
Which wisdom do you mean? The wisdom that a language that has no property
mechanism and thus can't intercept setting and getting of instance members
needs a bulky convention called JAVA Beans, so that _all_ uses of
properties are tunneled through some code, even if only a few percent of
these actually need that?

Or the wisdom that strangling developers by putting access modifiers with
approx. a dozen different rules in place is an annoyance to adult
developers to say the least?

These are the reasons they are not pythonic. We can intercept property
access (see the property descriptor, http://pyref.infogami.com/property),
and we trust in developers being able to judge form themselves if messing
with internals of code is a good idea or not.

Regards,

Diez
The property() mechanism gets rid of the need for getters and setters,
as you can invisibly change a member variable into a getter/setter as
needed. Nothing else needs to know that its using a property and not a
getter/setter.

Nothing like being forced to write getters and setters in C++/Java
before you feel like shooting your source code. Please don't bring
this code-rage into Python.

To refactor a name in your code, take a look at Bicycle Repair Man
[http://bicyclerepair.sourceforge.net/]. It integrates into Eclipse
via PyDev, and allows you to refactor variable names, class names, and
method names fairly easily.

Good luck!

--Jason

Jul 10 '06 #8

P: n/a
ZeD
Bruno Desthuilliers wrote:
>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
find and grep are usually mostly reliable for this kind of tasks.
you mean sed :)

sed 's/oldName/newName/g' oldFile newFile

--
Under construction
Jul 11 '06 #9

P: n/a
ZeD wrote:
Bruno Desthuilliers wrote:

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

find and grep are usually mostly reliable for this kind of tasks.


you mean sed :)
No, I meant find and grep.
sed 's/oldName/newName/g' oldFile newFile
Yeah, fine - as long as your pretty sure the same name is not used in
other contexts in any of the source files...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 11 '06 #10

P: n/a
Hello,

Thanks for the responses. The reason I want to change the name of the
attribute is because it doesn't reflect the purpose of the attribute,
anymore. The attribute was originally a string object, but not anymore.
It is primarily a readability issue. There are also a few key
attributes I don't want developers, including myself, fiddling with.
Properties /accessors are good because they allow you to encapsulate
attributes so you can change implementations at will. Some of you have
argued I would have needed to change accessor names too if I had
misnamed them earlier. It's hard to say. I find myself changing the
names of attributes a lot more frequently than I do functions or
methods. Choosing a crappy attribute name is effortless for me,
especially during intense coding sessions. I usually realize I've
choosing a crappy attribute name the next day, sometimes even later.
However, I put a lot more effort into choosing method and function
names, especially when I know it may likely be a public API. Plus it's
really hard to choose crappy accessor name.

Regards

Jul 11 '06 #11

P: n/a
mystilleef wrote:
Hello,

Thanks for the responses. The reason I want to change the name of the
attribute is because it doesn't reflect the purpose of the attribute,
anymore. The attribute was originally a string object, but not anymore.
It is primarily a readability issue. There are also a few key
attributes I don't want developers, including myself, fiddling with.
Properties /accessors are good because they allow you to encapsulate
attributes so you can change implementations at will. Some of you have
argued I would have needed to change accessor names too if I had
misnamed them earlier. It's hard to say. I find myself changing the
names of attributes a lot more frequently than I do functions or
methods. Choosing a crappy attribute name is effortless for me,
especially during intense coding sessions. I usually realize I've
choosing a crappy attribute name the next day, sometimes even later.
However, I put a lot more effort into choosing method and function
names, especially when I know it may likely be a public API.
What you need to understand here is that in Python,
1/ methods *are* attributes
2/ every attribute whose name is not prefixed by a leading underscore is
considered part of the api ('__magic__' names being a special case).

So it has nothing to do with "data vs method" dichotomy (which makes no
sens in a languages where functions and methods are objects), only with
"API vs implementation". You choosed a crappy name for an attribute
that's part of the API, so it's *exactly* the same case as if you had
chosen a crappy name for a public method in Java. Think of public "data"
attributes as magical getter/setters with the most straightforward
behaviour, and of properties as the way to override this default behaviour.
Plus it's
really hard to choose crappy accessor name.
What about getMyCrappyAttributeName/setMyCrappyAttributeName ?-)

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 11 '06 #12

P: n/a
Lousy Attribute Name:
self.tmp

Accessors:
set_temporary_buffer
get_temporary_buffer

The attribute name I chose, "tmp" sucks. I have used that name in
dozens of places spanning over 27000 LOC. There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"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. Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.

Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes. This
stems from the fact that in many languages data attributes aren't
usually part of the API, as well as the whole OO(Encapsulation) blah
blah. I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose. I don't hold data attributes to such
standards and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs, but eventually become one.
After all most data attributes are created with the purpose of serving
methods.

Bruno Desthuilliers wrote:
mystilleef wrote:
Hello,

Thanks for the responses. The reason I want to change the name of the
attribute is because it doesn't reflect the purpose of the attribute,
anymore. The attribute was originally a string object, but not anymore.
It is primarily a readability issue. There are also a few key
attributes I don't want developers, including myself, fiddling with.
Properties /accessors are good because they allow you to encapsulate
attributes so you can change implementations at will. Some of you have
argued I would have needed to change accessor names too if I had
misnamed them earlier. It's hard to say. I find myself changing the
names of attributes a lot more frequently than I do functions or
methods. Choosing a crappy attribute name is effortless for me,
especially during intense coding sessions. I usually realize I've
choosing a crappy attribute name the next day, sometimes even later.
However, I put a lot more effort into choosing method and function
names, especially when I know it may likely be a public API.

What you need to understand here is that in Python,
1/ methods *are* attributes
2/ every attribute whose name is not prefixed by a leading underscore is
considered part of the api ('__magic__' names being a special case).

So it has nothing to do with "data vs method" dichotomy (which makes no
sens in a languages where functions and methods are objects), only with
"API vs implementation". You choosed a crappy name for an attribute
that's part of the API, so it's *exactly* the same case as if you had
chosen a crappy name for a public method in Java. Think of public "data"
attributes as magical getter/setters with the most straightforward
behaviour, and of properties as the way to override this default behaviour.
Plus it's
really hard to choose crappy accessor name.

What about getMyCrappyAttributeName/setMyCrappyAttributeName ?-)

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 12 '06 #13

P: n/a
Le mercredi 12 juillet 2006 11:17, mystilleef a écrit*:
Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.
Not python developers.
This
stems from the fact that in many languages data attributes aren't
usually part of the API, as well as the whole OO(Encapsulation) blah
blah. I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.
But that's not python philosophy.
I don't hold data attributes to such
standards and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs, but eventually become one.
But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.
After all most data attributes are created with the purpose of serving
methods.
And in python the reverse can be true :

class a(object) :
def __init__(self, ro_attr) : self.__attr = ro_attr
def _getAttr(self) :
"""A method which serves an attribute"""
return self.__attr
attr = property(_getAttr)


--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Jul 12 '06 #14

P: n/a
mystilleef wrote:
Lousy Attribute Name:
self.tmp

Accessors:
set_temporary_buffer
get_temporary_buffer

The attribute name I chose, "tmp" sucks.
Well, it's surely not as descriptive as 'temporary_buffer'
I have used that name in
dozens of places spanning over 27000 LOC.
Too bad for you.
There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"tmp" is obvious to me, but not necessarily to others.
So why did you name it that way at first ?
Now compare that
to the accessors.
But 'tmp' actually *is* an accessor.
Not only do they improve readability
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

at the expense
of more code,
Indeed. In both the class and client code.
they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.
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'.
Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.
Indeed. But it's *your* responsability to choose good names for the API.
Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).
or 'tmp'.
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.
s/developpers/you/
This
stems from the fact that in many languages data attributes aren't
usually part of the API,
Once again, in Python, there is *no* such thing as 'data attributes'.
*All* attributes are *objects* - some of them callable.
as well as the whole OO(Encapsulation) blah
blah.
Don't confuse encapsulation with data-hiding.
I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.
That's true for each and every name in a program.
I don't hold data attributes to such
standards
Too bad for you.
and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs,
Then mark them as being implementation (ie : prefix them with a single
underscore).
but eventually become one.
After all most data attributes are created with the purpose of serving
methods.
Nope. You have the class API, and the class implementation. Both made of
both callable and non-callable attributes.

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.

If you intented 'tmp' to be part of the API, then you're responsible for
the bad naming. 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.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 12 '06 #15

P: n/a
Ant
Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes. This
In my experience of getters and setters in Java, most developers choose
attribute names first, and then use the IDE (Java without an IDE
*really* sucks) to auto-generate the getters and setters. So most Java
developers I have worked with pay more attention to attributes than
accessor names as these are derived anyway. So I guess it depends on
who the developers are ;-)

Jul 12 '06 #16

P: n/a
On 2006-07-12 06:17:27, mystilleef wrote:
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes. This
stems from the fact that in many languages data attributes aren't
usually part of the API, as well as the whole OO(Encapsulation) blah
blah.
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 start looking at the distinction
public vs private (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. 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. 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 (from reading this thread). But
maybe it does, and maybe that's then just part of the learning curve for
you. (And I'm sure you're not alone... :)

Gerhard

Jul 13 '06 #17

P: n/a
Gerhard Fiedler <ge*****@gmail.comwrote:
...
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
Smalltalk is a very well known object-oriented language that behaves
otherwise, just as one example.
Alex
Jul 13 '06 #18

P: n/a
Maric Michaud wrote:
Not python developers.
Nonsense!
But that's not python philosophy.
Python doesn't have any philosophy with regards to naming identifiers.
But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.
Right, and what if I want to change a private API to a public one. How
does that solve my naming issues.
And in python the reverse can be true :
The reverse is hardly ever true. 90% of public APIs in almost all
languages are methods or functions.

Jul 13 '06 #19

P: n/a
In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:
Maric Michaud wrote:
>But that's not python philosophy.
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.”
>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.
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.
>And in python the reverse can be true :
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
Jul 13 '06 #20

P: n/a
mystilleef wrote:
(snip)
Python doesn't have any philosophy with regards to naming identifiers.
Yes it does.
>
>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.
>>And in python the reverse can be true :

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.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #21

P: n/a

Bruno Desthuilliers wrote:
mystilleef wrote:
Lousy Attribute Name:
self.tmp

Accessors:
set_temporary_buffer
get_temporary_buffer

The attribute name I chose, "tmp" sucks.

Well, it's surely not as descriptive as 'temporary_buffer'
I have used that name in
dozens of places spanning over 27000 LOC.

Too bad for you.
Thank you, that was helpful.
>
There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"tmp" is obvious to me, but not necessarily to others.

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.
Now compare that
to the accessors.

But 'tmp' actually *is* an accessor.
I didn't say it wasn't.
>
Not only do they improve readability

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.
>
at the expense
of more code,

Indeed. In both the class and client code.
they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.

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.
Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.

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.
Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).
or 'tmp'.
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.

s/developpers/you/
Ha, right! I bet you are perfect developer.
This
stems from the fact that in many languages data attributes aren't
usually part of the API,

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.
as well as the whole OO(Encapsulation) blah
blah.

Don't confuse encapsulation with data-hiding.
I don't see the confusion.
>
I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.

That's true for each and every name in a program.
I don't hold data attributes to such
standards

Too bad for you.
Thank you.
and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs,

Then mark them as being implementation (ie : prefix them with a single
underscore).
I thought that too was unpythonic.
but eventually become one.
After all most data attributes are created with the purpose of serving
methods.

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

Jul 13 '06 #22

P: n/a

Marc 'BlackJack' Rintsch wrote:
In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:
Maric Michaud wrote:
But that's not python philosophy.
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."
I'm glad I'm in tune with the "python community."
>
But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.
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.
Right, but tmp isn't private.
And in python the reverse can be true :
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.
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.
Ciao,
Marc 'BlackJack' Rintsch
Jul 13 '06 #23

P: n/a
Gerhard Fiedler wrote:
On 2006-07-12 06:17:27, mystilleef wrote:

>>But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes. This
stems from the fact that in many languages data attributes aren't
usually part of the API, as well as the whole OO(Encapsulation) blah
blah.


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.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #24

P: n/a
"mystilleef" wrote:
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>

Jul 13 '06 #25

P: n/a

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

Yes it does.
No it doesn't.
>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.
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.
Ha! Just as bad as getters and setter.
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.
My point exactly! It doesn't solve my problem!
>And in python the reverse can be true :
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.
*sighs*

Jul 13 '06 #26

P: n/a
Marc 'BlackJack' Rintsch wrote:
In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:

>>Maric Michaud wrote:
(snip)
>>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.
Not even - cf my answer on this point.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #27

P: n/a

Fredrik Lundh wrote:
"mystilleef" wrote:
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>
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.

Jul 13 '06 #28

P: n/a
mystilleef wrote:
Marc 'BlackJack' Rintsch wrote:
>>In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:

>>>Maric Michaud wrote:
(snip)
>>>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.

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

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #29

P: n/a

Bruno Desthuilliers wrote:
mystilleef wrote:
Marc 'BlackJack' Rintsch wrote:
>In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:
Maric Michaud wrote:
(snip)
>>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.
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 ?
Methods are used to perform actions. Data attributes usually aren't. We
are on different planes.
(snip)
>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.
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.

Jul 13 '06 #30

P: n/a
"mystilleef" wrote:
>if your code is as muddled as your rhetorics, your only solution might be
to give up programming.

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>

Jul 13 '06 #31

P: n/a

Fredrik Lundh wrote:
"mystilleef" wrote:
if your code is as muddled as your rhetorics, your only solution might be
to give up programming.
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>
Pretending to be intelligent does, however.

Jul 13 '06 #32

P: n/a
"mystilleef" wrote:
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>

Jul 13 '06 #33

P: n/a
mystilleef wrote:
Bruno Desthuilliers wrote:
>>mystilleef wrote:
>>>Lousy Attribute Name:
self.tmp

Accessors:
set_temporary_buffer
get_temporary_buffer

The attribute name I chose, "tmp" sucks.

Well, it's surely not as descriptive as 'temporary_buffer'

>>>I have used that name in
dozens of places spanning over 27000 LOC.

Too bad for you.


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.
>
>>>There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"tmp" is obvious to me, but not necessarily to others.

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.
And how many reasons to use a bad name in 27000 LOCs before deciding to
fix the problem ?
>
>>>Now compare that
to the accessors.

But 'tmp' actually *is* an accessor.


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.
>>>Not only do they improve readability

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.
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.
>
>>>at the expense
of more code,

Indeed. In both the class and client code.

>>>they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.

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.
May I quote what wou wrote a few lines above in this very same post ?
"""
>>But 'tmp' actually *is* an accessor.


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.

>>>Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.

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.
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, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).

or 'tmp'.

>>>But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.

s/developpers/you/>

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.
>>>This
stems from the fact that in many languages data attributes aren't
usually part of the API,

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.
Nope, but you constantly bring that false "data/method" dichotomy in
your justifications for having badly named a public symbol.
>
>>>as well as the whole OO(Encapsulation) blah
blah.

Don't confuse encapsulation with data-hiding.

I don't see the confusion.
Was just an advice against a very common mistake.
>>>I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.

That's true for each and every name in a program.

>>>I don't hold data attributes to such
standards

Too bad for you.
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.
>
>>>and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs,

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

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.
>>>but eventually become one.
After all most data attributes are created with the purpose of serving
methods.

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.
Is a getter "behaviour" ? If yes, how does this differ from public
"data" attributes from a semantic POV ?

>>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.
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.
>>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.
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.
>
>>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.
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.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #34

P: n/a
mystilleef wrote:
Bruno Desthuilliers wrote:
>>mystilleef wrote:
>>>Marc 'BlackJack' Rintsch wrote:
In <11**********************@35g2000cwc.googlegroups. com>, mystilleef
wrote:

>Maric Michaud wrote:

(snip)

>>>>>>But they are in Python and that is the python's philosophy. All attribute or
>>method not beginning with an '_' *is* API.
>
>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.

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 ?

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
>>(snip)

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

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.
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.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #35

P: n/a

Fredrik Lundh wrote:
"mystilleef" wrote:
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>
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.

Jul 13 '06 #36

P: n/a
mystilleef wrote:
Bruno Desthuilliers wrote:
>>mystilleef wrote:
(snip)
>>>Python doesn't have any philosophy with regards to naming identifiers.

Yes it does.


No it doesn't.

>>>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.


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


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 ?
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #37

P: n/a

Bruno Desthuilliers wrote:
mystilleef wrote:
Bruno Desthuilliers wrote:
>mystilleef wrote:

Lousy Attribute Name:
self.tmp

Accessors:
set_temporary_buffer
get_temporary_buffer

The attribute name I chose, "tmp" sucks.

Well, it's surely not as descriptive as 'temporary_buffer'
I have used that name in
dozens of places spanning over 27000 LOC.

Too bad for you.

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),
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.
>
>>There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"tmp" is obvious to me, but not necessarily to others.

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.

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.
>>Now compare that
to the accessors.

But 'tmp' actually *is* an accessor.

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.
You are quoting me out of context. I was speaking with respect to real
accessors, not Python's latent implementation mechanisms.
>>Not only do they improve readability

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.

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.
>>at the expense
of more code,

Indeed. In both the class and client code.
they actually allow me to change the lousily named
attribute "tmp" to "temporary_buffer" without grepping, seding,
searching, replacing and praying.

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.

May I quote what wou wrote a few lines above in this very same post ?
"""
>But 'tmp' actually *is* an accessor.

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 never complained about either languages. You are making that up.
>
>>Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.

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.

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.
>>Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).

or 'tmp'.
But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.

s/developpers/you/>
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.
Can you point me to exactly where I blamed Python for anything?
>>This
stems from the fact that in many languages data attributes aren't
usually part of the API,

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.

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.
>>as well as the whole OO(Encapsulation) blah
blah.

Don't confuse encapsulation with data-hiding.
I don't see the confusion.

Was just an advice against a very common mistake.
>>I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.

That's true for each and every name in a program.
I don't hold data attributes to such
standards

Too bad for you.
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.
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.
>>and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs,

Then mark them as being implementation (ie : prefix them with a single
underscore).
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.
I know. Many people still think the private/public classification is
unpythonic.
>>but eventually become one.
After all most data attributes are created with the purpose of serving
methods.

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.

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

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

So you should not have used it outside the class.
The fact that I did, means I should have.
It evolved to be an
important part of the system.

Then you had plenty of occasions to address the problem.
And how did you come up with that?
>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.

Your opinion. Facts tell otherwise.
What facts?
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.
Good for you.
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.
I still don't know what or who I blamed.

Jul 13 '06 #38

P: n/a

Bruno Desthuilliers wrote:
mystilleef wrote:
Bruno Desthuilliers wrote:
>mystilleef wrote:
(snip)

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

Yes it does.

No it doesn't.

>>>But they are in Python and that is the python's philosophy. All attribute or
method not beginning with an '_' *is* API.

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.

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

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

Jul 13 '06 #39

P: n/a
Ant
We seem to be flogging a dead horse now. Is the following a fair
summary:

Q. What is the Pythonic way of implementing getters and setters?

A. Use attributes.

Quote: "I put a lot more effort into choosing method and function
names"

Wisdom: Python is a different paradigm from (e.g.) Java w.r.t.
accessors: Put the effort you would have put into choosing accessor
names into choosing attribute names.

Anything else to add to this? Or can it be put to bed?

Jul 13 '06 #40

P: n/a

Ant wrote:
We seem to be flogging a dead horse now. Is the following a fair
summary:

Q. What is the Pythonic way of implementing getters and setters?

A. Use attributes.

Quote: "I put a lot more effort into choosing method and function
names"

Wisdom: Python is a different paradigm from (e.g.) Java w.r.t.
accessors: Put the effort you would have put into choosing accessor
names into choosing attribute names.

Anything else to add to this? Or can it be put to bed?
Here are the lessons I've learned (the hard way).

1) Make all attributes of a class private or protected. You can make
them public later if need be. If anyone tells you making attributes
private/protected is not Pythonic ignore them. You'll thank me when
your code base grows.
2) If a data attribute might likely be an API, think about controlling
access to via "properties". That's the pythonic way to implement
accessors and mutators

I guess people who've done medium to large scale programming in Python
already know this.

Jul 13 '06 #41

P: n/a
On 10 Jul 2006 05:51:02 -0700, mystilleef <my********@gmail.comwrote:
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. I could simply change the name of the
attribute and move on. Well, I'm glad python has properties. It's a
feature that should be advertised more, especially for large scale
python development.
Something like this any use to you?

from warnings import warn
import sys

class MyClass(object):

def _get_bad_name(self):
caller = sys._getframe(1).f_code
warn("bad_name deprecated, but is referred to in function %s
(line %s in module %s). Please refer to good_name" % (caller.co_name,
caller.co_firstlineno, caller.co_filename))
return self.good_name

def _set_bad_name(self, bad_name):
caller = sys._getframe(1).f_code
warn("bad_name deprecated, but is referred to in function %s
(line %s in module %s). Please refer to good_name" % (caller.co_name,
caller.co_firstlineno, caller.co_filename))
self.good_name = bad_name

def _del_bad_name(self):
caller = sys._getframe(1).f_code
warn("bad_name deprecated, but is referred to in function %s
(line %s in module %s). Please refer to good_name" % (caller.co_name,
caller.co_firstlineno, caller.co_filename))
del self.good_name

bad_name = property(_get_bad_name, _set_bad_name, _del_bad_name,
"bad_name deprecated, please refer to good_name")

def test():
my_object = MyClass()
my_object.bad_name = "This should issue a warning"
print my_object.bad_name # This too
print my_object.good_name # But this should be fine

if __name__ == '__main__':
test()

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Jul 13 '06 #42

P: n/a
On 2006-07-13, mystilleef <my********@gmail.comwrote:
>
>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.
Well the impression we have is that should you used Jave, Eiffel, ...
You would not only have had an attribute tmp but would have had
accessores like getTmp and setTmp.

Now if you find tmp do be a bad name, it seems this would
imply that getTmp and setTmp are equally bad names. So if you
are using Java, Eiffel, ... and you want to get rid of the
bad names, it seems you have to search and replave 27000 lines
of code. You will just be replacing getTmp into getTemporary_buffer
and setTmp into setTemporary_buffer instead of just tmp into
temporary_buffer.

You seem to argue that all you had to do was change the attribute
tmp and then only needed to change the code of the class. But
what we are wondering about is why you would find tmp such a bad
name that you want to change it all over the program but
would be willing to leave names like getTmp setTmp.

So why is tmp bad in code like:

obj.tmp = f()

But is setTmp ok in code like:

obj.setTmp(f())

--
Antoon Pardon
Jul 13 '06 #43

P: n/a
mystilleef wrote:
Bruno Desthuilliers wrote:
>>mystilleef wrote:
(snip)
>>>>
>I have used that name in
>dozens of places spanning over 27000 LOC.

Too bad for you.
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),


This is a __baseless__ statement.
Please explain what's wrong ? The "bad naming" part is your own
statement, the "27000 lines" is your own statement too, and I don't see
what's wrong with the assumption that producing 27000 lines of Python
took some time.
For all you know I could have used
the attribute twice in those 27000 lines of code.
How does this make my statement wrong ? Did I imply that you used this
attribute in each and any of the 27000 lines ?
Even then searching
for and replacing the attribute is tedious and error prone.
Indeed, and whether you believe it or not, I do share your pain here. I
had to face similar problem, and without even find and grep (a dumb
'CASE Tool' that stored it's proprietary language code in a
non-documented binary format and was missing decent, reliable
search/replace utilities). And the project was actually more than
50KLOC, forms description excluded.
>
>>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.
Agreed. I don't pretend to be better than anyone else at this.
>
>>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!
Is actually this code already published ? If yes, you have the option of
making the 'tmp' accessor a computed attribute pointing to the better
named one, have the hidden getter/setter code emit a warning (including
useful informations about where the attributes is accessed - this is
opened to inspection), and officialy deprecate the badly named attribute
so you can definitively get rid of it in a near release.
>
>>But blaming the language for your error won't help.

I did no such thing, you are making that up.
Sorry, that's what I understood. If it's me being guilty of
overreaction, please accept my apologies.
>
>>>>>There's a chance that other
>develops might misinterpret exactly what "tmp" does. Plus I don't want
>emails from other developers querying me about what "tmp" is/does.
>"tmp" is obvious to me, but not necessarily to others.

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.

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?
Of course not. But since 27KLOC is far from trivial for a Python
application, one can think that you had time to notice something wrong
with the naming/use of this attribute.
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 can of course encapsulate access to the attribute in a property
and have that property either emit a warning, raise an exception, log
the access etc, so if you missed some use of it, chances are you'll find
out pretty soon. Unit tests may help too - they can be great for
reporting broken code. You may also want to look if lint-like tools
(pylint etc) can help you there.
>
>>>>>Now compare that
>to the accessors.

But 'tmp' actually *is* an accessor.
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.

You are quoting me out of context. I was speaking with respect to real
accessors, not Python's latent implementation mechanisms.
This I had understood. My point is that if you *see* a public attribute
name as really being an accessor with automagical default
getters/setters (FWIW, look at the __getattribute__ method and Python's
name lookup rules - you'll notice that it's really how it works), then
your "compare that to accessors" doesn't stand.
>
>>>>>Not only do they improve readability

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.

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.
Why ?

In Python, a "method" is nothing else than a descriptor (attribute)
returning a callable. I agree that there's a small difference between a
callable and a non-callable object, in that you can apply the __call__
operator only to callables, but this doesn't make such a difference
here. In Python, methods are attributes. And naming is naming.
>
(snip)
>>
>>>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 never complained about either languages. You are making that up.
I may be misunderstanding your point about "Java having a clear
distinction between attributes and methods" and overinterpreting it as
implying "Python doesn't and it led me into a bad situation, hence Java
is Good(tm) and Python is Bad(tm)". If so, once again, I do apologize.
>>>>>Sure, if you are dealing with less
>than a 1000LOC you can get away with using "tmp" or renaming it easily.
>But if you are dealing with a much larger code base and more
>developers, issues like this rapidly become a nuisance.

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.

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.
Not exactly a garden party.
>>>>>Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).

or 'tmp'.

>But developers tend to pay more attention to given methods/functions
>less crappy names, at least when compared to data attributes.

s/developpers/you/>

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.

Can you point me to exactly where I blamed Python for anything?
Point addressed above.
>>>>>This
>stems from the fact that in many languages data attributes aren't
>usually part of the API,

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.

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.
The only dichotomy, from a technical POV, is that methods are callable -
but so are classes, and any object that has a '__call__' attribute that
is itself a callable. The 'dichotomy' here is the same as the dichotomy
between iterable and non iterable objects. Of between file-like and
non-file like objects. IOW, the difference amounts to supported
interface, not to the very nature of the concerned objects.
>>>>>I know I would not name the accessors set_tmp/get_tmp, because my
>philosophy is that methods/functions need to have meaningful names and
>state their intended purpose.

That's true for each and every name in a program.

>I don't hold data attributes to such
>standards

Too bad for you.

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.

That's just silly.
Yes, agreed. My fault. Let's take it back and not start fighting because
of a misunderstanding.

(snip)
>>>>>and I imagine many developers don't either and least based on
>other people's code I've read. Plus there are many occassions when
>attributes are not intended to be APIs,

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

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.

I know. Many people still think the private/public classification is
unpythonic.
I'd rather say that many people thinks that language-enforced access
restrictors and the "public methods/private data" scheme are unpythonic.
And that if you're not sure wether a given name should be API or
implementation then make it part of the API - but then choose a
meaningful name for it !-)

>>>>>but eventually become one.
>After all most data attributes are created with the purpose of serving
>methods.

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.

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.
Ok. Python's name lookup all go thru the __getattribute__ accessor. So
obj.value
is a synonym for
obj.__getattribute__('value')

which, according to your definition, is behaviour. Hence, there's *no*
"data attribute" in Python.
A data attribute
does not perform any action. It just holds data for an object.
The attribute itself may not perform any action, but looking up the name
is an action.
Even
though methods are attributes, attributes aren't necessarily methods.
Indeed.
This is basic OO, I don't see anything semantically complex about it.
It becomes complex when the languages sees functions as first-order
objects supporting the Callable interfaces and let you define your own
callable objects, and sees attribute-access as call to an hidden (well,
not that much hidden) getter/setter mechanism that one as all lattitude
to customize in many ways. Seeing that way really takes you out of the
Java semantic/mindset (well, at least it did to me, and I guess for at
least a few others).
>>>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++.

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.
I was talking about the way you IMHO try to force-fit the common
"private data/public method" scheme (and it's associated dichotomy
between data and functions) into Python. Of course callable and
non-callable attributes usually have different usages, but we're really
far from the Java model where's the dichotomy between "data" and "code"
is irremediable.

Now wrt/ your naming problem, I think that you would not have done the
mistake if you had apply has much care to the naming of a non-callable
attribute as you assert (and I don't doubt you on this) you would have
for a callable one. You explain that you failed to do so because of you
viewing "data attributes" (ie non-callable attributes) as fundamentally
different from "methods" (ie callable attributes), so I try to share the
POV that Python is really different here, hoping this will help you
detect similar errors sooner.

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

So you should not have used it outside the class.
The fact that I did, means I should have.
Then if you felt it finally had to be part of the API *and* was badly
named, you should have renamed it immediatly.

But granted, it's easier to say so afterward than to make the right
choice in the moment.
>
>>>It evolved to be an
important part of the system.

Then you had plenty of occasions to address the problem.

And how did you come up with that?
By understanding "evolved" as a process (implying a timeline), and
"important part of the system" as widely used.

(snip fighting part)
>>>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.

Good for you.
That doesn't mean I get it right.

(snip, idem)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #44

P: n/a
On 7/13/06, Simon Brunning <si***@brunningonline.netwrote:
Something like this any use to you?
Or this, about a squillion times cleaner:

class MyClass(object):

def _get_bad_name(self):
warn('"bad_name" deprecated. Please refer to "good_name"', stacklevel=2)
return self.good_name

def _set_bad_name(self, bad_name):
warn('"bad_name" deprecated. Please refer to "good_name"', stacklevel=2)
self.good_name = bad_name

def _del_bad_name(self):
warn('"bad_name" deprecated. Please refer to "good_name"', stacklevel=2)
del self.good_name

bad_name = property(_get_bad_name, _set_bad_name, _del_bad_name,
'"bad_name" deprecated. Please refer to "good_name"')

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Jul 13 '06 #45

P: n/a
On 2006-07-13 06:03:40, Bruno Desthuilliers wrote:
>[...] 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.
I really did get that wrong. But this makes actually more sense,
considering the bigger picture (or what I saw from it, so far).

Thanks,
Gerhard

Jul 13 '06 #46

P: n/a
On 2006-07-13 01:50:18, Alex Martelli wrote:
>I'm not sure about which languages you are talking (pretty much all that
allow public methods also allow public attributes), [...]

Smalltalk is a very well known object-oriented language that behaves
otherwise, just as one example.
I didn't know that Smalltalk allows any methods at all... I wrote about
languages that allow public methods, and I didn't think of Smalltalk
falling into that category.

Gerhard

Jul 13 '06 #47

P: n/a
Bruno Desthuilliers wrote:
mystilleef wrote:
Bruno Desthuilliers wrote:
>mystilleef wrote:
(snip)
>>>
I have used that name in
dozens of places spanning over 27000 LOC.

Too bad for you.
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),

This is a __baseless__ statement.

Please explain what's wrong ? The "bad naming" part is your own
statement, the "27000 lines" is your own statement too, and I don't see
what's wrong with the assumption that producing 27000 lines of Python
took some time.
For all you know I could have used
the attribute twice in those 27000 lines of code.

How does this make my statement wrong ? Did I imply that you used this
attribute in each and any of the 27000 lines ?
Even then searching
for and replacing the attribute is tedious and error prone.

Indeed, and whether you believe it or not, I do share your pain here. I
had to face similar problem, and without even find and grep (a dumb
'CASE Tool' that stored it's proprietary language code in a
non-documented binary format and was missing decent, reliable
search/replace utilities). And the project was actually more than
50KLOC, forms description excluded.
>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.

Agreed. I don't pretend to be better than anyone else at this.
>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!

Is actually this code already published ? If yes, you have the option of
making the 'tmp' accessor a computed attribute pointing to the better
named one, have the hidden getter/setter code emit a warning (including
useful informations about where the attributes is accessed - this is
opened to inspection), and officialy deprecate the badly named attribute
so you can definitively get rid of it in a near release.
>But blaming the language for your error won't help.
I did no such thing, you are making that up.

Sorry, that's what I understood. If it's me being guilty of
overreaction, please accept my apologies.
>>>>There's a chance that other
develops might misinterpret exactly what "tmp" does. Plus I don't want
emails from other developers querying me about what "tmp" is/does.
"tmp" is obvious to me, but not necessarily to others.

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.

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?

Of course not. But since 27KLOC is far from trivial for a Python
application, one can think that you had time to notice something wrong
with the naming/use of this attribute.
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 can of course encapsulate access to the attribute in a property
and have that property either emit a warning, raise an exception, log
the access etc, so if you missed some use of it, chances are you'll find
out pretty soon. Unit tests may help too - they can be great for
reporting broken code. You may also want to look if lint-like tools
(pylint etc) can help you there.
>>>>Now compare that
to the accessors.

But 'tmp' actually *is* an accessor.
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.
You are quoting me out of context. I was speaking with respect to real
accessors, not Python's latent implementation mechanisms.

This I had understood. My point is that if you *see* a public attribute
name as really being an accessor with automagical default
getters/setters (FWIW, look at the __getattribute__ method and Python's
name lookup rules - you'll notice that it's really how it works), then
your "compare that to accessors" doesn't stand.
>>>>Not only do they improve readability

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.

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.

Why ?

In Python, a "method" is nothing else than a descriptor (attribute)
returning a callable. I agree that there's a small difference between a
callable and a non-callable object, in that you can apply the __call__
operator only to callables, but this doesn't make such a difference
here. In Python, methods are attributes. And naming is naming.
(snip)
>
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 never complained about either languages. You are making that up.

I may be misunderstanding your point about "Java having a clear
distinction between attributes and methods" and overinterpreting it as
implying "Python doesn't and it led me into a bad situation, hence Java
is Good(tm) and Python is Bad(tm)". If so, once again, I do apologize.
>>>>Sure, if you are dealing with less
than a 1000LOC you can get away with using "tmp" or renaming it easily.
But if you are dealing with a much larger code base and more
developers, issues like this rapidly become a nuisance.

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.

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.

Not exactly a garden party.
>>>>Yes, it is possible to name crappy accessors too (e.g set_tmp/get_tmp).

or 'tmp'.

But developers tend to pay more attention to given methods/functions
less crappy names, at least when compared to data attributes.

s/developpers/you/>

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.
Can you point me to exactly where I blamed Python for anything?

Point addressed above.
>>>>This
stems from the fact that in many languages data attributes aren't
usually part of the API,

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.

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.

The only dichotomy, from a technical POV, is that methods are callable -
but so are classes, and any object that has a '__call__' attribute that
is itself a callable. The 'dichotomy' here is the same as the dichotomy
between iterable and non iterable objects. Of between file-like and
non-file like objects. IOW, the difference amounts to supported
interface, not to the very nature of the concerned objects.
>>>>I know I would not name the accessors set_tmp/get_tmp, because my
philosophy is that methods/functions need to have meaningful names and
state their intended purpose.

That's true for each and every name in a program.

I don't hold data attributes to such
standards

Too bad for you.

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.
That's just silly.

Yes, agreed. My fault. Let's take it back and not start fighting because
of a misunderstanding.

(snip)
>>>>and I imagine many developers don't either and least based on
other people's code I've read. Plus there are many occassions when
attributes are not intended to be APIs,

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

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.
I know. Many people still think the private/public classification is
unpythonic.

I'd rather say that many people thinks that language-enforced access
restrictors and the "public methods/private data" scheme are unpythonic.
And that if you're not sure wether a given name should be API or
implementation then make it part of the API - but then choose a
meaningful name for it !-)

>>>>but eventually become one.
After all most data attributes are created with the purpose of serving
methods.

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.

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.

Ok. Python's name lookup all go thru the __getattribute__ accessor. So
obj.value
is a synonym for
obj.__getattribute__('value')

which, according to your definition, is behaviour. Hence, there's *no*
"data attribute" in Python.
A data attribute
does not perform any action. It just holds data for an object.

The attribute itself may not perform any action, but looking up the name
is an action.
Even
though methods are attributes, attributes aren't necessarily methods.

Indeed.
This is basic OO, I don't see anything semantically complex about it.

It becomes complex when the languages sees functions as first-order
objects supporting the Callable interfaces and let you define your own
callable objects, and sees attribute-access as call to an hidden (well,
not that much hidden) getter/setter mechanism that one as all lattitude
to customize in many ways. Seeing that way really takes you out of the
Java semantic/mindset (well, at least it did to me, and I guess for at
least a few others).
>>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++.
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.

I was talking about the way you IMHO try to force-fit the common
"private data/public method" scheme (and it's associated dichotomy
between data and functions) into Python. Of course callable and
non-callable attributes usually have different usages, but we're really
far from the Java model where's the dichotomy between "data" and "code"
is irremediable.

Now wrt/ your naming problem, I think that you would not have done the
mistake if you had apply has much care to the naming of a non-callable
attribute as you assert (and I don't doubt you on this) you would have
for a callable one. You explain that you failed to do so because of you
viewing "data attributes" (ie non-callable attributes) as fundamentally
different from "methods" (ie callable attributes), so I try to share the
POV that Python is really different here, hoping this will help you
detect similar errors sooner.

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

So you should not have used it outside the class.
The fact that I did, means I should have.

Then if you felt it finally had to be part of the API *and* was badly
named, you should have renamed it immediatly.

But granted, it's easier to say so afterward than to make the right
choice in the moment.
>>It evolved to be an
important part of the system.

Then you had plenty of occasions to address the problem.
And how did you come up with that?

By understanding "evolved" as a process (implying a timeline), and
"important part of the system" as widely used.

(snip fighting part)
>>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.
Good for you.

That doesn't mean I get it right.

(snip, idem)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Okay, I feel I need to make myself clear. I certainly I'm not blaming
Python for my mistakes. And I don't think language X is better than
Python or vice-versa. Okay scrap the vice-versa. It was silly of me to
name the variable tmp regardless of whatever excuses I have. This also
doesn't mean in the future I wouldn't use shitty names for my
attributes. :-) I most likely will. But at least now I know how to
minimize its impact of such carelessness. I mentioned them above but I
repeat it hear again.

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

Other than that we are just arguing semantics of language. For example,
your view of objects is by categorizing its attributes in callable and
non-callable. However, my categorization is state(data) and
behavior(methods). Neither ways of thinking about it is wrong. It just
reflects the way we design classes. When I'm coding I certainly don't
care about how Python accesses tmp. What I do care about is how to
change tmp without breaking code left, right and center and the
facilities Python provides for making my code robust. Most other OO
languages provide accessors in addition to keywords for that kind of
stuff. I knew it wasn't Pythonic, but I wanted to know the Pythonic way
to do it. So I asked. My query does not automatically suggest Python
sucks. Neither those it suggest that Java or other OO languages are
better. I asked because I sincerely wanted to know the Pythonic way
handling issues like that.

Jul 13 '06 #48

P: n/a
mystilleef schreef:
Ant wrote:
>We seem to be flogging a dead horse now. Is the following a fair
summary:

Q. What is the Pythonic way of implementing getters and setters?

A. Use attributes.

Quote: "I put a lot more effort into choosing method and function
names"

Wisdom: Python is a different paradigm from (e.g.) Java w.r.t.
accessors: Put the effort you would have put into choosing accessor
names into choosing attribute names.

Anything else to add to this? Or can it be put to bed?

Here are the lessons I've learned (the hard way).

1) Make all attributes of a class private or protected. You can make
them public later if need be. If anyone tells you making attributes
private/protected is not Pythonic ignore them. You'll thank me when
your code base grows.
2) If a data attribute might likely be an API, think about controlling
access to via "properties". That's the pythonic way to implement
accessors and mutators

I guess people who've done medium to large scale programming in Python
already know this.
Here's what I have learned from this discussion:

1. Give all symbols in your public interface a sensible name.
2. Don't use accessors and mutators for trivial attributes. If needed
you can always add them later via properties.

You seem to imply that your rule #1 would have prevented the problem
you're experiencing. After this whole discussion, frankly I still don't
understand how it would have done that.

--
If I have been able to see further, it was only because I stood
on the shoulders of giants. -- Isaac Newton

Roel Schroeven
Jul 13 '06 #49

P: n/a
mystilleef wrote:
Bruno Desthuilliers wrote:
>>>>You choose a bad name for a *public* symbol.
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 ?

I did already. If I had used Java, Eiffel, Smalltalk or C++, I would
have easily changed tmp to temporary_buffer
What I ask you is about renaming get_tmp/set_tmp to get_temporary_buffer
and set_temporary_buffer.
without having search and
replace or grep 27000 lines of code. The point of accessors in those
languages is encapsulation.
Nope, the point of accessors (in the meaning of get_XXX/set_XXX *public*
methods) is to remedy the lack of support for computed attributes syntax
(ie accessing something like a public data member when it really go thru
implementation methods).

Encapsulation is about depending on an interface, not an implementation.
Your problem is really with interface change, not implementation change.
Which means I can change any detail of
implementation, yes including names of attributes, without breaking
code.
I'm not asking about to rename an *implementation* attribute, but about
how to rename a pair of *API* badly named getter/setter.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 13 '06 #50

112 Replies

This discussion thread is closed

Replies have been disabled for this discussion.