[Python-Dev] assymetry in descriptor behavior
David Abrahams
dave@boost-consulting.com
Sun, 23 Feb 2003 21:18:01 -0500
Guido van Rossum <guido@python.org> writes:
>> I considered these two options:
>>
>> option 1:
>> introduce a separate metaclass for every wrapped class so that we
>> have a place to stick a property object.
>>
>> option 1a:
>> only do this if the user supplies a special extra template
>> parameter to the class_<...> declaration
>>
>> option 2:
>> Implement a special property type which allows us to easily
>> identify property attributes which correspond to Boost.Python static
>> data members
>>
>> Implement a special __setattr__ in the Boost.Python metaclass which
>> looks up the attribute on the class to see if it has this special
>> type; if so, it is called, and otherwise the default __setattr__
>> behavior takes effect.
>>
>> I was going to go with option 1. Are you suggesting option 2?
>
> It would seem to be less work than having a separate metaclass for
> each class that has a static data item. But it's really up to you.
My reasoning was:
it favors speed and code size over data size. The only downside I
can see is that an extra object (the metaclass object) is created
for every wrapped class. It's also simpler to implement.
However, I think it might also cost an extra property object per
wrapped class, unless I can find a way to get the class and its
instance to share the property. Hmm, feels a bit hack-ish to me now
that you mention it. Maybe option 2 is better after all. But then,
do I want to implement tp_getattr or tp_getattro? I don't recall the
differences.
>> Yes, but type is always non-None, it seems.
>
> Yes, that's what I said.
>
>> Look at descrintro.html again. It says:
>>
>> Example: coding super in Python.
>>
>> As an illustration of the power of the new system, here's a fully
>> functional implementation of the super() built-in class in pure
>> Python. This may also help clarify the semantics of super() by
>> spelling out the search in ample detail. The print statement at the
>> bottom of the following code prints "DCBA".
>>
>> class Super(object):
>> def __init__(self, type, obj=None):
>> self.__type__ = type
>> self.__obj__ = obj
>> def __get__(self, obj, type=None):
>> ^^^^^^^^^
>> if self.__obj__ is None and obj is not None:
>> return Super(self.__type__, obj)
>> else:
>> return self
>>
>> Also, PEP 252 says:
>>
>> - __get__(): a function callable with one or two arguments that
>> retrieves the attribute value from an object.
>>
>> What's that about? Does __get__ ever get called with just one
>> argument (excluding self)? If so, when?
>
> When you call it yourself (rather than when it is called as a result
> of __getattribute__).
When do you call it yourself?
> I suppose this is a bit redundant.
I guess; I don't know. I'm trying to understand whether "callable
with one or two arguments" is really part of the requirements for use
as a property method, or just something that got thrown in there.
>> >> 3. Is there documentation for __delete__ anywhere?
>> >
>> > Apparently not, but it's easy to guess what it does if you know
>> > __getattr__, __setattr__ and __delattr__. It's __delete__ and not
>> > __del__ because __del__ is already taken. In an early alpha release
>> > it was actually __del__, but that didn't work very well. :-)
>>
>> It's easy enough to guess what it does by instrumenting it, too.
>> However, it's been out in a released Python for several versions now
>> and I get tired of guessing every time I have to write a new one of
>> these ;-). I think it's time there were some official docs.
>
> So volunteer some.
I'm anxious to, and I will -- just as soon as I can get a clear
picture of what I should say. Gee, I guess "someone" should document
__getattribute__ while I'm in there. Are there any other obvious
omissions in that neighborhood?
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com