[Baypiggies] Idiotmatic Savanica

Alex Martelli aleax at google.com
Tue May 15 01:46:59 CEST 2007

On 5/14/07, Warren Stringer <warren at muse.com> wrote:
> Last Thursday's newbie night was inspiring!

Glad you liked it!

Is there a more idiomatic way of expressing this? Perhaps a faster, yet
> pythy solution?

I would change things to be more idiomatic in several ways:
a. use "if key in somedict" rather than "if somedict.has_key(key)"
b. know that __getattr__ is only called if OTHER normal ways to
    get the attribute fail (so don't bother checking if one of such
    normal ways would have succeeded!) -- __setattr__ is different
c. add unit tests to make sure one can change and refactor with
    much more confidence

I'm not going to tackle (c), but, without testing, here's roughly how I
might rephrase things...:

class Tr3(dict):

    _ok_attrs = set('who what child parent'.split())

    def __init__(self, parent=None, who='tr3'):
        self.who = who
        self.what = None
        self.child = {}
        self.parent = parent

    def __call__(self, v=None):
        self.what = v

    def __str__(self):
        if self.parent is not None:
            return '%s.%s' % (self.parent, self.who)
            return self.who

    def __getattr__(self, name):
        if name[:2] == '__' == name[-2:]:
            return dict.__getattr__(self, name)
        if name not in self.child:
            self.child[name] = Tr3(self, name)
        return self.child[name]

    def __setattr__(self, name, value):
        if name in self._ok_attrs or name in self.__dict__:
            self.__dict__[name] = value
            if name not in self.child:
                self.child[name] = Tr3(self, name)
            self.child[name].what = value

The intent is to get the same semantics as you had on your page, just
in a slightly more fluid and idiomatic way.
(I'm not quite sure how any name except those in _ok_attrs would ever
end up in self.__dict__, so I do
suspect that test in __setattr__ can be simplifited, but as I said I'm
trying to keep the same semantics as
you had, so I avoided performing that simplification myself).

As I abhor repetition so deeply, I'd probably add a tiny auxiliary method:

    def _setInChild(self, name):
        if name not in self.child:
            self.child[name] = Tr3(self, name)

and call self._setInChild(name) in the two places which now have,
instead, repetitions of this guarded
assignment (but I realize that most people don't abhor repetition as
intensely as I do:-).

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/baypiggies/attachments/20070514/53bf6d3d/attachment.htm 

More information about the Baypiggies mailing list