我很难看到为String对象的新实例创建值的过程与创建String文字的值有何不同。
a = String.new("Hello")
# => "Hello"
b = "Hello"
# => "Hello"
如果我跑
a == b
# => true
相同的价值观!发生了什么事?
答案 0 :(得分:4)
字符串文字是一个字符串对象。早期版本的Ruby没有区别。
从Ruby 2.3开始,您可以选择冻结字符串文字。这是Ruby 3.0中的计划默认值
这意味着......
x = String.new("Hello")
x.upcase!
...会产生错误,因为字符串不可变。
使用构造函数......
from nltk import sent_tokenize, word_tokenize
from nltk.tag import StanfordNERTagger
st = StanfordNERTagger('english.muc.7class.distsim.crf.ser.gz','stanford-ner.jar')
i= "He was born on October 15, 1931 at Dhanushkothi in the temple town Rameshwaram in Tamil Nadu."
words = word_tokenize(i)
namedEnt = st.tag(words)
print namedEnt
工作正常。
答案 1 :(得分:1)
在您的示例中,a
和b
是类似c的引用,而不是指针。所以你要比较的是价值而不是对象。
答案 2 :(得分:1)
相同的价值观!发生了什么事?
没有什么特别的,你可以用相同的值创建无限数量的局部变量。
您可以使用Object#object_id
查看这些变量实际上是不同的对象:
a = String.new("Hello")
b = "Hello"
a.object_id #=> 70295696460580
b.object_id #=> 70295696294220
答案 3 :(得分:1)
==
检查内容是否相等。
equal?
检查同等身份。
a = "hello"
b = "hello"
a == b # => true
a.equal?(b) # => false
在Ruby中,字符串文字不是不可变的,因此创建字符串并使用文字确实是相同的。在这两种情况下,每次评估表达式时,Ruby都会创建一个新的字符串实例。
因此两者都是相同的
10.times { String.new }
# is the same as
10.times { "" }
让我们验证这个
10.times { puts "".object_id }
打印10个不同的数字
70227981403600
70227981403520
70227981403460
...
为什么呢?字符串默认是可变的,因此每次在源代码中到达字符串文字时,Ruby都必须创建一个副本。即使这些文字在实践中通常很少被修改。
因此,Ruby程序通常会创建过多的短期字符串对象,这会给垃圾收集带来巨大压力。 Rails应用程序仅为一个请求创建500,000个短期字符串并不罕见,这是将Rails扩展到数百万甚至1亿用户的主要性能瓶颈之一。
解决Ruby 2.3引入的冻结字符串文字,其中所有字符串文字默认为不可变。由于这不是向后兼容的,因此选择使用pragma
# frozen_string_literal: true
让我们验证一下
# frozen_string_literal: true
10.times { puts "".object_id }
打印相同的数字10次
69898321746880
69898321746880
69898321746880
...
有趣的是,在哈希中设置密钥也会创建字符串的副本
str = "key"
hash = {}
hash[str] = true
puts str.object_id
puts hash.keys.first.object_id
打印两个不同的数字
70243164028580
70243132639660