以下を実装するためのエレガントな(効率的な)方法を探しています:
値のリストを文字列として格納するクラスがあります(セパレーター付き、例: " - ")。プロパティ (ゲッターとセッター) を使用して、この文字列を Python に変換しますlist
。
class C(object):
def __init__(self, values):
"""
Construct C with a string representing a list of values.
:type values: str
:param values: List of values
"""
self.values = values
@property
def value_list(self):
""" Values as list """
return self.values.split(" - ")
@value_list.setter
def value_list(self, seq):
self.values = " - ".join(seq)
プロパティの取得/設定はOKです:
c = C("one - two")
assert c.value_list == ["one", "two"]
c.value_list = ["one", "two", "three"]
assert c.values == "one - two - three"
しかし、変更を自動的に反映する何か (別の種類のリストかもしれません) を探していlist
ます。
c.value_list.append("four")
assert c.values == "one - two - three - four"
Traceback (most recent call last):
...
AssertionError
list
現在、コールバック システムで継承する独自のクラスを実装してcollections.MutableSequence
います。それを行うより良い方法はありますか?
編集:私の現在の解決策
次のように、「on_change」ハンドラーを含むリストを使用します。
class MyList(collections.MutableSequence):
""" A ``list`` class with a "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)
次に、C
このハンドラーを実装して変更を反映するようにクラスを変更する必要があります。
クラスの新しいバージョンは次のとおりです。
class C(object):
def __init__(self, values):
"""
Construct C with a string representing a 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 as 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)
values
そうすれば、リストの変更が属性に反映されます。
c = C("one - two")
c.value_list.append("three")
assert c.values == "one - two - three"
c.value_list += ["four"]
assert c.values == "one - two - three - four"