Add Properties to Instances?

Bengt Richter bokr at oz.net
Sat Mar 12 23:46:25 EST 2005


On Sun, 13 Mar 2005 03:18:51 GMT, bokr at oz.net (Bengt Richter) wrote:

>On 12 Mar 2005 09:48:42 -0800, "Martin Miller" <ggrp1.20.martineau at dfgh.net> wrote:
>
>>I'm trying to create some read-only instance specific properties, but
>>the following attempt didn't work:
>>
>>> class Foobar(object):
>>>     pass
>>>
>>> foobar = Foobar()
>>> foobar.x = property(fget=lambda: 42)
>>>
>>> print "foobar.x:", foobar.x
>>
>>Which results in the following ouput instead of '42':
>>  foobar.x: <property object at 0x00AE57B0>
>>
>>I also tried this:
>>> foobar.__dict__['x'] = property(fget=lambda: 42)
>>but get the same behavior.
>>
>>Can anyone tell me what's wrong with this approach (and perhaps the
>>correct way to do it, if there is one)?
>>
>One way is to doctor the instance attribute access to do what
>happens with a property when it is implemented normally as an
>attribute of the class. E.g., (using InstProp in place of your Foobar)
>
> >>> class InstProp(object):
> ...     def __getattribute__(self, attr):
> ...         p = object.__getattribute__(self, attr)
> ...         if isinstance(p, property): return p.__get__(self)
> ...         return p
> ...
Actually, checking for being a property instance is more restrictive than
normal default processing. Checking for __get__ would be better.

This would let you use a function as an instance-specific method as well,
since functions have __get__ methods, and that is how they become bound
methods etc. We'll also pass the type of the instance, to give __get__
everything it needs for a proper bound method.

 >>> class InstProp(object):
 ...     def __getattribute__(self, attr):
 ...         p = object.__getattribute__(self, attr)
 ...         if hasattr(p, '__get__'): return p.__get__(self, type(self))
 ...         return p
 ...
 >>> inst = InstProp()
 >>> def bar(self, *args): print 'bar method called with %r'% (args,)
 ...
 >>> inst.bar = bar
 >>> inst.bar
 <bound method InstProp.bar of <__main__.InstProp object at 0x02EF1E8C>>
 >>> inst.baz = lambda self: 'baz method'
 >>>
 >>> inst.baz
 <bound method InstProp.<lambda> of <__main__.InstProp object at 0x02EF1E8C>>
 >>> inst.baz()
 'baz method'
 >>> inst.p = property(lambda self: 'property p')
 >>> inst.p
 'property p'

Regards,
Bengt Richter



More information about the Python-list mailing list