Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Declarative properties

2 views
Skip to first unread message

Artur Siekielski

unread,
Oct 11, 2007, 7:48:18 AM10/11/07
to
Hi.

I would like to have declarative properties in Python, ie. something
like slots definitions in defclass in Common Lisp. It seems that even
Java will have it, using a library ( https://bean-properties.dev.java.net/
).

I know about 'property' function in Python, but it's normal usage
isn't declarative, because I have to code imperatively getters and
setters:

class Person(object):
def __init__(self, name):
self._name = name
def _get_name(self):
return self._name
def _set_name(self, new_name):
self._name = new_name
name = property(_get_name, _set_name)

I would like to have something like that:

class Person(object):
name = property('_name')

I assume that this causes "generation" of instance field '_name' and
default getters and setters. And if I would like to customize (g|
s)etters, I would write them by hand, or, better, use more declarative
approach (like @NotNull annotations in Java version).

I could probably code a solution to my problem with help of wonderful
introspection functionalities. But I'm looking for a standard and/or
proven way of doing this. Maybe some PEP is being prepared for this?

Regards,
Artur

Marc 'BlackJack' Rintsch

unread,
Oct 11, 2007, 8:27:35 AM10/11/07
to
On Thu, 11 Oct 2007 11:48:18 +0000, Artur Siekielski wrote:

> class Person(object):
> def __init__(self, name):
> self._name = name
> def _get_name(self):
> return self._name
> def _set_name(self, new_name):
> self._name = new_name
> name = property(_get_name, _set_name)

This is more easily spelled:

class Person(object):
def __init__(self, name):

self.name = name

> I would like to have something like that:
>
> class Person(object):
> name = property('_name')
>
> I assume that this causes "generation" of instance field '_name' and
> default getters and setters.

But why? Default getters and setters are unnecessary and if you need
something other than the default you need to write it anyway more
explicitly.

Ciao,
Marc 'BlackJack' Rintsch

Artur Siekielski

unread,
Oct 11, 2007, 9:04:53 AM10/11/07
to
On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
> But why? Default getters and setters are unnecessary and if you need
> something other than the default you need to write it anyway more
> explicitly.

I see some problems with your approach:

1. If I use instance field 'name' which is accessed directly by other
classes,
and later I decide to implement nonstandard getter, I must refactor
'Person' class
and in some places change 'name' to '_name' (assuming this is now the
field's name).
The problem is that I cannot automatically change 'name' to '_name'
everywhere, because
in some places I want public property value (eg. validated and
formatted), and in other
places raw property value.

2. Properties define (a part of) public interface of a class. When
using fields for public
access, you must tell this explicitly in documentation, or use name
convention. And public
fields definition is mixed with private fields, which doesn't happen
when using properties.

3. Using properties as first-class objects gives possibilities to use
declarative approaches
for constructing them.

Marc 'BlackJack' Rintsch

unread,
Oct 11, 2007, 9:46:12 AM10/11/07
to
On Thu, 11 Oct 2007 13:04:53 +0000, Artur Siekielski wrote:

> On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
>> But why? Default getters and setters are unnecessary and if you need
>> something other than the default you need to write it anyway more
>> explicitly.
>
> I see some problems with your approach:
>
> 1. If I use instance field 'name' which is accessed directly by other
> classes,
> and later I decide to implement nonstandard getter, I must refactor
> 'Person' class
> and in some places change 'name' to '_name' (assuming this is now the
> field's name).
> The problem is that I cannot automatically change 'name' to '_name'
> everywhere, because
> in some places I want public property value (eg. validated and
> formatted), and in other
> places raw property value.

So what? Otherwise you carry *always* the baggage of a public property
and a private attribute whether you need this or not. At least for me it
would be unnecessary in most cases.

> 2. Properties define (a part of) public interface of a class. When
> using fields for public
> access, you must tell this explicitly in documentation, or use name
> convention. And public
> fields definition is mixed with private fields, which doesn't happen
> when using properties.

Attributes are public unless you start the name with an underscore which is
by convention a warning to not use that attribute unless you know what you
are doing. With properties all over the place you use that convention
anyway because the "real" value for `name` is bound as `_name`. So you
clutter your API with two attributes for non-method-attributes.

And a property is not automatically part of the public API, just if the
name does not start with an underscore.

> 3. Using properties as first-class objects gives possibilities to use
> declarative approaches for constructing them.

No idea what you mean here. Everything in Python is an object.

Ciao,
Marc 'BlackJack' Rintsch

sjde...@yahoo.com

unread,
Oct 11, 2007, 10:21:31 AM10/11/07
to
Artur Siekielski wrote:
> On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
> > But why? Default getters and setters are unnecessary and if you need
> > something other than the default you need to write it anyway more
> > explicitly.
>
> I see some problems with your approach:
>
> 1. If I use instance field 'name' which is accessed directly by other
> classes,
> and later I decide to implement nonstandard getter, I must refactor
> 'Person' class
> and in some places change 'name' to '_name' (assuming this is now the
> field's name).
> The problem is that I cannot automatically change 'name' to '_name'
> everywhere, because
> in some places I want public property value (eg. validated and
> formatted), and in other
> places raw property value.

In practice, it turns out to be a lot less work to deal with that
occasionally than to always deal with lugging around internal
attributes and external properties when they're really not needed. By
writing everything as properties up front you're just creating more
work for yourself, and it's generally considered bad practice in
Python to have default getters/setters (whether part of a property or
not).

> 2. Properties define (a part of) public interface of a class. When
> using fields for public
> access, you must tell this explicitly in documentation, or use name
> convention.

Property vs. attribute doesn't make any difference here: both of them
are public, and part of the external interface, unless they're named
with a leading underscore.

Making something a property doesn't make it any more or less a part of
the public interface.

> 3. Using properties as first-class objects gives possibilities to use
> declarative approaches
> for constructing them.

This doesn't make any sense. Properties and attributes are both
objects in python.

Artur Siekielski

unread,
Oct 11, 2007, 11:39:29 AM10/11/07
to
On Oct 11, 4:21 pm, "sjdevn...@yahoo.com" <sjdevn...@yahoo.com> wrote:
> In practice, it turns out to be a lot less work to deal with that
> occasionally than to always deal with lugging around internal
> attributes and external properties when they're really not needed. By
> writing everything as properties up front you're just creating more
> work for yourself, and it's generally considered bad practice in
> Python to have default getters/setters (whether part of a property or
> not).

Ok, I appreciate your and Marc's argument. So I see that a pythonic
way is
using public attributes, and it works in real life. Automatic
"generation" of
getters/setters is a nice thing when using Java style of properties,
ie. no
public fields.

> > 2. Properties define (a part of) public interface of a class. When
> > using fields for public
> > access, you must tell this explicitly in documentation, or use name
> > convention.
>
> Property vs. attribute doesn't make any difference here: both of them
> are public, and part of the external interface, unless they're named
> with a leading underscore.

Nice thing about properites is that they are defined in more
declarative way -
in class body. Attributes are "defined" in a piece of code (which can
be long
and can contain loops etc.) by assigning a value to 'self'.

> > 3. Using properties as first-class objects gives possibilities to use
> > declarative approaches
> > for constructing them.
>
> This doesn't make any sense. Properties and attributes are both
> objects in python.

Attribute is an object which has value specific for the time it's get
from object.
It is separated from containing object - relation to it is lost.
Python property is an object that describes how to get/set a specific
attribute of
containing object - any time. It describes relationship between the
two.

By declarative method I mean something like a function that takes a
property object
and returns modified property object:

def not_none(prop):
def new_fset(self, obj):
if obj is not None:
prop.fset(self, obj)
else:
raise 'Cannot set None value'
return property(prop.fget, new_fset, prop.fdel)

And then:

class Person(object):
...
name = not_none( property(_get_name, _set_name) )

Marc 'BlackJack' Rintsch

unread,
Oct 11, 2007, 12:35:36 PM10/11/07
to
On Thu, 11 Oct 2007 15:39:29 +0000, Artur Siekielski wrote:

> On Oct 11, 4:21 pm, "sjdevn...@yahoo.com" <sjdevn...@yahoo.com> wrote:
>> > 2. Properties define (a part of) public interface of a class. When
>> > using fields for public access, you must tell this explicitly in
>> > documentation, or use name convention.
>>
>> Property vs. attribute doesn't make any difference here: both of them
>> are public, and part of the external interface, unless they're named
>> with a leading underscore.
>
> Nice thing about properites is that they are defined in more declarative
> way - in class body. Attributes are "defined" in a piece of code (which
> can be long and can contain loops etc.) by assigning a value to 'self'.

The convention is to bind all attributes in `__init__()`, possibly to
`None` if the real value is not available at that time, and document at
least the public ones in the class' docstring. Tools like `pylint` check
for attributes that are introduced in other methods than `__init__()` and
give a warning.

Ciao,
Marc 'BlackJack' Rintsch

Bruno Desthuilliers

unread,
Oct 11, 2007, 12:51:01 PM10/11/07
to
Artur Siekielski a écrit :

> Hi.
>
> I would like to have declarative properties in Python, ie. something
> like slots definitions in defclass in Common Lisp. It seems that even
> Java will have it, using a library ( https://bean-properties.dev.java.net/
> ).
>
> I know about 'property' function

Actually, it's a class.

> in Python, but it's normal usage
> isn't declarative, because I have to code imperatively getters and
> setters:

Indeed. What would be the use of a property (AKA computed attribute) if
you don't need to do something specific ?

> class Person(object):
> def __init__(self, name):
> self._name = name
> def _get_name(self):
> return self._name
> def _set_name(self, new_name):
> self._name = new_name
> name = property(_get_name, _set_name)

While it's often seen as demonstration code for a property, it's
actually totally useless. If all you want to do is to get and set an
attribute (I mean, without any computation anywhere), then just use an
attribute - you will always be able to turn it into a property if and
whene the need arises.

> I would like to have something like that:
>
> class Person(object):
> name = property('_name')
>
> I assume that this causes "generation" of instance field '_name' and
> default getters and setters.

So far, it's a waste of time. That's exactly what you'd get with a plain
attribute, with far less complexity and overhead.

> And if I would like to customize (g|
> s)etters, I would write them by hand,

Which bring us back to how properties actually work !-)

> or, better, use more declarative
> approach (like @NotNull annotations in Java version).

> I could probably code a solution to my problem with help of wonderful
> introspection functionalities. But I'm looking for a standard and/or
> proven way of doing this. Maybe some PEP is being prepared for this?

I guess you want to have a look at the descriptor protocol - it's what
makes properties work, and it allow you to write your own custom 'smart
attributes'. If you want automatic validation/conversion, you could
write custom descriptors working with the FormEncode package (I started
such a thing for Elixir, but had no time to finish it so far). It would
then looks like:

class Person(object):
name = StringField(empty=False)

// etc

HTH

Bruno Desthuilliers

unread,
Oct 11, 2007, 12:58:44 PM10/11/07
to
Artur Siekielski a écrit :

> On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
>> But why? Default getters and setters are unnecessary and if you need
>> something other than the default you need to write it anyway more
>> explicitly.
>
> I see some problems with your approach:
>
> 1. If I use instance field 'name' which is accessed directly by other
> classes,
> and later I decide to implement nonstandard getter, I must refactor
> 'Person' class
> and in some places change 'name' to '_name' (assuming this is now the
> field's name).

Why so ?

class Toto(object):
def __iinit__(self, name):
self.name = name
@apply
def name():
def fget(self):
print "getting %s.name" % self
return self._name
def fset(self, val):
print "setting %s.name to %s" % (self, val)
self._name = name
def say_hello(self):
print "Hello, my name is %s" % self.name

t = Toto('bruno')
t.say_hello()

> The problem is that I cannot automatically change 'name' to '_name'
> everywhere, because
> in some places I want public property value (eg. validated and
> formatted), and in other
> places raw property value.

But then, you do know where you want the raw value, don't you ? And this
would be for special cases that didn't exist before this refactoring,
anyway ?

> 2. Properties define (a part of) public interface of a class.

So do attributes.

> When
> using fields for public
> access, you must tell this explicitly in documentation, or use name
> convention. And public
> fields definition is mixed with private fields, which doesn't happen
> when using properties.

I just don't understand what you're saying here. As long as you did not
prefix a name with an underscore, it's part of the API. And anyway,
nothing (except common sens) will prevent anyone to mess with
implementation attributes.

> 3. Using properties as first-class objects

Which they are already - I don't know of anything that isn't a
"first-class" object in Python.

Bruno Desthuilliers

unread,
Oct 11, 2007, 1:08:37 PM10/11/07
to
Artur Siekielski a écrit :

> On Oct 11, 4:21 pm, "sjdevn...@yahoo.com" <sjdevn...@yahoo.com> wrote:
>> In practice, it turns out to be a lot less work to deal with that
>> occasionally than to always deal with lugging around internal
>> attributes and external properties when they're really not needed. By
>> writing everything as properties up front you're just creating more
>> work for yourself, and it's generally considered bad practice in
>> Python to have default getters/setters (whether part of a property or
>> not).
>
> Ok, I appreciate your and Marc's argument. So I see that a pythonic
> way is
> using public attributes, and it works in real life.

Indeed !-)

> Automatic
> "generation" of
> getters/setters is a nice thing when using Java style of properties,
> ie. no
> public fields.

Java doesn't have computed attributes, so you have no other choice if
you want to keep your design flexible. For languages that have computed
attributes, this is not a problem to use plain attributes until you
*really* need to do otherwise.

>>> 2. Properties define (a part of) public interface of a class. When
>>> using fields for public
>>> access, you must tell this explicitly in documentation, or use name
>>> convention.
>> Property vs. attribute doesn't make any difference here: both of them
>> are public, and part of the external interface, unless they're named
>> with a leading underscore.
>
> Nice thing about properites is that they are defined in more
> declarative way -
> in class body. Attributes are "defined" in a piece of code (which can
> be long
> and can contain loops etc.) by assigning a value to 'self'.

Usually, all there is to know is readable in the initializer. And I've
rarely seen (good) code that defines public attribute elsewehere (i've
seen such a thing on a couple occasion, and that's bad coding IMHO).

Anyway, since attributes (including methods, class etc...) can be
added/replaced/deleted by anyone having access to the object at any
point of the program, using properties won't help that much here IMHO.
Not that I don't see your point - I also have a taste for declarative
APIs and readability - but this is enough to justify the use of
properties IMHO.

Dan Stromberg

unread,
Oct 11, 2007, 12:58:48 PM10/11/07
to pytho...@python.org
On Thu, 11 Oct 2007 13:46:12 +0000, Marc 'BlackJack' Rintsch wrote:

> On Thu, 11 Oct 2007 13:04:53 +0000, Artur Siekielski wrote:
>
>> On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
>>> But why? Default getters and setters are unnecessary and if you need
>>> something other than the default you need to write it anyway more
>>> explicitly.
>>
>> I see some problems with your approach:
>>
>> 1. If I use instance field 'name' which is accessed directly by other
>> classes,
>> and later I decide to implement nonstandard getter, I must refactor
>> 'Person' class
>> and in some places change 'name' to '_name' (assuming this is now the
>> field's name).
>> The problem is that I cannot automatically change 'name' to '_name'
>> everywhere, because
>> in some places I want public property value (eg. validated and
>> formatted), and in other
>> places raw property value.
>
> So what? Otherwise you carry *always* the baggage of a public property
> and a private attribute whether you need this or not. At least for me it
> would be unnecessary in most cases.

That "baggage" of carrying around "unneeded" methods is something the
computer carries for you - IE, no big deal in 99.99% of all cases.

The "baggage" of possibly fixing (AKA "generalizing") how your attributes
are accessed is something you lug around while your deadline looms.

Here's some code that defines such methods for you:

#!/usr/bin/env python

def gimme_set_get(foo, attribute):
lst = [ \
'def set_%s(self, value):' % attribute, \
' self._%s = value' % attribute, \
'def get_%s(self):' % attribute, \
' return self._%s' % attribute, \
'foo.set_%s = set_%s' % (attribute, attribute), \
'foo.get_%s = get_%s' % (attribute, attribute) \
]
s = '\n'.join(lst)
code = compile(s, '<string>', 'exec')
eval(code)

class foo:
def __init__(self, value):
self.public_value = value
gimme_set_get(foo, 'via_accessor_method_only')

f = foo(1)
f.set_via_accessor_method_only(1/9.0)
print f.get_via_accessor_method_only()

print dir(f)


Marc 'BlackJack' Rintsch

unread,
Oct 11, 2007, 2:42:16 PM10/11/07
to
On Thu, 11 Oct 2007 09:58:48 -0700, Dan Stromberg wrote:

> On Thu, 11 Oct 2007 13:46:12 +0000, Marc 'BlackJack' Rintsch wrote:
>
>> On Thu, 11 Oct 2007 13:04:53 +0000, Artur Siekielski wrote:
>>
>>> 1. If I use instance field 'name' which is accessed directly by other
>>> classes,
>>> and later I decide to implement nonstandard getter, I must refactor
>>> 'Person' class
>>> and in some places change 'name' to '_name' (assuming this is now the
>>> field's name).
>>> The problem is that I cannot automatically change 'name' to '_name'
>>> everywhere, because
>>> in some places I want public property value (eg. validated and
>>> formatted), and in other
>>> places raw property value.
>>
>> So what? Otherwise you carry *always* the baggage of a public property
>> and a private attribute whether you need this or not. At least for me it
>> would be unnecessary in most cases.
>
> That "baggage" of carrying around "unneeded" methods is something the
> computer carries for you - IE, no big deal in 99.99% of all cases.

It shows twice as much attributes if I inspect the objects and I don't know
which are merely useless default getters and setters. And it is more and
more complex code. Code can be cut down a bit by some metaclass magic but
this brings in another complexity.

> The "baggage" of possibly fixing (AKA "generalizing") how your attributes
> are accessed is something you lug around while your deadline looms.

Sorry I don't get it. If I want to customize the access to a "normal"
attribute I simply turn it into a property.

> Here's some code that defines such methods for you:
>
> #!/usr/bin/env python
>
> def gimme_set_get(foo, attribute):
> lst = [ \
> 'def set_%s(self, value):' % attribute, \
> ' self._%s = value' % attribute, \
> 'def get_%s(self):' % attribute, \
> ' return self._%s' % attribute, \
> 'foo.set_%s = set_%s' % (attribute, attribute), \
> 'foo.get_%s = get_%s' % (attribute, attribute) \
> ]
> s = '\n'.join(lst)
> code = compile(s, '<string>', 'exec')
> eval(code)
>
> class foo:
> def __init__(self, value):
> self.public_value = value
> gimme_set_get(foo, 'via_accessor_method_only')
>
> f = foo(1)
> f.set_via_accessor_method_only(1/9.0)
> print f.get_via_accessor_method_only()
>
> print dir(f)

And the benefit of this evil ``eval`` dance is exactly what!?

Ciao,
Marc 'BlackJack' Rintsch

Paul Hankin

unread,
Oct 11, 2007, 2:53:03 PM10/11/07
to
On Oct 11, 12:48 pm, Artur Siekielski <artur.siekiel...@gmail.com>
wrote:

> Hi.
>
> I would like to have declarative properties in Python, ie. something
> like slots definitions in defclass in Common Lisp. It seems that even
> Java will have it, using a library (https://bean-properties.dev.java.net/

> ).
>
> I know about 'property' function in Python, but it's normal usage
> isn't declarative, because I have to code imperatively getters and
> setters:
>
> class Person(object):
> def __init__(self, name):
> self._name = name
> def _get_name(self):
> return self._name
> def _set_name(self, new_name):
> self._name = new_name
> name = property(_get_name, _set_name)
>
> I would like to have something like that:
>
> class Person(object):
> name = property('_name')

Here's something that does what I think you want. I think your use
case is quite unusual in that you expect the public accessors to
change (keeping private use the same), and that you know you're going
to have a costly rewrite of your class when that happens.

Attributes that are declared with 'magic_attribute' access the private
attribute '_<name>', unless there's a '_get_<name>' or '_set_<name>'
method in which case those are called instead.

def magic_attribute(_name):
def set(self, value):
try:
getattr(self, '_set' + _name)(value)
except AttributeError:
setattr(self, _name, value)
def get(self):
try:
return getattr(self, '_get' + _name)()
except AttributeError:
return getattr(self, _name)
return property(get, set)

# An example use...
class C(object):
x = magic_attribute('_x')
y = magic_attribute('_y')

# Override the default set method for x
def _set_x(self, value):
self._x = value + ' world'

# Override the default get method for y
def _get_y(self):
return self._y.upper()

# Test it works...
c = C()
c.x = c.y = 'hello'
print c.x
print c.y

# hello world
# HELLO

--
Paul Hankin

Paul Hankin

unread,
Oct 11, 2007, 3:02:25 PM10/11/07
to
On Oct 11, 7:42 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
> Sorry I don't get it. If I want to customize the access to a "normal"
> attribute I simply turn it into a property.

I *think* I understand Artur's problem: he wants to be able to add
(for example) clean-up and validation code to public accesses of these
attributes, but he doesn't want this code run internally to the class.
Or another way of saying the same thing: he wants two views of a
variable; one internal to the class, another to the public.

If I understand correctly, his plan is to use 'X._name' internally to
code in his class, but the public uses 'X.name'. Initially, one is an
alias for the other, but later he writes getters and setters to
customise access through the public version.

[I could be totally wrong of course]
--
Paul Hankin

George Sakkis

unread,
Oct 11, 2007, 7:04:27 PM10/11/07
to
On Oct 11, 7:48 am, Artur Siekielski <artur.siekiel...@gmail.com>
wrote:

> I know about 'property' function in Python, but it's normal usage
> isn't declarative, because I have to code imperatively getters and
> setters:
>
> class Person(object):
> def __init__(self, name):
> self._name = name
> def _get_name(self):
> return self._name
> def _set_name(self, new_name):
> self._name = new_name
> name = property(_get_name, _set_name)
>
> I would like to have something like that:
>
> class Person(object):
> name = property('_name')

By now you must have been convinced that default getters/setters is
not a very useful idea in Python but this does not mean you can't do
it; it's actually straightforward:

def make_property(attr):
return property(lambda self: getattr(self,attr),
lambda self, value: setattr(self, attr, value))

class Person(object):
name = make_property('_name')


def __init__(self, name):
self.name = name

You could take it even further by removing the need to repeat the
attribute's name twice. Currently this can done only through
metaclasses but in the future a class decorator would be even better:

def PropertyMaker(*names, **kwds):
format = kwds.get('format', '_%s')
def meta(cls,bases,attrdict):
for name in names:
attrdict[name] = make_property(format % name)
return type(cls,bases,attrdict)
return meta

class Person(object):
__metaclass__ = PropertyMaker('name', format='__%s__')

def __init__(self, name):
self.name = name

print self.__name__


George

George Sakkis

unread,
Oct 11, 2007, 9:01:41 PM10/11/07
to
On Oct 11, 7:04 pm, George Sakkis <george.sak...@gmail.com> wrote:

> You could take it even further by removing the need to repeat the
> attribute's name twice. Currently this can done only through
> metaclasses but in the future a class decorator would be even
> better:

Replying to myself here, but actually metaclasses is not the only way;
another solution involves a descriptor class:


class Property(object):

# cache the mapping of types to 'private' attribute names
_type2attrname = {}

def __init__(self, format='_%s'):
self._format = format

def __get__(self, obj, type=None):
try: name = self._type2attrname[type(obj)]
except KeyError:
self._type2attrname[type(obj)] = name =
self._get_propname(obj)
return getattr(obj, name)

def __set__(self, obj, value):
try: name = self._type2attrname[type(obj)]
except KeyError:
self._type2attrname[type(obj)] = name =
self._get_propname(obj)
setattr(obj, name, value)

def _get_propname(self, obj):
for cls in type(obj).mro():
for name,value in cls.__dict__.iteritems():
if value is self:
return self._format % name
assert False # unreachable


#---- example ------------------------------------

class Person(object):
name = Property()

def __init__(self, name):
self.name = name

p = Person('John')
q = Person('Mike')
print p.name, q.name
print p.__dict__


George

Artur Siekielski

unread,
Oct 12, 2007, 3:13:15 AM10/12/07
to
George Sakkis wrote:
> By now you must have been convinced that default getters/setters is
> not a very useful idea in Python but this does not mean you can't do
> it;

It's a perfect summary of my thoughts after reading this thread. I
will use public attributes (with access customizable with properties)
and remember that in Python I can do everything :).
Thanks everybody.

Bruno Desthuilliers

unread,
Oct 12, 2007, 3:42:28 AM10/12/07
to
Dan Stromberg a écrit :

> On Thu, 11 Oct 2007 13:46:12 +0000, Marc 'BlackJack' Rintsch wrote:
>
>> On Thu, 11 Oct 2007 13:04:53 +0000, Artur Siekielski wrote:
>>
>>> On Oct 11, 2:27 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
>>>> But why? Default getters and setters are unnecessary and if you need
>>>> something other than the default you need to write it anyway more
>>>> explicitly.
>>> I see some problems with your approach:
>>>
>>> 1. If I use instance field 'name' which is accessed directly by other
>>> classes,
>>> and later I decide to implement nonstandard getter, I must refactor
>>> 'Person' class
>>> and in some places change 'name' to '_name' (assuming this is now the
>>> field's name).
>>> The problem is that I cannot automatically change 'name' to '_name'
>>> everywhere, because
>>> in some places I want public property value (eg. validated and
>>> formatted), and in other
>>> places raw property value.
>> So what? Otherwise you carry *always* the baggage of a public property
>> and a private attribute whether you need this or not. At least for me it
>> would be unnecessary in most cases.
>
> That "baggage" of carrying around "unneeded" methods is something the
> computer carries for you - IE, no big deal in 99.99% of all cases.

1/ Accessing the value of a property is not free. Accessing a plain
attribute is much cheaper.

2/ cluttering the class's namespace with useless names and the source
code with useless code is definitively not a good thing.

> The "baggage" of possibly fixing (AKA "generalizing") how your attributes
> are accessed is something you lug around while your deadline looms.
>
> Here's some code that defines such methods for you:
>
> #!/usr/bin/env python
>
> def gimme_set_get(foo, attribute):
> lst = [ \
> 'def set_%s(self, value):' % attribute, \
> ' self._%s = value' % attribute, \
> 'def get_%s(self):' % attribute, \
> ' return self._%s' % attribute, \
> 'foo.set_%s = set_%s' % (attribute, attribute), \
> 'foo.get_%s = get_%s' % (attribute, attribute) \
> ]
> s = '\n'.join(lst)
> code = compile(s, '<string>', 'exec')
> eval(code)

Yuck. This is not only a waste of time, but also badly coded. have mercy
and at least learn how to properly use lexical scoping and closures.

> class foo:
> def __init__(self, value):
> self.public_value = value
> gimme_set_get(foo, 'via_accessor_method_only')
>
> f = foo(1)
> f.set_via_accessor_method_only(1/9.0)
> print f.get_via_accessor_method_only()
>
> print dir(f)
>

Correction: this is not only a waste of time and badly coded, this is
also misleading and braindead.

Bruno Desthuilliers

unread,
Oct 12, 2007, 3:44:45 AM10/12/07
to
Artur Siekielski a écrit :

Well... Almost !-)

And +1 QOTW, BTW.


Stargaming

unread,
Oct 12, 2007, 9:59:39 AM10/12/07
to
On Thu, 11 Oct 2007 18:58:44 +0200, Bruno Desthuilliers wrote:
[snip]

Your implementation seems particularly broken. You do not return anything
from `name()`, hereby removing name as an attribute (or: replacing it
with its return value -- None). You should return ``property(**locals())
`` (or ``property(fget=fget, fset=fset, ...)``, whatever you like).

I'm going to point out a few other mistakes first:

> class Toto(object):
> def __iinit__(self, name):

Typo here: __init__

> self.name = name
> @apply
> def name():
> def fget(self):
> print "getting %s.name" % self
> return self._name
> def fset(self, val):
> print "setting %s.name to %s" % (self, val)
> self._name = name

It should be `val`, not `name`, huh? And, as mentioned above, the return
value is missing.

> def say_hello(self):
> print "Hello, my name is %s" % self.name

A fixed implementation could be something along these lines::

>>> class Toto(object):
... def __init__(self, name):
... self.name = name
... @apply
... def name():
... def fget(self):
... print "getting %s.name" % self
... return self._name
... def fset(self, val):
... print "setting %s.name to %s" % (self, val)
... self._name = val
... return property(**locals())
... def say_hello(self):
... print "Hello, my name is %s" % self.name
...


>>> t = Toto("bruno")

setting <__main__.Toto object at 0xb792f66c>.name to bruno
>>> t.say_hello()
getting <__main__.Toto object at 0xb792f66c>.name
Hello, my name is bruno
>>> t.name
getting <__main__.Toto object at 0xb792f66c>.name
'bruno'
>>> t.name = "jon"
setting <__main__.Toto object at 0xb792f66c>.name to jon
>>> t.say_hello()
getting <__main__.Toto object at 0xb792f66c>.name
Hello, my name is jon

Cheers,
Stargaming

Dan Stromberg

unread,
Oct 12, 2007, 2:55:43 PM10/12/07
to pytho...@python.org
On Fri, 12 Oct 2007 09:42:28 +0200, Bruno Desthuilliers wrote:

>>> So what? Otherwise you carry *always* the baggage of a public
>>> property and a private attribute whether you need this or not. At
>>> least for me it would be unnecessary in most cases.
>>
>> That "baggage" of carrying around "unneeded" methods is something the
>> computer carries for you - IE, no big deal in 99.99% of all cases.
>
> 1/ Accessing the value of a property is not free. Accessing a plain
> attribute is much cheaper.

Python's current performance characteristics have no bearing on what is
good software engineering practice in general, and little bearing on what
is good software engineering practice in python. Even from a
strictly "what's good for python" perspective, if we limit our view of
"good SE practice" to what python can express well right now (and IMO,
python can express this fine, but you seem to be arguing it cannot),
that needlessly limits python's evolution.

I'm not omniscient, and neither is anyone else; when one initially codes a
class, one doesn't know to what purposes it will need to be bent in the
future; using accessor methods instead of exposed attributes is
significantly more flexible for the future of your class. In fact, I may
even go so far as to say that public attributes would be good to leave out
of future languages that don't have a lot of backward compatibility
baggage.

It may not be traditional to use accessor methods in python. It may even
be a more expensive operation. But neither of these make accessor methods
a bad idea in the abstract.

> 2/ cluttering the class's namespace with useless names and the source
> code with useless code is definitively not a good thing.

Adding two clear and flexible methods and eliminating one clear and
inflexible attribute is not namespace clutter. It's paydirt.

The performance expense in the vast majority of cases is tiny compared to
the human expense of going back and fixing a design bug if anything
significant has been hinging on your exposed implementation detail.

Unless, that is, you don't think your code is important enough to be
stretched to another, previously unforeseen purpose someday. If you're
coding for a hobby, and enjoy coding for the sake of coding irrespective
of how long it takes, rather than as a means to a valuable end, maybe
needlessly exposing attributes is a Really Good Idea.

My implementation may or may not be lacking (feel free to improve it - in
fact, please do!), but that's irrelevant to the heart of the matter, which
is "what you didn't think to plan for now most definitely can hurt you
later".

If you have a program that needs to perform well, you're much better off
coding your classes the best way you know how from a Software Engineering
perspective, and using pysco or shedskin or pypy or similar to
improve performance. If that's not enough, then you're better off
profiling the program, and only after that should you recode the critical
portions into something like pyrex or a C extension module, or -maybe-
some python "tricks". I'd argue that trick-free C or C++ is normally
better than python with tricks from a performance vantage -and- from an SE
viewpoint.

Little hackish tricks for performance's sake scattered throughout a
program are very wasteful of something more precious than CPU time.


George Sakkis

unread,
Oct 12, 2007, 3:59:49 PM10/12/07
to
On Oct 12, 2:55 pm, Dan Stromberg <dstrombergli...@gmail.com> wrote:

> If you have a program that needs to perform well, you're much better off
> coding your classes the best way you know how from a Software Engineering
> perspective, and using pysco or shedskin or pypy or similar to
> improve performance.

"best way you know how from a Software Engineering" != "best way to do
it in less flexible languages that will go unnamed, such as Java"

You seem to conflate these two.

George

Dan Stromberg

unread,
Oct 12, 2007, 4:15:40 PM10/12/07
to pytho...@python.org
On Thu, 11 Oct 2007 18:42:16 +0000, Marc 'BlackJack' Rintsch wrote:


>> The "baggage" of possibly fixing (AKA "generalizing") how your attributes
>> are accessed is something you lug around while your deadline looms.
>
> Sorry I don't get it. If I want to customize the access to a "normal"
> attribute I simply turn it into a property.

You're right, properties are an intersting language feature. I wasn't
aware of them until today.

I'm not sure I believe they are better than disallowing public attributes
and requiring setters and getters, but they do appear to address the same
issue: the needless change in API when your internal representation
needs to change.

Apologies.


Chris Mellon

unread,
Oct 12, 2007, 4:21:48 PM10/12/07
to pytho...@python.org
On 10/12/07, Dan Stromberg <dstromb...@gmail.com> wrote:

> On Fri, 12 Oct 2007 09:42:28 +0200, Bruno Desthuilliers wrote:
>
> >>> So what? Otherwise you carry *always* the baggage of a public
> >>> property and a private attribute whether you need this or not. At
> >>> least for me it would be unnecessary in most cases.
> >>
> >> That "baggage" of carrying around "unneeded" methods is something the
> >> computer carries for you - IE, no big deal in 99.99% of all cases.
> >
> > 1/ Accessing the value of a property is not free. Accessing a plain
> > attribute is much cheaper.
>
> Python's current performance characteristics have no bearing on what is
> good software engineering practice in general, and little bearing on what
> is good software engineering practice in python. Even from a
> strictly "what's good for python" perspective, if we limit our view of
> "good SE practice" to what python can express well right now (and IMO,
> python can express this fine, but you seem to be arguing it cannot),
> that needlessly limits python's evolution.
>
> I'm not omniscient, and neither is anyone else; when one initially codes a
> class, one doesn't know to what purposes it will need to be bent in the
> future; using accessor methods instead of exposed attributes is
> significantly more flexible for the future of your class.

This is simply not true in Python, and anyone who thinks it is hasn't
the slightest understanding of the consequences of dynamic vs static
lookup. The best practice (in C++, which Java inherited) of using
accessors is because changing a public attribute to a property broke
your interface, and all the clients of your code needed to be altered.
Later languages, like C#, introduced syntax support for properties,
which improved the situation such that clients didn't need to be
re-written, but only recompiled.

Python, however, uses truly dynamic attribute lookup and there is
*zero* cost to clients in a change from a public attribute to a
property.

Writing accessors in a language that doesn't have the pressures that
introduced them is cargo cult programming, not Software Engineering.

>In fact, I may
> even go so far as to say that public attributes would be good to leave out
> of future languages that don't have a lot of backward compatibility
> baggage.
>

>From a reasonable point of view, Python doesn't have public
attributes, it just has things that syntactically look like them.
Discuss!

> It may not be traditional to use accessor methods in python. It may even
> be a more expensive operation. But neither of these make accessor methods
> a bad idea in the abstract.
>

Of course not, that's why Python supports properties. What's being
called the anti-pattern here is the creation-by-default of trivial
accessors.

> > 2/ cluttering the class's namespace with useless names and the source
> > code with useless code is definitively not a good thing.
>

> Adding two clear and flexible methods and eliminating one clear and
> inflexible attribute is not namespace clutter. It's paydirt.
>

No, you kept the attribute and also added (at least) 2 methods.

> The performance expense in the vast majority of cases is tiny compared to
> the human expense of going back and fixing a design bug if anything
> significant has been hinging on your exposed implementation detail.
>

You still don't know what language you're writing in, do you? There is
zero additional cost associated with changing a public attribute to a
property.

> Unless, that is, you don't think your code is important enough to be
> stretched to another, previously unforeseen purpose someday. If you're
> coding for a hobby, and enjoy coding for the sake of coding irrespective
> of how long it takes, rather than as a means to a valuable end, maybe
> needlessly exposing attributes is a Really Good Idea.
>

Ah, the old "my code is way more important than yours, so what I do is
right" approach. You hang out in the Java world a lot, don't you?

> My implementation may or may not be lacking (feel free to improve it - in
> fact, please do!), but that's irrelevant to the heart of the matter, which
> is "what you didn't think to plan for now most definitely can hurt you
> later".
>

Your implementation is, quite possibly, the worst possible
implementation of automatic properties in Python, both in terms of
readability and code size (and thus maintenance), as well as
performance and flexibility. The fact that you consider it, even for a
moment, to be better than writing accessors when and if you need them
(and not writing them otherwise) belies a dreadful lack of self
awareness.

> If you have a program that needs to perform well, you're much better off
> coding your classes the best way you know how from a Software Engineering
> perspective, and using pysco or shedskin or pypy or similar to

> improve performance. If that's not enough, then you're better off
> profiling the program, and only after that should you recode the critical
> portions into something like pyrex or a C extension module, or -maybe-
> some python "tricks". I'd argue that trick-free C or C++ is normally
> better than python with tricks from a performance vantage -and- from an SE
> viewpoint.
>

You're not going to teach anyone on this list anything about
optimizing, I suspect.

> Little hackish tricks for performance's sake scattered throughout a
> program are very wasteful of something more precious than CPU time.
>

It's truly bizarre to hear someone refer to *not* writing code as a
"hackish trick". Especially when the alternative they prevent depends
on eval!

>

Diez B. Roggisch

unread,
Oct 13, 2007, 2:15:29 PM10/13/07
to
Dan Stromberg schrieb:

This belief is most probably nurtured by Java. Or am I wrong here?
Matter of factly, the whole getter/setter-mamboo-jamboo is nothing but a
pathetic attempt to overcome the lack of attribute-access-hooks, as they
are e.g. provided by python or C#.

By forcing this convention upon the programmer (and supporting it using
e.g. BeanInfo and other introspection-based mechanisms), Java allows for
the implementation of delegation, lazyness and so forth without all that
forcing major interface changes upon the user. Talking of interfaces -
they do lack properties as well... so you _can't_ possibly provide an
interface with attributes.


But I really don't think one can argue over a more aesthetic &
expressive syntax like

a.foo = b.bar * c.baz

compared to

a.setFoo(b.getBar() * c.getBaz())


Diez

Bruno Desthuilliers

unread,
Oct 13, 2007, 4:21:31 PM10/13/07
to
Stargaming a écrit :

> On Thu, 11 Oct 2007 18:58:44 +0200, Bruno Desthuilliers wrote:
> [snip]
>
> Your implementation seems particularly broken. You do not return anything
> from `name()`,

Oops, my bad ! Indeed, I forgot the 'return property(**locals())' at the
end. And a couple other things too:

> I'm going to point out a few other mistakes first:
>

(snip other corrections)

I'll call you when I'll have code to fix - you're doing a good job !-)

Bruno Desthuilliers

unread,
Oct 8, 2007, 7:25:35 AM10/8/07
to
Dan Stromberg a écrit :

> On Fri, 12 Oct 2007 09:42:28 +0200, Bruno Desthuilliers wrote:
>
>
>>>>So what? Otherwise you carry *always* the baggage of a public
>>>>property and a private attribute whether you need this or not. At
>>>>least for me it would be unnecessary in most cases.
>>>
>>>That "baggage" of carrying around "unneeded" methods is something the
>>>computer carries for you - IE, no big deal in 99.99% of all cases.
>>
>>1/ Accessing the value of a property is not free. Accessing a plain
>>attribute is much cheaper.
>
>
> Python's current performance characteristics have no bearing on what is
> good software engineering practice in general,

Neither useless complexity nor tryig to apply inappropriate idioms are
good practices.

(snip)

> I'm not omniscient, and neither is anyone else; when one initially codes a
> class, one doesn't know to what purposes it will need to be bent in the
> future; using accessor methods instead of exposed attributes is
> significantly more flexible for the future of your class.

Please remember that Python has support for computed attributes (you do
know what's a computed attribute, don't you ?), so you can turn a plain
attribute into a computed one at any time without breakink the API. IOW,
you don't need getters/setter a priori.

Bruno Desthuilliers

unread,
Oct 8, 2007, 8:04:49 AM10/8/07
to
Dan Stromberg a écrit :
(snip)

> My implementation may or may not be lacking (feel free to improve it - in
> fact, please do!),

Since you ask for it:

def makeprop(name):
_name = '_' + name
def fget(self):
return getattr(self, _name, None)
def fset(self, val):
setattr(self, _name, val)
return property(fget, fset)

class AutoPropType(type):
def __init__(cls, clsname, bases, attribs):
for name in cls._autoprops:
if name not in attribs:
setattr(cls, name, makeprop(name))

class Demo(object):
__metaclass__ = AutoPropType
_autoprops = ('foo', 'bar', 'baaz')

def __init__(self, foo, bar=42, baaz='ni'):
self.foo = foo
self.bar = bar
self.baaz = baaz

d = Demo('yadda yadda')


> but that's irrelevant to the heart of the matter, which
> is "what you didn't think to plan for now most definitely can hurt you
> later".

Ahem... Please let me know, Mr Professor, what difference it would make,
from client code's POV, if we simply wrote this instead:

class Demo(object):
def __init__(self, foo, bar=42, baaz='ni'):
self.foo = foo
self.bar = bar
self.baaz = baaz


(snip more blah)

> Little hackish tricks for performance's sake scattered throughout a
> program are very wasteful of something more precious than CPU time.

Indeed. The point you're missing is that, in a language that supports
computed attributes, using plain attributes when that's all you need is
*not* a 'litlle hackish trick'. It's just common sense - and actually
saves on *both* programmer's and CPU time.

0 new messages