possible attribute-oriented class

Jan Kaliszewski zuo at chopin.edu.pl
Mon Sep 7 21:02:25 EDT 2009


08-09-2009 o 02:15:10 Steven D'Aprano <steve at pearwood.info> wrote:

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

a['xyz'] = something['blablabla'] + somethingelse['foobar']
b['ababababa'] += afun(bobo['dodo']['kookoo'] * pofopofo['gh'][0]['a'])
cupu['abc'] = (kukumunu['bo'], kukumunu['kuu'].mbmbmb['lalala'])

a.xyz = something.blablabla + somethingelse.foobar
b.ababababa += afun(bobo.dodo.kookoo * pofopofo.gh[0].a)
cupu.abc = (kukumunu.bo, kukumunu.kuu.mbmbmb.lalala)

For me the latter is definitely easier to read and understand.

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

You are right, but it's a bit different story... I don't say that attr
access is always better than key access -- but only that sometimes it is.

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

Me too! :)

> 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

I'd add to it also dict-like iteration (__iter__(), _keys(), _values(),
_items()) and __str__ adjusted to nice nested representation (like in
some posts in this thread, e.g. my proposition).

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

I think it depends how often people need to implement such boiler-plate
code for themselves. Now I see that this thread is not very popular, so
indeed maybe you are right... Though it'd be nice to have OOTB such
a factory in `collections` module...

Cheers,
*j

-- 
Jan Kaliszewski (zuo) <zuo at chopin.edu.pl>



More information about the Python-list mailing list