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
--
http://mail.python.org/mailman/listinfo/python-list