Bruno Desthuilliers
2/7/2008 9:05:00 AM
dg.google.groups@thesamovar.net a écrit :
> On Feb 6, 11:09 pm, "bruno.desthuilli...@gmail.com"
> <bruno.desthuilli...@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