在字符串属性中反映Python列表更改

2024-03-28 13:11:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一种优雅(高效)的方法来实现以下目标:

我有一个类将值列表存储为字符串(带有分隔符,例如:“-”)。我使用一个属性(getter和setter)将这个字符串转换成Pythonlist。你知道吗

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中的变化。你知道吗

c.value_list.append("four")
assert c.values == "one - two - three - four"

Traceback (most recent call last):
...
AssertionError

目前,我用回调系统实现了自己的list类继承collections.MutableSequence。 有没有更好的办法?你知道吗

编辑:我当前的解决方案

我使用带有“on\u 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"

Tags: self列表indexvalueondefassertchange
2条回答

我将通过重载您想要支持的某些操作符来实现这一点,例如+= operator by defining ^{}。然后,您可以执行以下操作:

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'

相关问题 更多 >