2010-12-23 92 views
6

我有以下字符串子类:修改到位子类的字符串

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 

我希望这个工作如下:

>>> x = S("My") 
>>> x.conc("name") 
'My name' 
>>> x 
'My name' 

相反,我得到这个:

>>> x = S("My") 
>>> x.conc("name") 
'My name' 
>>> x 
'My' 

有没有办法修改字符串?我认为这进入了可变字符串和不可变字符串的区别。子类化似乎是将字符串视为可变对象的正确方法(至少根据python docs),但我认为我错过了我实现中的一些关键部分。

+4

该文档告诉你_wrap_字符串类不是它的子类!也就是说,要做你想做的事情,你应该使用一个持有当前字符串值的属性来创建一个从`object`继承的类。 – katrielalex 2010-12-23 16:08:55

+0

[用手拍打额头] D'oh!谢谢。谢谢。请将上面的评论作为答案(或将其添加到现有的答案中),以便我可以接受它。我想我错过了一些明显的东西。 – mwolfe02 2010-12-23 16:23:58

回答

4

你不能这样做,因为字符串是不可变的。该文档告诉你包装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 

但是,更好的方案是使用StringIO。实际上,通过继承StringIO(注意,您需要使用纯Python版本而不是C版本来完成此操作,并且它是旧样式的类,因此您无法使用super)。这是更整洁,更快,并且更加优雅的IMO。

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

您可以覆盖__repr__,如果你想x看起来更像一个字符串,但是这是不好的做法,因为在可能的情况__repr__是为了在对象的Python中返回一个说明。

3

线self = self + delimiter + next_val是创建一个新可变self分配的self + delimiter + next_val此结果。要达到您想要的效果,您需要将操作直接应用于self变量。但由于字符串是不可变的,所以你不能这样做。这就是为什么所有str的方法都会返回一个新字符串,而不是修改它们操作的字符串。

非常抱歉,您无法完成您要完成的任务。

0

没有可变字符串。有字节/字节表和单字符串列表,您可以修改它们,然后转换为字符串。如果你想模仿一个“可变字符串”,你必须保留一个字符串在私人领域,取代它,否则假装你是那个字符串(这可以是什么)。但是,请注意:这将非常低效,并且可能不需要。此外,你不能总是使用可变字符串代替不可变字符串(例如,作为字典键)。为什么你认为你需要一个可变的字符串?我们其他人(和Java和.NET人)相处得很好。您的conc不起作用,因为Python没有传递引用。 self = ...不改变当前对象,它只是覆盖一个局部变量(self.member = ...确实工作,因为这是一个方法调用修改某些字典)。

+0

Python中的所有内容都是参考。指定自己只是重新命名该名称。 – katrielalex 2010-12-23 16:07:51

+0

@katrielalex:是的,每个变量都是一个引用,但是Python通过值传递了这些引用(或者指针,在C/C++中讲)。 – delnan 2010-12-23 17:05:09

1

Python字符串(以及从它们继承的任何东西)是不可变的。

在UserString模块中有一个叫做MutableString的类,它可以做你想做的事。

如果您使用的是Python的最新版本(如2.7/3.1版本),您还可以查看bytearray,尽管它有它自己的一组限制和怪癖。

0

这里是你想要做什么样的实现:

你可以用更多的方法来扩展这个类。