Accessors in Python (getters and setters)

B

Ben C

IMO that's not quite true. Ultimately, the state always gets changed by
something else (user interaction, physical events); very few objects are
completely self-contained in their behavior.

In most systems (and you possibly have written some of them) are objects
whose state gets changed by other objects -- possibly through the
intermediation of setter methods that do nothing else but set the state.
There's no conceptual difference between directly setting the state or
calling a setter function that does nothing else but directly setting the
state -- except for one unnecessary level of indirection in the latter.

The conceptual difference is that a function call is more like an "event",
a variable is more like a "process".

An object that provides a setter is a process that is prepared to engage
in this "set event". An object that exposes a variable is a process that
interacts with this variable which the user is also invited to interact
with concurrently.

So with a setter in the API, conceptually, there are two processes
sharing the set event: the object itself, and the process that's calling
the setter. With an exposed variable, there are three: the object, the
variable in between, and the calling process.

Restricting yourself to setters and getters is a bit like saying we
build a machine that only has touch-keys and lights on the outside.
Shared variables are more like a machine with levers and dials you set,
and bits that pop up, like the numbers on mechanical cash-registers.
They have "state" on the outside, not just on the inside. Such designs
can be less tolerant of unsympathetic input-- think how easy it is to
jam up an old-fashioned typewriter if you just press a few keys at the
same time.

There isn't any practical difference, as you say, if all the setter does
is set. But it might easily do a few other subtle things, in particular
wait for a good moment to actually effect the change.
 
G

Gerhard Fiedler

State - behavior is not something I made up, so it isn't subjective. It
is a common term used in OO literature. In fact, the only reason I used
it is because I thought is was common knowledge.

Of course. But your association of state with attributes and behavior with
methods is arbitrary to a specific implementation. Of course you probably
will have always something like attributes to store state, but you may
trigger behavior just as well through state changes as you may trigger it
through method calls or other means. (Remember, this is about the public
API, not about implementation details.)

Gerhard
 
G

Gerhard Fiedler

There isn't any practical difference, as you say, if all the setter does
is set. But it might easily do a few other subtle things, in particular
wait for a good moment to actually effect the change.

I agree. But even then, for me there's no practical difference between
calling a setter that does those other subtle things, or setting an
attribute, and by this triggering the associated property handler than then
does what in the other case the setter would do.

Gerhard
 
B

Bruno Desthuilliers

mystilleef wrote:
On State and Behavior:

To understand objects in terms of state and behavior you need to
absolve yourself from implementation details of languages
and think at an abstract level.


Take a button object, for example. It has state and behavior. Possible
states may include, is_active, is_focused, is_mapped, etc. Behavior is
what the button does when it responds to events, (e.g when you click on
it, or drag it, or position a pointer over it.) If you've done any form
of event based programming (GUI/Games/Simulation), this method of
thinking becomes natural.

As you can see, when I'm designing a button object, I don't care what
Python does with is_active. I don't care how it accesses. I don't care
what is_active means to Python. I don't care about Python's __get__
/__set__ special/latent functions or implementation details. is_active
to me and every other developer is a state of the button object. And at
that level that's all that matters. Python can tell me it's just ones
and zeros for all I care.

In very well designed systems, the state of an object should only be
changed by the object.

.... as a response to a message.
For example, a third party randomly changing
is_active, (which Python lets you do freely and easily)

Unless you make it a read-only property.
from False to
True may crash your GUI.
And I'm not making this up. Things like this
do really happen depending on the whackyness of your toolkit. So
sometimes, it is my duty to protect the state of an object. Especially
if its state cannot afford to be corrupted rendering the system
unstable. And situations like this are found a plenty in event based
programming. Which is programming objects based almost entirely on
state and behavior. As you can see this has nothing to do with Python
vs Java's vs X's implementation of accessors and how using them sucks,
or how they aren't Pythonic. Some domains just require this stuff.

Properties *are* 'accessors'.
One of the requirements for designing robust object systems is ensuring
the state of objects aren't easily contaminated.

"contaminated" ???
That "state" is the
objects data (read: stuff the object needs to do something "reliably").

Makes no sens to me.
And this is why many overzealous OO languages do "force" you to use
accessors. It's not because they hate you or aren't aware of the
convenience of having direct access to an object's attributes. It's
just because these languages convenience/robustness ratios are
different.

Thinking in terms of callable vs non-callable is not helpful for me,
because it isn't high level enough.

Allo, Huston ?
Thinking in terms of state and
behavior is, because it works regardless of programming language or
implementations. This is the reason I like working with Python. I
wanted a language that didn't bore me with it semantics and allowed me
to focus on design. Let me reiterate, I'm not obsessing over language
semantics, I just need practical, not religious, solutions for my
problem domain.

Using properties instead of explicit getters/setters is pragmatism, not
religion. Using the default get/set mechanism when there's no specific
reason to do otherwise is pragmatism too. And understanding the object
model and idioms of the language you're using is IMHO the very pragmatic
thing to do...
 
B

Bruno Desthuilliers

mystilleef said:
Then in those cases the system becomes a victim of high coupling.

Time to burn your book and face reality. ObjA sends message Msg1 to
ObjB. Part of the associated behaviour is that in responce to Msg1, objB
changes it's own state. Practical result : ObjB's state has been changed
by ObjA. Practical question : how do you hope to avoid this "hi
coupling" (lol), apart from making all your objects totally autistic ?
It depends. If certain conditions need to be met before changing the
state of an object, then arbitrarily changing it can be dangerous.

Does this imply a 'method call' *syntax* ? Given the existence of
"computed attributes" (ie: support for 'attribute access' *syntax* with
hidden accessors) and the possibility to redefine implementation (from
default attribute r/w access to computed/controlled) without touching
the interface, why advocate the *systematic* use of computed attributes
when it's just duplicating the default behaviour ?

Of course using setters for the sake of just using them is pointless.
Indeed.

The reason to use them is if pre-conditions or post-conditions need to
be met. Or to control access to an objects states.

Then why advocate *systematic* use of them ?

(snip)
State - behavior is not something I made up, so it isn't subjective.

The words (and the concept they describe) are not. Interpretation of
what is state and what is behaviour is subjective.
It
is a common term used in OO literature. In fact, the only reason I used
it is because I thought is was common knowledge.

It is.
And behaviors are not
just necessarily getters/setters, they are methods of objects.

Behaviour is how a given object reacts to a given message. *Nothing* in
this implies the notions of attributes or methods. Attributes and
methods are implementation details of the concepts of state and
behaviour, and - while this is a common implementation of OO concepts -
the choice to use non-callable attributes as representing the state
and callable ones as representing behaviour is totally
implementation-dependant.
 
B

Bruno Desthuilliers

Bruno said:
mystilleef wrote: (snip)


Unless they are obviously part of the implementation

s/implementation/interface/, of course.
(ie: when you would
definitively had written getters/setters in Java), in which case make
them public (and name them with the same care you would have for Java
getters/setters). You can change the implementation later.
(snip)
 
M

mystilleef

Bruno said:
mystilleef wrote:


... as a response to a message.


Unless you make it a read-only property.

So you see the purpose of accessors then?
Properties *are* 'accessors'.

I never said they weren't.
"contaminated" ???

Make an object's state unreliable. See above example.
Makes no sens to me.

is_active is an object's data, with regards to our example.
Allo, Huston ?


Using properties instead of explicit getters/setters is pragmatism, not
religion. Using the default get/set mechanism when there's no specific
reason to do otherwise is pragmatism too. And understanding the object
model and idioms of the language you're using is IMHO the very pragmatic
thing to do...

Again, the object model of the language is irrelevant. The only
relevant model is my application's model, which should work regardless
of the language I use.
 
M

mystilleef

Bruno said:
Time to burn your book and face reality. ObjA sends message Msg1 to
ObjB. Part of the associated behaviour is that in responce to Msg1, objB
changes it's own state. Practical result : ObjB's state has been changed
by ObjA. Practical question : how do you hope to avoid this "hi
coupling" (lol), apart from making all your objects totally autistic ?

Are you serious? Well, you design an object that serves as a mediator.
All objects can then only interact with themselves and the mediator
only. Via signals, objects learn to automatically adjust their states
and respond to events. This is just one of several methods you can
dramatically reduce coupling. I'm sure glad I didn't burn my book.
Does this imply a 'method call' *syntax* ?

That's language dependent.
Given the existence of
"computed attributes" (ie: support for 'attribute access' *syntax* with
hidden accessors) and the possibility to redefine implementation (from
default attribute r/w access to computed/controlled) without touching
the interface, why advocate the *systematic* use of computed attributes
when it's just duplicating the default behaviour ?

I'm not advocating anything. I'm just stating the use case for
accessors and the wisdom behind them. My qualm with implicit accessors
remains the name issue.
Then why advocate *systematic* use of them ?

(snip)

I never advocated anything. On the contrary, I asked a query?
The words (and the concept they describe) are not. Interpretation of
what is state and what is behaviour is subjective.


It is.


Behaviour is how a given object reacts to a given message. *Nothing* in
this implies the notions of attributes or methods. Attributes and
methods are implementation details of the concepts of state and
behaviour, and - while this is a common implementation of OO concepts -
the choice to use non-callable attributes as representing the state
and callable ones as representing behaviour is totally
implementation-dependant.

I agree. And I already told you I think in terms of state and behavior
and not language dependent semantics.
 
B

Bruno Desthuilliers

mystilleef said:
Are you serious?

Deadly serious. But I'm afraid you're still missing the point.
Well, you design an object that serves as a mediator.
All objects can then only interact with themselves and the mediator
only. Via signals, objects learn to automatically adjust their states
and respond to events.

signal -> message -> method call -> change state.

Spell it how you like, add as many indirection levels you want, it still
boils down to the fact that *something* triggers the state change.
This is just one of several methods you can
dramatically reduce coupling.

It's just one of several methods that dramatically increases complexity,
without changing anything to the fact that in the end, *practically*,
some object ObjA changes its state as a response to a message sent by ObjB.
I'm sure glad I didn't burn my book.

No comment.
That's language dependent.




I'm not advocating anything.

cf below on this.
I'm just stating the use case for
accessors and the wisdom behind them. My qualm with implicit accessors
remains the name issue.

The "name issue" is *your* problem. And AFAICT, it's a "problem" because
you refuse to free your mind from a "what's in the book" mindset.
I never advocated anything.

You advocated
"""
1). Make all attributes of a class private/protected .
2). If a "non-callable" attribute is going to be used outside a class,
think about making it a property and name the property well, because
you never know...
"""
I agree. And I already told you I think in terms of state and behavior
and not language dependent semantics.

Then why do you advise "(making) all attributes of a class
private/protected" and systematically using properties ?
 
B

Bruno Desthuilliers

mystilleef said:
So you see the purpose of accessors then?

*where* did I say *anything* that could *possibly* be taken as me not
seeing the point of computed attributes ?

What I'm saying here is that it's totally useless to duplicate default
behaviour.
I never said they weren't.

Fine.

Now : in a language with support for computed attributes, direct
attribute access is the default r/w accessors.
Make an object's state unreliable. See above example.

That's the word you choose that I find really strange.
is_active is an object's data,

class Obj(object):
# ....
@apply
def is_active():
def fget(self):
return (self.something and self.computeThis()) \
or self.otherCondition()
def fset(self, val):
raise ReadOnlyError()
def fdel(self):
raise UndeletableError()
return **locals()

According to *your* sayings, Obj.is_active is "behaviour"...

The only languages I know that "force" you to use accessors are
Smalltalk and Ruby (and Ruby offers some syntactic sugar for 'default' -
ie r/w - accessors).
It's not because they hate you or aren't aware of the

I'm afraid it has very few to do with "robustness".
Again, the object model of the language is irrelevant.

Allo, Huston ?
The only
relevant model is my application's model, which should work regardless
of the language I use.

What to say...
 
M

mystilleef

Bruno said:
Deadly serious. But I'm afraid you're still missing the point.


signal -> message -> method call -> change state.

Spell it how you like, add as many indirection levels you want, it still
boils down to the fact that *something* triggers the state change.

Riiiiight!


It's just one of several methods that dramatically increases complexity,
without changing anything to the fact that in the end, *practically*,
some object ObjA changes its state as a response to a message sent by ObjB.

Say that to game/simulation developers.
No comment.


cf below on this.


The "name issue" is *your* problem. And AFAICT, it's a "problem" because
you refuse to free your mind from a "what's in the book" mindset.

What book are we talking about?
You advocated
"""
1). Make all attributes of a class private/protected .
2). If a "non-callable" attribute is going to be used outside a class,
think about making it a property and name the property well, because
you never know...
"""

You use accessors when you need to control access to a data attribute.
That's not advocacy, that's common sense.
Then why do you advise "(making) all attributes of a class
private/protected" and systematically using properties ?

Because you don't want third parties illegimately tampering with an
object's internal data and thus crashing your system?
 
M

mystilleef

Bruno said:
*where* did I say *anything* that could *possibly* be taken as me not
seeing the point of computed attributes ?

What I'm saying here is that it's totally useless to duplicate default
behaviour.

And who's doing that?
Fine.

Now : in a language with support for computed attributes, direct
attribute access is the default r/w accessors.

Depends on your definition of accessors. Otherwise 97% of languages
provide direct access to an object's data attributes.
That's the word you choose that I find really strange.

What's strange about it. If an object's data attribute is supposed to
state that it is false when there are no mark objects in the buffer,
and a third party accidently incorrectly changes the attribute to state
it is True for whatever reasons, you essentially corrupt the objects
state and render the whole system "unreliable," or "buggy". What again
is difficult to grasp?
class Obj(object):
# ....
@apply
def is_active():
def fget(self):
return (self.something and self.computeThis()) \
or self.otherCondition()
def fset(self, val):
raise ReadOnlyError()
def fdel(self):
raise UndeletableError()
return **locals()

According to *your* sayings, Obj.is_active is "behaviour"...

Not my saying. OO says so.
The only languages I know that "force" you to use accessors are
Smalltalk and Ruby (and Ruby offers some syntactic sugar for 'default' -
ie r/w - accessors).

Add Eiffel to the list. Java/C++/C#/Ada all recommend it by convention.

I'm afraid it has very few to do with "robustness".

Your opinion.
Allo, Huston ?


What to say...

....
 
S

Steve Holden

mystilleef wrote, making me somewhat tired of his/her repeated inability
to get what's being said [sigh]:This makes it somewhat obvious that you don't appear to fully understand
the concept of coupling as applied to software systems.
Riiiiight!
If you implement an accessor to change a class's instances' states,
surely something has to call that accessor. You seem to be implying that
such calls can only be made from within other methods of the same
object, which (if true, which it isn't) would tend to leave each class
in a vacuum where nothing else can affect its instances.

Of *course* objects are subject to external influences: since you like
the concept of coupling, how else could different components be coupled
at all?
Say that to game/simulation developers.
This is a complete non-sequitur as you don't say why game developers
specifically benefit from the reduced coupling that you allege the
provision of accessor methods introduces.

Tight coupling would be (for example) where you provided the argument to
a method by storing it in a global variable rather than passing it as an
argument. From a coupling point of view it makes no difference whether
you call an accessor method or (in Python) read or write a referenced
object's attributes directly. You still have to know the required API:
whether you call a method (in which case you have to know its name) or
read/write an attribute (in which case you have to know its name ...)
makes no essential difference.

It appears you have seen the term "content coupling" as defined, for
example, in

http://en.wikipedia.org/wiki/Coupling_(computer_science)

and taken that to mean that any knowledge at all of another object's
internals will lead to over-tight coupling and hence low cohesion. The
Python point of view is somewhat different, and says that since both
methods and data items are attributes of instances there is little
difference (except in efficiency) between accessing data via a method
(inefficient) and accessing data directly through the attribute
containing that data (efficient).

It has already been pointed out to you several times that once you have
written your code to access attributes you can introduce properties
without changing the client (accessing) code should further isolation or
additional computation be required.
What book are we talking about?
Well you should know, you're the one who wants to hang on to it. So
please enlighten us, what is this source of knowledge that appears to
contradict sound computer science?

Whereas you appear to feel that there can be no possibility if a crash
because someone calls thing.is_active(True), and yet you repeatedly fail
to demonstrate the difference. Which is why this thread has been so
mind-numbingly long. As is pointed out AGAIN here:
You use accessors when you need to control access to a data attribute.
That's not advocacy, that's common sense.
Perhaps so, but you still refuse to explain why it's better, when all
you need to do is read or write the value of an instance's attribute, to
define accessor methods to do it, introducing unnecessary (in Python)
overhead in the process.Am I the only one here who has lost track of this "'tis/'tisn't" stuff?
Because you don't want third parties illegimately tampering with an
object's internal data and thus crashing your system?
In which case you write correct software and provide it with a thorough
set of tests to allow you to modify it without worrying too much about
breakage. Attribute access is part of an object's API just like method
calls are.

You seem to think that every ill in software design can be legislated
away by strangling design freedom with specific rules. I am afraid that
experience will teach you this is far from the case: go look at the way
that the "bondage" languages that use static typing (like Java and C++)
still fail to impose the required typing discipline on a determinedly
incompetent user.

As has already been said, the Python philosophy is to provide the
features that "consenting adults" (i.e. programmers who know what they
are doing) can use most effectively to produce complex software systems
to reasonable deadlines. Unfortunately not all the knowledge required to
do this is readily available in books; the rest must come from experience.

regards
Steve
 
D

Diez B. Roggisch

Then why do you advise "(making) all attributes of a class
Because you don't want third parties illegimately tampering with an
object's internal data and thus crashing your system?

Ah, you mean like in JAVA where the compiler prevents you from accessing
private variables, but the runtime allows access to these very variables
via reflection?

Or in C++, where the malevolent programmer just removes the private
declarations in his compile run, and accesses the "private" data from your
object as if it was never declared that way?

You better forget thinking about these hilarious mechanisms of access
control as something that enforces security, and start thinking about them
as a convention that states "I told you not to tamper with this, you've
been warned" - which is done in python using a leading underscore. Or two.

Unless setting or getting a property implies code being run beside the
actual state change, there is absolutely no reason to use accessors. But I
fear this horse has been beaten to death in front of you so many times, yet
still you refuse to see it that way - so, go and use accessors if you like.
Nobody cares....


Diez
 
D

Diez B. Roggisch

What I'm saying here is that it's totally useless to duplicate default
And who's doing that?

Somebody who uses setters that only set a property?


Diez
 
E

Ed Jensen

Diez B. Roggisch said:
Ah, you mean like in JAVA

Java is not an acronym. That is: it's "Java", not "JAVA".
where the compiler prevents you from accessing
private variables, but the runtime allows access to these very variables
via reflection?

Java does not allow access to private members via reflection.
 
B

Bruno Desthuilliers

mystilleef said:
You use accessors when you need to control access to a data attribute.

Indeed. And when you don't need too ? (the second 'o' is not a typo)
That's not advocacy, that's common sense.

I'm afraid we don't use the same definition of "common sense". Writing
useless code is not part of my definition of "common sense".

(snip)
Because you don't want third parties illegimately tampering with an
object's internal data and thus crashing your system?

Let's try again...

point 1 : there's *no* language-inforced access restriction in Python.
Just a *convention*.

point 2 : so anyone *can* "illegimately tampering with an object's
internal data" at will.

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

point 4 : since we have computed attributes, turning a "public data
attribute" (to use your idiom) into a "private/protected data attribute
with accessors" *without breaking the interface* is not even a non-brainer.

Now, please, can you explain the difference between :

class Complicated(object):
def __init__(self, data):
self.data = data
def _get_data(self):
return self._data
def _set_data(self, data):
self._data = data

and

class Pragmatic(object):
def __init__(self, data)
self.data = data


and find any *valid* reason to use the first solution instead of the
second ? ('that's what the book says' not being a valid reason).
 
T

Tobias Brox

[Jason]
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.

"Code generation" springs into my mind. IMO, if the code needs to be
generated, the language is not sufficiently advanced.
 
B

Bruno Desthuilliers

mystilleef said:
(snip)



And who's doing that?

That's exactly what you recommended: "make all attributes
private/protected (...) If a data attribute might likely be an API,
think about controlling access to via "properties""

Depends on your definition of accessors.

something that let me access an attribute.
Otherwise 97% of languages
provide direct access to an object's data attributes.

But not 97% of languages provide support for computed attributes.
What's strange about it. If an object's data attribute is supposed to
state that it is false when there are no mark objects in the buffer,
and a third party accidently incorrectly changes the attribute to state
it is True for whatever reasons, you essentially corrupt the objects
state and render the whole system "unreliable," or "buggy". What again
is difficult to grasp?

The choice of the word "contaminated".
Not my saying. OO says so.

Chapter and verse, please ?

now :
class Obj(object):
def __init__(self):
self.is_active = False

Now, 'is_active' is state again ?
Add Eiffel to the list. Java/C++/C#/Ada all recommend it by convention.

Java/C++/C#/Ada all recommend it because they have no support for
computed attributes, which means that you cannot change implementation
without breaking the interface.

Your opinion.

what's the exact difference in "robustness" between:

class DreamItisRobust(object):
def __init__(self):
self._attr = 42
def get_attr(self):
return self._attr
def set_attr(self, attr):
self._attr = attr

and

class DontCare(object):
def __init__(self):
self.attr = 42


???
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top