From: Bruno Desthuilliers on
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
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
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
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
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
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6
Prev: getting rpy2 from repository
Next: cpan for python?