Accessors in Python (getters and setters)

Bruno Desthuilliers onurb at xiludom.gro
Thu Jul 13 11:53:10 EDT 2006


mystilleef wrote:
(snip)
> 
> 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 .

Please re-read my answer to your previous mention of this and my other
remarks in this thread (and below in this thread) about the profound
differences between Python and Java wrt/ object model and attribute
access semantics.

> 2). If a "non-callable" attribute is going to be used outside a class,
> think about making it a property

Unless you don't need to.

> and name the property well, 

Indeed !-)

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

And also API/implementation. These are to orthogonal problems - even in
Java FWIW !-)

> However, my categorization is state(data) and
> behavior(methods). 

If properties are an equivalent of getters/setters, are properties state
or behaviour ? According to your views, they are behaviour, if I
understood you. In that case, what's the difference between 'directely'
(which in fact implies going thru __getattribute__) accessing a public
"data" attribute and accessing an implementation attribute by the mean
of a descriptor (property or custom) ?

* before:

# mylib.py
class Knight(object):
   def __init__(self, name):
     self.name = name

   def sayHello(self):
     print "hello, I'm %s" % self.name

# mymain.py
from mylib import Knight
k = Knight("Robin")
print k.name
k.sayHello()
k.name = "Lancelot"
k.sayHello()

* after
# mylib.py
class Knight(object):
   def __init__(self, name):
     self.name = name

   @apply
   def name():
     def fget(self):
        return self._xxx.capitalize()

     def fset(self, name):
        self._xxx = name

   def sayHello(self):
     print "hello, I'm %s" % self.name

# mymain.py
from mylib import Knight
k = Knight("Robin")
print k.name
k.sayHello()
k.name = "Lancelot"
k.sayHello()



> Neither ways of thinking about it is wrong.

>From the client code (including other methods of the same class) POV, is
Knight.name behaviour or state ? Please, don't see it as a flame or a
pissing context or whatever, and try to seriously answer this question.

Thinking in terms of state and behaviour is certainly not wrong in
itself, but what is state and what is behaviour ? If I pass a callable
as an argument to another callable, is the first one data or behaviour ?
If I return a callable from a another callable, is the first callable
data or behaviour ?  In a Partial application object [1], is the stored
callable data or behaviour ? Is the class of an object data or
behaviour? Is it's metaclass data or behaviour ?

[1] http://www.python.org/dev/peps/pep-0309/


> It just
> reflects the way we design classes. When I'm coding I certainly don't
> care about how Python accesses tmp. 

Neither do I. But I have in mind how I can change the way it is accessed.

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

cf Simon's answer and mines. But your original problem is not related to
tmp being callable or not, it's related to how you use to think about
them, hence name them.

> Most other OO
> languages provide accessors in addition to keywords for that kind of
> stuff.

Most OO languages *don't* provide you accessors - they indeed *forces
you* to write them even for the most trivial cases. What Python (or any
other language supporting "computed attributes" syntax) gives you is a
way to avoid writing tedious, boilerplate code. Not more, not less.

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

Mark as implementation what is obviously implementation (be it callable
or not), mark as API what is obviously API (be it callable or not). In
both cases, there will be simple ways to either expose an implementation
name or make a non-callable attribute a property. And *always* try to be
careful about naming, at least (but not restricted to) wrt/ your API.



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



More information about the Python-list mailing list