Python descriptor protocol (for more or less structured data)

CWr christoph.wruck at gmail.com
Tue Jul 30 09:04:14 EDT 2013


Hi together,

Some years ago I started a small WSGI project at my university. Since then the project was grown up every year. Some classes have more than 600 lines of code with (incl. boiler-plates mostly in descriptors/properties). 

Many of these properties are similar or have depencies among themselves.
The idea is to grouping similar properties like:

new style:
----------
>>>m = MyClass(...)
>>>m.attr = 'some; complex:data#string'

>>>m.attr.value
'some'
>>>m.attr.extras
{'complex':('data','string')}

I wrote this descriptor:

class Descr:
    
    def __init__(self, value):
        self.attribute = self.__class__.__name__
        self.__set__(None, value)

    def __get__(self, obj, Type=None):
        return getattr(obj, self.attribute, self)
        
    def __set__(self, obj, value):
        if obj is None: # descripting yourself
            # do something here ...
            self.value = value
        else:
            if hasattr(obj, self.attribute):
                self.__get__(obj).__set__(None, value)
            else:
                setattr(obj, self.attribute, type(self)(value))

This works fine as long as the value attribute of Descr is read-only and the 
user have to use the descriptor interface e.g. __get__/__set__. Because
it's not guaranteed that the user gets a seperated instance of Descr which
will be living in obj.__dict__. If obj is None the descriptor will be returned
themselves.

But I would like that the user can use the following statement:

>>>m = MyClass(...)
>>>m.attr = 'some; complex:data#string'
>>>m.attr.value
'some'
>>>m.attr.value = 'some other'
>>>m.attr.value
'some other'

But this usage will be problematic. If the descriptor returned themselves (default case) and the user modified the value, he modified the default
value without to create a seperated instance attribute.

>>>class C:
>>>    def __init__(self, value):
>>>        if not value is None:
>>>            self.attr = value
>>>    attr = Descr('default value')

>>># explicit default usage (no problem): 
>>>C.attr.value
'default value'

>>>a = C()
>>>a.attr.value
'default value'

The following is the main Problem:

>>>a.attr.value = 'other'
>>>C.attr.value
'other'

The user could think that a new instance based value will be created. But it
isn't.

It will works fine only if I assign a value explicitly.

>>>m = MyClass(value='test')
>>>m.__dict__
>>>{'Descr':<object of ...>}

Has anyone had a similar problem in the past? Or I am on the wrong way.

Kind Regards,
Chris

Sorry for my terrible english ...





 








More information about the Python-list mailing list