在字符串属性中反映 Python 列表变化
Reflect Python list change in string attribute
我正在寻找一种优雅(高效)的方式来实现以下内容:
我有一个 class 将值列表存储为 字符串 (带有分隔符,例如:“ - ”)。我使用 属性(getter 和 setter)将此字符串转换为 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)
获取/设置 属性 正常:
c = C("one - two")
assert c.value_list == ["one", "two"]
c.value_list = ["one", "two", "three"]
assert c.values == "one - two - three"
但我正在寻找一些东西(可能是另一种 list)来自动反映 list
.
中的变化
c.value_list.append("four")
assert c.values == "one - two - three - four"
Traceback (most recent call last):
...
AssertionError
目前,我实现了自己的 list
class 继承 collections.MutableSequence
的回调系统。
有更好的方法吗?
编辑:我目前的解决方案
我将 list 与 "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 以实现此处理程序以反映更改。
class的新版本是:
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"
我会通过重载您想要支持的某些运算符来解决这个问题,例如 += operator by defining __iadd__
。然后您就可以执行以下操作:
class C(object):
def __init__(self, values):
self._values = values
def __iadd__(self, value):
self._values += " - " + str(value)
return self
obj = C("one - two")
obj += "three"
print(obj.values) # "one - two - three"
有关运算符重载的更多信息,请参阅 docs。
也许我过于简单化了您的问题,因为您过于简化了您的第一个示例,但我同意一些评论者的观点,并建议您改变存储它的方式。 存储列表,按需生成字符串。
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 - two - three')
In [3]: c.values
Out[3]: ['one', 'two', 'three']
In [4]: c.values.append('four')
In [5]: c.value_str
Out[5]: 'one - two - three - four'
我正在寻找一种优雅(高效)的方式来实现以下内容:
我有一个 class 将值列表存储为 字符串 (带有分隔符,例如:“ - ”)。我使用 属性(getter 和 setter)将此字符串转换为 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)
获取/设置 属性 正常:
c = C("one - two")
assert c.value_list == ["one", "two"]
c.value_list = ["one", "two", "three"]
assert c.values == "one - two - three"
但我正在寻找一些东西(可能是另一种 list)来自动反映 list
.
c.value_list.append("four")
assert c.values == "one - two - three - four"
Traceback (most recent call last):
...
AssertionError
目前,我实现了自己的 list
class 继承 collections.MutableSequence
的回调系统。
有更好的方法吗?
编辑:我目前的解决方案
我将 list 与 "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 以实现此处理程序以反映更改。
class的新版本是:
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"
我会通过重载您想要支持的某些运算符来解决这个问题,例如 += operator by defining __iadd__
。然后您就可以执行以下操作:
class C(object):
def __init__(self, values):
self._values = values
def __iadd__(self, value):
self._values += " - " + str(value)
return self
obj = C("one - two")
obj += "three"
print(obj.values) # "one - two - three"
有关运算符重载的更多信息,请参阅 docs。
也许我过于简单化了您的问题,因为您过于简化了您的第一个示例,但我同意一些评论者的观点,并建议您改变存储它的方式。 存储列表,按需生成字符串。
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 - two - three')
In [3]: c.values
Out[3]: ['one', 'two', 'three']
In [4]: c.values.append('four')
In [5]: c.value_str
Out[5]: 'one - two - three - four'