Prev: getting rpy2 from repository
Next: cpan for python?
From: Bruno Desthuilliers on 4 Mar 2010 05:59 Eike Welk a écrit : > Bruno Desthuilliers wrote: >> John Posner a écrit : >>> Done -- see http://wiki.python.org/moin/FromFunctionToMethod >> Done and well done !-) >> Thanks again for the good job John. > > I like it too, thanks to both of you! > > I have two small ideas for improvement: > - Swap the first two paragraphs. First say what it is, and then give the > motivation. Mmm... As far as I'm concerned, I like it the way its. John ? > - The section about the descriptor protocol is a bit difficult to > understand. I may eventually try to rework it a bit when I'll have time (death march here currently, duh...) > But judging from the official descriptor documentation, it seems > to be hard to explain Not that easy, indeed. I once posted on c.l.py a longer explanation of the whole lookup rule stuff, that IIRC included a "naive python implementation" example. Might be worth trying to google for it and turning it into another "overview" article. >: The official documentation is nearly incomprehensible > (IMHO). I should probably have a look at it !-)
From: John Posner on 4 Mar 2010 08:35 On 3/4/2010 5:59 AM, Bruno Desthuilliers wrote: >> >> I have two small ideas for improvement: - Swap the first two >> paragraphs. First say what it is, and then give the motivation. > > Mmm... As far as I'm concerned, I like it the way its. John ? I think it doesn't make very much difference. But in the end, I believe it's the student, not the teacher, who gets to decide what's comprehensible. What *does* make a difference, IMHO, is getting more people to participate in the process of shining lights into Python's darker corners. That's why I encouraged (and still encourage) Eike to roll up the sleeves and wade into these waters. Metaphor-mixingly yours, John
From: John Posner on 4 Mar 2010 16:17 On 3/3/2010 6:56 PM, John Posner wrote: > > ... I was thinking > today about "doing a Bruno", and producing similar pieces on: > > * properties created with the @property decorator > > * the descriptor protocol > > I'll try to produce something over the next couple of days. > Starting to think about a writeup on Python properties, I've discovered that the official Glossary [1] lacks an entry for "property" -- it's missing in both Py2 and Py3! Here's a somewhat long-winded definition -- comments, please: --------------------------------------------- An attribute, *a*, of an object, *obj*, is said to be implemented as a property if the standard ways of accessing the attribute: * evaluation: print obj.a * assignment: obj.a = 42 * deletion: del obj.a .... cause methods of a user-defined *property object* to be invoked. The attribute is created as a class attribute, not an instance attribute. Example: class Widget: # create "color" as class attribute, not within __init__() color = <<property-object>> def __init__(self, ...): # do not define "self.color" instance attribute The property object can be created with the built-in function property(), which in some cases can be coded as a decorator: @property. The property object can also be an instance of a class that implements the descriptor protocol. --------------------------------------------- Tx, John [1] http://docs.python.org/glossary.html
From: Bruno Desthuilliers on 5 Mar 2010 07:15 John Posner a écrit : > On 3/3/2010 6:56 PM, John Posner wrote: >> >> ... I was thinking >> today about "doing a Bruno", and producing similar pieces on: >> >> * properties created with the @property decorator >> >> * the descriptor protocol >> >> I'll try to produce something over the next couple of days. >> > > Starting to think about a writeup on Python properties, I've discovered > that the official Glossary [1] lacks an entry for "property" -- it's > missing in both Py2 and Py3! > > Here's a somewhat long-winded definition -- comments, please: > > --------------------------------------------- > An attribute, *a*, of an object, *obj*, is said to be implemented as a > property if the standard ways of accessing the attribute: > > * evaluation: print obj.a > * assignment: obj.a = 42 > * deletion: del obj.a > > ... cause methods of a user-defined *property object* to be invoked. Hmmm... a couple remarks: 1/ "property" is actually the name of a Python builtin type. It's also pretty much used in general OO litterature for what we name "attributes". So I think it would be better to avoid confusion between "property" as the builtin type, "property" as synonym for attribute, and "property" as the more specific concept of "computed attribute" - which is what you're describing here. As far as I'm concerned, I prefer to stick to "computed attribute" for the generic case, and only use "property" when the computed attribute is actually implemented using the builtin property type. 2/ depending on how the computed attribute is implemented, the computation needs not happen on ALL get/set/del access - you can have non-binding descriptors (that is, not implementing __set__). Also, the "standard" access also include getattr(), setattr() and delattr() (might be worth a note). > The > attribute /attribute/user-defined object/ here ? > is created as a class attribute, not an instance attribute. > Example: > > class Widget: > # create "color" as class attribute, not within __init__() > color = <<property-object>> > > def __init__(self, ...): > # do not define "self.color" instance attribute Yes you can, and it's even actually pretty common: # example.py from somewhere import RGBColor class Foo(object): def _get_color(self): return str(self._color) def _set_color(self, val): self._color = RGBColor.from_string(val) color = property(fget=_get_color, fset=_set_color) def __init__(self, colorvalue): self.color = colorvalue > The property object can be created with the built-in function > property(), It's actually a type, not a function. > which in some cases can be coded as a decorator: @property. > The property object can also be an instance of a class that implements > the descriptor protocol. The "property object" IS an instance of a class that implements the descriptor protocol. The property type is just a "generic" descriptor: # naive (and incomplete) python implementation of the property type class property(object): def __init__(self, fget, fset=None, fdel=None) self._fget = fget self._fset = fset self._fdel = fdel def __get__(self, instance, cls): if instance is None: return self return self._fget(instance) def __set__(self, instance, value): if not self._fset: raise AttributeError("can't set attribute") self._fset(instance, value) def __del__(self): if not self._fdel: raise AttributeError("can't delete attribute") self._fdel(instance) As far as I'm concerned, I'd "plan" such a paper as: """ What's a property ? It's a computed attribute implemented using the builtin "property" type. Ok, so far it doesn't help much. So 1/ what's a computed attribute, and 2/ what is the property type ? 1/ your above explanation about what's a computed attribute in general, then a brief explanation of how computed attributes are implemented in python -> IOW, the descriptor protocol 2/ my above snippet !-) """ I think the way you started explaining computed attributes wrt/ attribute access could be a pretty good way to explain the descriptor protocol, since the mapping from get/set/del access to __get__, __set__, and __del__ magic methods is then pretty obvious. But YMMV of course, so by all mean feel free to discard all or parts of the above remarks !-) HTH
From: John Posner on 5 Mar 2010 10:10
On 3/5/2010 7:15 AM, Bruno Desthuilliers wrote: > John Posner a écrit : >> On 3/3/2010 6:56 PM, John Posner wrote: >>> >>> ... I was thinking >>> today about "doing a Bruno", and producing similar pieces on: >>> >>> * properties created with the @property decorator >>> >>> * the descriptor protocol >>> >>> I'll try to produce something over the next couple of days. >>> >> >> Starting to think about a writeup on Python properties, I've >> discovered that the official Glossary [1] lacks an entry for >> "property" -- it's missing in both Py2 and Py3! >> >> Here's a somewhat long-winded definition -- comments, please: >> >> --------------------------------------------- >> An attribute, *a*, of an object, *obj*, is said to be implemented as a >> property if the standard ways of accessing the attribute: >> >> * evaluation: print obj.a >> * assignment: obj.a = 42 >> * deletion: del obj.a >> >> ... cause methods of a user-defined *property object* to be invoked. > > Hmmm... a couple remarks: > > 1/ "property" is actually the name of a Python builtin type. It's also > pretty much used in general OO litterature for what we name > "attributes". So I think it would be better to avoid confusion between > "property" as the builtin type, "property" as synonym for attribute, and > "property" as the more specific concept of "computed attribute" - which > is what you're describing here. > > As far as I'm concerned, I prefer to stick to "computed attribute" for > the generic case, and only use "property" when the computed attribute is > actually implemented using the builtin property type. Yes, I had already decided that the first sentence of the glossary definition needs to be, "A property is a computed attribute". > > 2/ depending on how the computed attribute is implemented, the > computation needs not happen on ALL get/set/del access - you can have > non-binding descriptors (that is, not implementing __set__). Yes, but IMHO that information belongs in the full writeup, not in the glossary definition. I've added the phrase "some or all" in the glossary definition (see below). > Also, the "standard" access also include getattr(), setattr() and > delattr() (might be worth a note). > >> The attribute > > /attribute/user-defined object/ here ? > >> is created as a class attribute, not an instance attribute. Example: >> >> class Widget: >> # create "color" as class attribute, not within __init__() >> color = <<property-object>> >> >> def __init__(self, ...): >> # do not define "self.color" instance attribute > > Yes you can, and it's even actually pretty common: Of course -- and I realize that I was introducing confusion, rather than enlightenment, with my example. I think the point is too subtle for a (necessarily short) glossary definition, so I'm removing the example from the definition. > > # example.py > from somewhere import RGBColor > > class Foo(object): > def _get_color(self): > return str(self._color) > def _set_color(self, val): > self._color = RGBColor.from_string(val) > color = property(fget=_get_color, fset=_set_color) > > def __init__(self, colorvalue): > self.color = colorvalue [OFF-TOPIC] Wow, Thunderbird 3.0.2 nuked the indentation in the code above. :-( > > >> The property object can be created with the built-in function property(), > > It's actually a type, not a function. Ah, yes. Thanks. > >> which in some cases can be coded as a decorator: @property. The >> property object can also be an instance of a class that implements the >> descriptor protocol. > > The "property object" IS an instance of a class that implements the > descriptor protocol. The property type is just a "generic" descriptor: > > # naive (and incomplete) python implementation of the property type > > class property(object): > def __init__(self, fget, fset=None, fdel=None) > self._fget = fget > self._fset = fset > self._fdel = fdel > > def __get__(self, instance, cls): > if instance is None: > return self > return self._fget(instance) > > def __set__(self, instance, value): > if not self._fset: > raise AttributeError("can't set attribute") > self._fset(instance, value) > > def __del__(self): > if not self._fdel: > raise AttributeError("can't delete attribute") > self._fdel(instance) Good stuff for the full writeup on properties. > As far as I'm concerned, I'd "plan" such a paper as: > > """ > What's a property ? It's a computed attribute implemented using the > builtin "property" type. > > Ok, so far it doesn't help much. So > 1/ what's a computed attribute, and > 2/ what is the property type ? > > 1/ your above explanation about what's a computed attribute in general, > then a brief explanation of how computed attributes are implemented in > python -> IOW, the descriptor protocol > > 2/ my above snippet !-) I agree. I'm not sure whether the "brief explanation of how computed attributes are implemented in Python" belongs in the *properties* writeup or the *descriptors* writeup. (I think they should be separate, to avoid making readers brains explode.) I'll make the (initial) call when/if I get that far! > > """ > > I think the way you started explaining computed attributes wrt/ > attribute access could be a pretty good way to explain the descriptor > protocol, since the mapping from get/set/del access to __get__, __set__, > and __del__ magic methods is then pretty obvious. > > But YMMV of course, so by all mean feel free to discard all or parts of > the above remarks !-) > > HTH Here's my leaner, meaner glossary definition of *property*: ------------------- A property is a computed attribute: an attribute, a, of an object, obj, is said to be implemented as a property if some or all of the standard ways of accessing the attribute: * evaluation: result = obj.a * assignment: obj.a = 42 * deletion: del obj.a .... cause methods of another user-defined object to be invoked. This other object can be an instance of the built-in type *property*, or as an instance of a class that implements the descriptor protocol. ------------------- Many thanks, Bruno -- again! -John |