Adding properties to an instance

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Thu Feb 7 04:05:20 EST 2008


dg.google.groups at thesamovar.net a écrit :
> On Feb 6, 11:09 pm, "bruno.desthuilli... at gmail.com"
> <bruno.desthuilli... at gmail.com> wrote:
>> While this is technically possible (I tried a couple years ago), it
>> requires hacking the __getattribute__ method, which is something I
>> would not recommand, not only because it can be tricky, but mostly
>> because this is a very critical path wrt/ perfs.  (IIRC it also
>> required using custom descriptors, but I'm not really sure about this
>> last point).
> 
> Performance is pretty important for the class I'm designing so I think
> __getattribute__ is probably out. The computed properties are only
> infrequently accessed, but using __getattribute__ slows everything
> down, right?

Indeed - it *is* the attribute lookup mechanism. Better to leave it alone.

>> Before new-style classes, we used the __getattr__/__setattr__ hooks
>> for computed attributes. While this approach is now a bit abandonned
>> in favor of descriptors (properties or custom ones), it still works
>> fine, and is probably the best solution to your problem.
> 
> Ah, I didn't know about these - it looks as though they might be just
> the thing since it seems they're only called after all the other
> methods fail.

Right.

> That looks like there would be no performance hit, I
> wouldn't need to mess around with dynamically changing the class, and
> it would automatically deal with the (irritating) feature of having to
> check if there is already something in the object's dir() with that
> name. I'll look into this tomorrow - I hope this feature isn't going
> to be removed in future versions of Python?

I really don't think so. It's still has it's use for automatic 
delegation. And, as is the case here, for per-instance computed attributes.

As a side note: the naming symetry between __getattr__ and __setattr__ 
is a gotcha, since __setattr__ is mostly symetric to __getattribute__ - 
IOW, customizing __setattr__ is a bit tricky. The naive approach, ie:

class Parrot(object):
     def __setattr__(self, name, val):
         self.name = val

will indeed go into infinite recursion (or would, if the interpreter 
didn't stop it after a while)

The solution is of course to call on the parent class's __setattr__:

class Ni(object):
     def __setattr__(self, name, val):
         object.__setattr__(self, name, value)

HTH



More information about the Python-list mailing list