i'm searching elegant (an efficient) way implement following:
i have class storing list of values string (with separator, eg.: " - "). use property (getter , setter) convert string python list
.
class c(object): def __init__(self, values): """ construct c string representing list of values. :type values: str :param values: list of values """ self.values = values @property def value_list(self): """ values list """ return self.values.split(" - ") @value_list.setter def value_list(self, seq): self.values = " - ".join(seq)
getting / setting property ok:
c = c("one - two") assert c.value_list == ["one", "two"] c.value_list = ["one", "two", "three"] assert c.values == "one - 2 - three"
but i'm looking (may kind of list) automatically reflect changes in list
.
c.value_list.append("four") assert c.values == "one - 2 - 3 - four" traceback (most recent call last): ... assertionerror
currently, implement own list
class inheriting collections.mutablesequence
callback system. there better way that?
edit: current solution
i use list "on_change" handler, this:
class mylist(collections.mutablesequence): """ ``list`` class "on_change" handler. """ def __init__(self, *args): self._list = list(*args) def on_change(self, seq): pass def __getitem__(self, index): return self._list.__getitem__(index) def __len__(self): return self._list.__len__() def __setitem__(self, index, value): self._list.__setitem__(index, value) self.on_change(self._list) def __delitem__(self, index): self._list.__delitem__(index) self.on_change(self._list) def insert(self, index, value): self._list.insert(index, value) self.on_change(self._list)
then need modify c
class implement handler reflect changes.
the new version of class is:
class c(object): def __init__(self, values): """ construct c string representing list of values. :type values: str :param values: list of values """ self.values = values def _reflect_changes(self, seq): self.values = " - ".join(seq) @property def value_list(self): """ values list """ my_list = mylist(self.values.split(" - ")) my_list.on_change = self._reflect_changes return my_list @value_list.setter def value_list(self, seq): self.values = " - ".join(seq)
that way, change in list in reflected in values
attribute:
c = c("one - two") c.value_list.append("three") assert c.values == "one - 2 - three" c.value_list += ["four"] assert c.values == "one - 2 - 3 - four"
maybe i'm oversimplifying problem because you've oversimplified first example, i'm going agree of commenters , propose change around way store this. store list, produce string on demand.
in [1]: class c(object): ...: def __init__(self, values): ...: self.values = values.split(' - ') ...: @property ...: def value_str(self): ...: return ' - '.join(self.values) ...: in [2]: c = c('one - 2 - three') in [3]: c.values out[3]: ['one', 'two', 'three'] in [4]: c.values.append('four') in [5]: c.value_str out[5]: 'one - 2 - 3 - four'