Method / Functions - What are the differences?

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Fri Mar 5 07:15:59 EST 2010


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



More information about the Python-list mailing list