[Python-Dev] assymetry in descriptor behavior
Guido van Rossum
guido@python.org
Sun, 23 Feb 2003 19:53:57 -0500
> FWIW, it doesn't disambiguate anything:
I'm not prepared to argue about C++ with you. :-)
> 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.
> >> 2. What are the optional type=None arguments for? It seems as though
> >> only the middle argument (obj) is ever None. I just copied this
> >> protocol out of descrintro.html
> >
> > Only __get__ has both obj and type as arguments; __set__ has obj and
> > value, __delete__ only obj.
> >
> > __get__ has obj and type because it can be used for instance and class
> > attribute access. When called for a class, obj is None because it is
> > unavailable; but when called for an instance, type is set to obj's
> > class, for the convenience of descriptors that aren't interested in
> > the instance (like staticmethod and classmethod).
>
> 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__). I suppose this is a bit redundant.
> >> 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.
--Guido van Rossum (home page: http://www.python.org/~guido/)