[Python-ideas] possible attribute-oriented class

Steven D'Aprano steve at pearwood.info
Tue Sep 8 02:15:10 CEST 2009

On Mon, 7 Sep 2009 09:37:35 am Jan Kaliszewski wrote:
> 06-09-2009 o 20:20:21 Ethan Furman <ethan at stoneleaf.us> wrote:

> > ... I love being able to type
> >
> >    current_record.full_name == last_record.full_name
> >
> > instead of
> >
> >    current_record['full_name'] == last_record['full_name']
> Me too, and I suppose many people too...
> The latter:
> * makes your code less readable if there is high density of such
>    expressions;
> * makes typing much more strenuous/irritating -- what is not very
>    important in case of advanced development (when time of typing is
>    short in relation to time of thinking/reading/testing) but becomes
>    quite important in case of scripting (which is still important
> area of Python usage).

If you have a large number of such expressions, what's wrong with this?

FNAME = "full_name"  # Define the string in one place only.
current_record[FNAME] == last_record[FNAME]  # Use it in many places.

Not only is it shorter to use, but it's easy to change the 
key "full_name" to (say) "complete_name" or "volledige_naam" with one 
edit, and without mistakenly changing some other string which just 
happens to match the key. (I don't know about others, but when I'm 
first working on a piece of code, and before I settle on an API or 
database schema, I often change field names two or three times before I 
settle in on the final version.)

In any case, while I accept that this is sometimes useful, I also think 
that it's a something which is simple enough to add to your classes 
when necessary with just a few lines -- all you really need are the 
__*attr__ methods, everything else is superfluous. If you're doing this 
a lot, avoid boilerplate with a class decorator. Here's an untested 
minimalistic version which probably does everything necessary:

def add_attr(cls):
    """Class decorator which adds attribute access to mappings."""
    def __getattr__(self, name):
        return self[name]
    def __setattr__(self, name, value):
        self[name] = value
    def __delattr__(self, name):
        del self[name]
    for func in (__getattr__, __setattr__, __delattr__):
        setattr(cls, func.__name__, func)
    return cls

Fields of an object (attributes) and keys of a mapping are generally for 
different purposes, and I'm not sure we should encourage people to 
conflate the two. I think this belongs in the cookbook, not the 
standard library.

Steven D'Aprano

More information about the Python-ideas mailing list