Python descriptor protocol (for more or less structured data)
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':}
Has anyone had a similar problem in the past? Or I am on the wrong way.
Kind Regards,
Chris
Sorry for my terrible english ...
--
http://mail.python.org/mailman/listinfo/python-list
Re: Python descriptor protocol (for more or less structured data)
Peter, thanks for your response.
Sure, you are right when you say that's easier to use standard attribute
assigning via __init__.
But my intention was:
- reducing the complexiticity of __init__
- avoiding boiler-plates (mostly property descriptors inside of the main class)
- creating instances (for complex data strings) only if they will be needed,
otherwise use default instances (descriptors)
- make it prossible that the data structure can be used in static context -
like MyClass.attr - to get default values
Standard procedure:
>>>class C:
>>>def __init__(self, one, two=None, three=None, four=None, five=None, ...):
>>>if not two is None:
>>>self.two = Value(two)
>>>else:
>>>self.two = Value(self.DEFAULT_4_TWO)
>>>...
vs:
>>>class C:
>>>
>>>two = MyDescriptor('default for two')
>>>
>>>def __init__(self, one, two=None, three=None, four=None, five=None, ...):
>>>self.one = one
>>>if not two is None:
>>>self.two = two
>>>...
Probably it will be necessary to set the attribute at first access.
Alternatively it may be possible to observe the descriptor til an attribute
will be setted e.g. instance.attr.value = 'whatever'. At this point a new
instance (like Value) should be created on obj.__dict__.
It's the procedure what I'm looking for. ;)
Kind Regards,
Chris
--
http://mail.python.org/mailman/listinfo/python-list
string processing - some problems whenever I have to parse a more complex string
Hello together,
currently I have to parse a string in an atomic way. Normally - in this case
too - I have a counter variable to keep the current position inside the string.
So far, I think this is the most flexible solution to do some lookaround's
inside the string if necessary. Subroutines will be feed by the underlying data
and the current position. A subroutine returns a tuple of the new position and
the result. But I would like process subroutines with the same flexibillity
(slicing/lookaround) but without returning the new position every again.
Is there any implementation like C++ StringPiece class? Or something like the
following behavior:
>>>s = StringSlice('abcdef')
>>>s
StringSlice('abcdef') at xxx
>>>s[0]
'a'
>>>s.chop(1) # chop the first item
>>>s[0] # 'b' is the new first item
'b'
>>>s[:2]
'bc'
>>>s.chop(-1) # chop the last item
>>>s[-1]
'e'
>>>s[1:]
'cde'
>>>while s[0] != 'e':
s.chop(1)
>>>s[0]
'e'
>>>s.startswith('e')
True
>>>s.isdigit()
False
Subroutines could chop the number of processed items internally if no error
occours.
Another possibillty will be to chop the current item manually. But I don't know
how efficient this is in case of large strings.
>>>while string:
c = string[0]
# process it ...
string = string[1:]
But this assumes that I have to return rest of the string too and not useful for
my problem covered abrove.
Has anyone some tips what's the best practice to process a complex string,
handling prositions in/and subroutines.
Thanks for all answers...
Cheers
Chris
--
https://mail.python.org/mailman/listinfo/python-list
