Per instance descriptors ?

Steven Bethard steven.bethard at gmail.com
Wed Mar 22 15:58:19 EST 2006


bruno at modulix wrote:
> Hi
> 
> I'm currently playing with some (possibly weird...) code, and I'd have a
> use for per-instance descriptors, ie (dummy code):
> 
> class DummyDescriptor(object):
>   def __get__(self, obj, objtype=None):
>     if obj is None:
>       return self
>     return getattr(obj, 'bar', 'no bar')
> 
> class MyClass1(object):
>   def __init__(self, bar=None):
>     if bar is not None:
>       self.bar = bar
>     self.baaz = DummyDescriptor()
> 
> mc1 = MyClass1(bar='back')
> mc1.baaz
> -> <__main__.DummyDescriptor object at 0x2aaaabc6c390>
> 
> Which is of course what one would expect...  Now I tried the following
> hack^Mworkaround:
> 
> class MyClass2(MyClass1):
>     def __getattribute__(self, key):
>         v = MyClass1.__getattribute__(self, key)
>         if hasattr(v, '__get__'):
>             return v.__get__(self, self.__class__)
>         return v
> 
> And it *seems* to work just fine:
> 
> mc2 = MyClass2(bar='foo')
> mc2.baaz
> ->  'foo'
> 
> Now the question: is there any obvious (or non-obvious) drawback with
> this approach ?

Don't know if this matters, but if you override __getattribute__, you'll 
slow down all attribute accesses to this object.  If this matters, you 
could write something like:

     class MyClass(object):
         def __init__(self, bar=None):
             if bar is not None:
                 self.bar = bar
         def __getattr__(self, name):
             if name == 'baaz':
                 return self.bar
             elif name == 'bar':
                 return 'no bar'

Then you only incur the penalty on the ``baaz`` lookup and the ``bar`` 
lookup when it's missing -- not on all attribute lookups.

Could you explain again why you don't want baaz to be a class-level 
attribute?

STeVe



More information about the Python-list mailing list