[Python-Dev] __set_foo__ et al. (PEP-able)

M.-A. Lemburg mal@lemburg.com
Thu, 20 Jul 2000 22:49:30 +0200

Paul Prescod wrote:
> "M.-A. Lemburg" wrote:
> >
> > ..
> >
> > I don't get the point: how is this better than defining
> > explicit access methods ?
> >
> > get_foo(self)
> > set_foo(self, value)
> > del_foo(self)
> It's more verbose for the client programmer and it forces them to "know"
> that there is magical processing going on under the covers.

Magical processing is usually not a very good design, IMHO
(no, I don't like the Unicode auto-conversions ;-).

> I'm going to
> provide examples of where we do or would use a feature like this in
> extension modules so that you can see that I'm just trying to extend the
> fun to Python programmers (not just extension writers).
> There are about a million places in Python's implementation where
> extension modules do computation like:
> def __setattr__( name, val ):
>     if attribute_to_set=="__class__":
>         assert PyClass_Check( val ):
>     elif attribute_to_set=="__dict__":
>         assert PyDict_Check( val ):

But that's just an implementation detail (you either do the
lookup via a mapping, e.g. the instance dict, or by switching
on the attribute name)... in C and with only a few cases, the
switching technique is faster than the lookup.

> One could imagine a circumstance in which we decide to "trap"
> sys.stdin=o so that if it HASN'T been set we could use a more efficient
> stdout writing protocol internal to the interpreter implementation.
> In general, it is useful when you want to migrate from an
> attribute-setting situation to a computational situation without
> changing existing code.
> You can also think of the various places where the interpreter traps
> when you try to write to a read-only attribute.
> In pyexpat, when you assign to certain variables we "push" that
> information down to expat itself (set variables in expat).
> Imagine trying to read or write an attribute over COM or CORBA. Why
> should Python programmers have to use foo.set("a", 5) when VB
> programmers just say foo.a=5? Mark Hammond currently does this with
> __getattr__ I believe. It would be more efficient better to
> auto-generate getter and setter methods.
> In general, its useful for proxy situations where the set of attribute
> you want to proxy are known in advance.
> It's just a cleaner, Pythonic way to do something that is already common
> either using __getattr__ hacks or in extension modules.

It's also *much* slower: you'd have to check objects for
e.g. obj.__set_foo__ prior to every obj.foo=1 assignment.

I think that these techniques are better implemented by
writing a special proxy which then does your proposed
mapping for a predefined set of attributes.

mx.Proxy would be a good code base for these kind of
experiments, but a simple Python prototype would do
as well.
> > These not only define a distinct interface, but also provide
> > more flexibility, e.g. get_foo() could have a default argument.
> I'm not taking away anyone's right to use methods. The logical extension
> of your argument is that we should always use getter/setter methods in
> case we need to add arguments to them later. That's the Java stance but
> I think we can differentiate ourselves from Java with clearer code.

Well, you can't really say what is best in the general case.

I usually use the direct attribute access method for
information containers and the method access for more
elaborate objects (ones which care about the data format,
apply extra checks, depend on state, etc.). Very often
these methods set more than just one attribute, so using
__set_foo__ wouldn't work here.

Marc-Andre Lemburg
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/