On Thu, Mar 15, 2012 at 11:32 AM, Steven W. Orr <ste...@syslang.net> wrote: > Question 1: > > I have a class A with one attribute and I define __get__ and __set__ for > that class. Then I create another class B that uses it. > > Why does B require that the instance of A be a class variable in B and not > created as an instance variable in __init__?
Because that's the way descriptors work -- you put them on a class, and they modify the behavior of instances of that class w.r.t. the attribute they're stored in. If you store an object that implements the descriptor protocol in an instance attribute, then it is treated as ordinary data, not as a descriptor (which would often be undesirable). For example, this behavior is the reason that you can store functions in instance attributes without having them automagically turn into methods of the instance: def make_color(name): if name == 'red': return (255, 0, 0) elif name == 'green': return (0, 255, 0) elif name == 'blue': return (0, 0, 255) else: raise ValueError('Unsupported color %r' % name) class FactoryUser(object): def __init__(self, factory): self.factory = factory def show_blue(self): color = self.factory('blue') print(color) FactoryUser(make_color).show_blue() Here, if "self.factory" were treated as a descriptor, then it would become a method of the FactoryUser instance instead of just an arbitrary function, and the call "self.factory('blue')" would fail, because it would try to pass "self" in as the first argument to "make_color", which it is not expecting since it is not a member of FactoryUser. > Question2: > > Is it the case that people only use descriptors for classes with single > attributes? Or is it more frequent that descriptors are used with classes > that have multiple attributes? property is a convenient shorthand for a one-off descriptor. I use descriptor classes instead when I have a generic behavior that I want to use across multiple attributes, either on a single class or in multiple classes. As a simple, real example, I have a wxPython app with some classes for dialog windows, each of which contain one or more text controls, and I want to be able to access the contents of those text controls as attributes. I could create a whole bunch of properties, each of which does basically the same thing, or I could just use this descriptor class: class TextDescriptor(object): def __init__(self, control_name): self._control_name = control_name def __get__(self, instance, owner): if instance is not None: return getattr(instance, self._control_name).GetValue() def __set__(self, instance, value): getattr(instance, self._control_name).ChangeValue(value) Then to create the individual properties, all I have to do is this: class MyDialog(wx.Dialog): name = TextDescriptor('_name') description = TextDescriptor('_description') address = TextDescriptor('_address') def __init__(self, ...): # Build the dialog along with the _name, _description, and _address controls... Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list