修改子类字符串

mwo*_*e02 6 python subclassing

我有以下字符串子类:

class S(str):
    def conc(self, next_val, delimiter = ' '):
        """Concatenate values to an existing string"""
        if not next_val is None:
            self = self + delimiter + next_val
        return self
Run Code Online (Sandbox Code Playgroud)

我希望这可以工作如下:

>>> x = S("My")
>>> x.conc("name")
'My name'
>>> x
'My name'
Run Code Online (Sandbox Code Playgroud)

相反,我得到了这个:

>>> x = S("My")
>>> x.conc("name")
'My name'
>>> x
'My'
Run Code Online (Sandbox Code Playgroud)

有没有办法修改字符串到位? 我认为这涉及到可变字符串和不可变字符串之间的区别.子类化似乎是将字符串视为可变对象的正确方法(至少根据python文档),但我认为我在实现中缺少一些关键部分.

Kat*_*iel 5

你不能做你所要求的事情,因为字符串是不可变的。文档告诉你包装str;也就是说,创建一个具有属性的类,该属性是“可变字符串”的当前值。这在 Python 2.x 的标准库中存在UserString.MutableString(但在 Python 3 中消失了);不过写起来很容易:

class MutableString(object):
    def __init__(self, value):
        self.value = value

    def conc(self, value, delim=' '):
        self.value = "{self.value}{delim}{value}".format(**locals())

    def __str__(self):
        return self.value
Run Code Online (Sandbox Code Playgroud)

然而,更好的计划是使用StringIO. 事实上,您可以通过子类化来获得非常接近您想要的功能StringIO(请注意,您需要使用纯 Python 版本而不是 C 版本来执行此操作,并且它是一个旧式类,因此您不能使用super) 。在我看来,这更整洁、更快,而且更优雅。

>>> from StringIO import StringIO as sIO
>>> class DelimitedStringIO(sIO):
...     def __init__(self, initial, *args, **kwargs):
...             sIO.__init__(self, *args, **kwargs)
...             self.write(initial)
...
...     def conc(self, value, delim=" "):
...             self.write(delim)
...             self.write(value)
...
...     def __str__(self):
...             return self.getvalue()
...
>>> x = DelimitedStringIO("Hello")
>>> x.conc("Alice")
>>> x.conc("Bob", delim=", ")
>>> x.conc("Charlie", delim=", and ")
>>> print x
Hello Alice, Bob, and Charlie
Run Code Online (Sandbox Code Playgroud)

__repr__如果你想x看起来更像字符串,你可以重写,但这是不好的做法,因为在可能的情况下__repr__意味着返回对象的 Python 描述。