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 = ... -- http://mail.python.org/mailman/listinfo/python-list