2011-12-20 50 views
33

考虑下面的代码:Ruby中的字符串是否可变?

$ irb 
> s = "asd" 
> s.object_id # prints 2171223360 
> s[0] = ?z  # s is now "zsd" 
> s.object_id # prints 2171223360 (same as before) 
> s += "hello" # s is now "zsdhello" 
> s.object_id # prints 2171224560 (now it's different) 

好像单个字符是可以改变的W/O创建一个新的字符串。但是附加到字符串显然会创建一个新的字符串。

是在Ruby中的字符串可变的?

+2

是的,通过琐碎的搜索交代。 http://stackoverflow.com/questions/2608493/why-did-matz-choose-to-make-strings-mutable-by-default-in-ruby – 2011-12-20 18:43:18

+0

@DaveNewton:不是很好它是多么容易在SO上寻找诀窍,因为你几乎可以依靠谷歌首先提出的SO话题? – 2011-12-20 18:45:15

+4

'+'连接并将返回一个新的字符串。 '<<'正在附加,并将附加到给定的字符串对象(不会创建一个新对象)。 – Chad 2011-12-20 18:45:43

回答

37

是,在Ruby中的字符串,不像在Python,是可变的。

s += "hello"附加"hello"s - 一个全新的字符串对象被创建。要追加到“到位”的字符串,使用<<,像:

s = "hello" 
s << " world" 
s # hello world 
+3

在Ruby中将'a + = b'想成'a = a + b'是否合理?这将清楚为什么's + =“hello”'创建一个新的字符串。 – emlai 2016-01-08 17:52:36

+1

@tuple_cat是的,这就是'+ ='的实现方式,因此重新定义'+'会得到一个重定义的'+ ='。 – YoTengoUnLCD 2016-07-12 19:08:49

8

Ruby String追加不+=,它是<<

所以,如果你改变+=<<你的问题

+3

+1。正如http://www.rubyfleebie.com/appending-to-a-string/所解释的那样,“'+ ='将创建一个新的String实例并将其分配给您的左对象。另一方面,'<< '会将新字符串直接追加到已存在的左对象中。“ – ruakh 2011-12-20 18:45:01

11
ruby-1.9.3-p0 :026 > s="foo" 
=> "foo" 
ruby-1.9.3-p0 :027 > s.object_id 
=> 70120944881780 
ruby-1.9.3-p0 :028 > s<<"bar" 
=> "foobar" 
ruby-1.9.3-p0 :029 > s.object_id 
=> 70120944881780 
ruby-1.9.3-p0 :031 > s+="xxx" 
=> "foobarxxx" 
ruby-1.9.3-p0 :032 > s.object_id 
=> 70120961479860 

所以,字符串是可变的,但+=运营商创建一个被单独处理新的字符串。 <<保持老

6

字符串在Ruby中是可变的,但你可以冻结改变它。

irb(main):001:0> s = "foo".freeze 
=> "foo" 
irb(main):002:0> s << "bar" 
RuntimeError: can't modify frozen String 
0

从我可以做的this pull request,它将Ruby的3.0成为可能添加一个“神奇的意见”,这将使所有的字符串不变,而不是可变的。

因为看起来你必须明确地添加这个评论,它似乎是“字符串可变的默认?”的答案。仍然是肯定的,但有条件的是 - 取决于你是否将魔术评论写入了你的剧本。

编辑

我指出这个bug/issue on Ruby-Lang.org是明确指出一些类型的Ruby 3.0字符串其实会默认为不可变的。

1

Ruby字符串是可变的。但是你需要使用< <来连接而不是+。
事实上连接字符串与
+运算符(不可变),因为它创建新的字符串对象。
< <操作者(可变)因为它在同一个对象变化。

相关问题