Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #51561

Re: Python descriptor protocol (for more or less structured data)

From Peter Otten <__peter__@web.de>
Subject Re: Python descriptor protocol (for more or less structured data)
Date 2013-07-30 16:35 +0200
Organization None
References <040f33f6-6435-4aea-98ae-eabf8c16b167@googlegroups.com>
Newsgroups comp.lang.python
Message-ID <mailman.5310.1375194933.3114.python-list@python.org> (permalink)

Show all headers | View raw


CWr wrote:

> 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))

You must not store per-object data in the descriptor. I suggest a naming 
convention (the internal data for obj.attr is stored in obj._attr) together 
with a value class that handles breaking of the string into attributes of an 
instance of itself:

class StructuredAttribute:
    def __init__(self, name, make_default):
        self.name = name
        self.make_default = make_default

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        _name = "_" + self.name
        try:
            return getattr(obj, _name)
        except AttributeError:
            setattr(obj, _name, self.make_default())
        return getattr(obj, _name)

    def __set__(self, obj, value):
        self.__get__(obj).update(value)


class Value:
    def __init__(self, value):
        self.update(value)
    def update(self, value):
        if isinstance(value, str):
            self.value, sep, rest = value.partition(";")
            self.extras = dict(item.partition("#")[::2] for item in 
rest.split())
        else:
            self.value = value.value
            self.extras = value.extras
    def __repr__(self):
        return repr("{}; {}".format(self.value, " ".join("{}:
{}".format(*item) for item in self.extras.items())))

def make_default_value():
    return Value("some; complex:data#string")

class A:
    attr = StructuredAttribute("alpha", make_default_value)

def show(obj):
    print("attr:", obj.attr)
    print("attr.value:", obj.attr.value)
    print("attr.extras:", obj.attr.extras)

a = A()
show(a)
newvalue = "whatever"
print("updating value to", newvalue)
a.attr.value = newvalue
show(a)

That's the general idea if you want "setattr polymorphism". Personally I 
would go with simpler standard attributes:

class A:
    def __init__(self):
        self.attr = Value(...)

a = A()
a.value = Value(...)
a.value.extras = ...


Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Python descriptor protocol (for more or less structured data) CWr <christoph.wruck@gmail.com> - 2013-07-30 06:04 -0700
  Re: Python descriptor protocol (for more or less structured data) Peter Otten <__peter__@web.de> - 2013-07-30 16:35 +0200
    Re: Python descriptor protocol (for more or less structured data) CWr <christoph.wruck@gmail.com> - 2013-07-31 02:16 -0700
      Re: Python descriptor protocol (for more or less structured data) Terry Reedy <tjreedy@udel.edu> - 2013-07-31 13:44 -0400

csiph-web