Why property works only for objects?

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Sat Mar 11 03:52:04 CET 2006


Michal Kwiatkowski a écrit :
> Steven Bethard napisał(a):
> 
>>>Is there any method of making descriptors on per-object basis?
>>
>>I'm still not convinced that you actually want to, but you can write
>>your own descriptor to dispatch to the instance object (instead of the
>>type):
> 
> 
> Ok, this works for attributes I know a name of at class definition. What
> about other situations? I could possibly want to have different sets of
> attributes for instances of a class.

Then you want a different class for each different set of attributes.

> Is it still possible to do? I don't
> also like current solution, as it wraps things around, creating another
> attribute ('_x') in the process. Aren't there any cleaner solutions?
> 
> The problem is I have an instance of a given class (say BaseClass) and I
> want it to implement some attribute accesses as method calls. I'm not a
> creator of this object, so changing definition of BaseClass or
> subclassing it is not an option. 

What you want is delegation. Which is pretty easy with Python, look at 
__getattr__ and __setattr__.

> Code below doesn't work, but shows my
> intention:
> 
> # obj is instance of BaseClass
> def get_x(self):
>     # ...
> def set_x(self, value):
>     # ...
> obj.x = property(get_x, set_x)

class ObjWrapper(object):
   def __init__(self, obj):
     self.obj = obj

  # special case x
  def _get_x(self):
    return self.obj.x

  def _set_x(self, value):
    self.obj.x = value

  x = property(fget=_get_x, fset=_set_x)

  # default lookup, directly delegate to obj
  def __getattr__(self, name):
    return getattr(self.obj, name)

  def __setattr__(self, name, value):
    # this one is a bit more tricky
    # and I don't remember it right now,
    # but it's in the fine manual anyway

obj = ObjWrapper(obj)
obj.x # calls ObjWrapper._get_x()


> Changing __setattr__/__getattr__ of an object also doesn't work for the
> same reason: dictionary lookup is made only in class attributes,
> ommiting object attributes. It's confusing, because writting obj.x and
> obj.__getattribute__('x') gives a different results. There also seems
> not to be any clear way to define methods for objects. Something like:
> 
> class C(object):
>     pass
> 
> def method(self):
>     return self.x
> 
> c = c.x
> c.method = method
> c.method() # => AttributeError

import types
c.method = types.MethodType(method, c, c.__class__)

> So another question arise. Is it possible to make function a method (so
> it will receive calling object as first argument)?

Yeps, just wrap it in a Method object (cf above)




More information about the Python-list mailing list