2

我正在寻找一种优雅(有效)的方式来实现以下内容:

我有一个类将值列表存储为字符串(带有分隔符,例如:“ - ”)。我使用一个属性(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.

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"
4

2 回答 2

1

我会通过重载您想要支持的某些运算符来解决这个问题,例如+= 运算符通过定义__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"

有关运算符重载的更多信息,请参阅文档

于 2016-06-06T19:58:03.210 回答
1

也许我过度简化了你的问题,因为你过度简化了你的第一个例子,但我会同意一些评论者的观点,并建议你改变你存储它的方式。存储列表,按需生成字符串。

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'
于 2016-06-06T20:44:17.747 回答