[Python-Dev] PEP 487 vs 422 (dynamic class decoration)

Nick Coghlan ncoghlan at gmail.com
Sun Apr 5 03:59:01 CEST 2015


On 5 April 2015 at 10:40, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Eric Snow wrote:
>>
>> I've felt for a long time that it would be helpful in some situations
>> to have a reverse descriptor protocol.
>
>
> Can you elaborate on what you mean by that?

My guess from the name and the context: having a way to notify
descriptor objects when they're added to or removed from a class.

That is, the current descriptor protocol works as follows:

1. Descriptor *instances* are stored on *class* objects
2. Descriptor *instance methods* are invoked to control class
*instance* attribute access & modification
3. Descriptors play no role in *class* attribute access &
modification, you have to put descriptors on a metaclass for that

A "reverse descriptor" protocol would be aimed at addressing point 3
without needing a custom metaclass. For example, suppose we took
Martin's "__post_process__" idea, and instead changed it to:

    def __addclassattr__(self, cls, attr):
        "Notifies the descriptor of a new reference from a class attribute"
        ...

    def __delclassattr__(self, cls, attr):
        "Notifies the descriptor of the removal of a reference from a
class attribute"
       ...

If a descriptor had an "__addclassattr__" defined, then not only would
type.__init__ call it during type creation, but so would class
attribute assignment (on the descriptor being assigned, not on one
that is already present). Class attribute *deletion* would call
"descr.__delclassattr__(cls, attr)" on the current descriptor value,
and "__delclassattr__" would also be called on the *current* attribute
descriptor when a class attribute is set to something different. Class
attribute retrieval would remain unaffected, and just return the
descriptor object as it does now.

It would be up to the descriptor implementor to decide how to handle
"__addclassattr__" being called multiple times on the same descriptor
instance (e.g. you might allow it for aliasing purposes within a
single class, but throw an exception if you try to register the same
instance with a second class without removing it from the old one
first).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list