更改ruby变量/引用的值
我只是偶然发现了一些我不太明白的东西。我知道ruby中的变量是引用。所以,这些很棒的东西是可能的。但当我将一个变量传递给一个方法时,它的行为异常:更改ruby变量/引用的值,ruby,variables,reference,scope,Ruby,Variables,Reference,Scope,我只是偶然发现了一些我不太明白的东西。我知道ruby中的变量是引用。所以,这些很棒的东西是可能的。但当我将一个变量传递给一个方法时,它的行为异常: my_var_a = "nothing happend to me" my_var_b = "nothing happend to me" def parse_set(my_var_set) my_var_set = "my value changed" end def parse_sub(my_var_sub) my_var_sub.s
my_var_a = "nothing happend to me"
my_var_b = "nothing happend to me"
def parse_set(my_var_set)
my_var_set = "my value changed"
end
def parse_sub(my_var_sub)
my_var_sub.sub! /(.*)/, "my value changed"
end
parse_set(my_var_a)
parse_sub(my_var_b)
my_var_a # => "nothing happend to me"
my_var_b # => "my value changed"
你能解释一下为什么它与
sub一起工作吗
和=
是否使对象保持不变?如何避免使用sub代码>但具有相同的结果?my\u var\u a
和my\u var\u set
是不同的引用,但它们指向相同的对象。如果在my\u var\u集合
中修改对象,更改将显示在my\u var\u a
中。但是,如果将my\u var\u set
重新指向一个新对象,则不会更改my\u var\u a
指向的对象
def parse_set()
"my value changed"
end
a = parse_set()
编辑:澄清
Ruby所做的就是按值传递引用。当你说
my_var_a = "nothing happend to me"
Ruby将字符串“nothing happend to me”保存在一个内存位置(我们称之为1000),并将my\u var\u a
引用保存在另一个内存位置(比如2000)。当您的代码使用my_var_a
时,解释器会查看位置2000,查看它是否指向1000,然后从1000中获取实际字符串值
当您调用parse\u set(my\u var\u a)
时,Ruby实际上创建了一个名为my\u var\u set
的新引用,并将其指向my\u var\u a
指向的字符串(内存位置1000)。然而,my_var_集
是my_var_a
引用的副本——比如说my_var_集
是在内存位置3000处创建的my_var_a
和my_var_set
是内存中两个完全不同的引用,它们恰好指向保存字符串值的相同内存位置
parse\u set
中的语句my\u var\u set=“my value changed”
在内存中创建一个新字符串,并将my\u var\u set
指向该新内存位置。但是,这不会改变原始的my\u var\u a
参考点所在的位置!既然my\u var\u set
指向不同的内存位置,您对该变量所做的任何操作都不会影响my\u var\u a
同样的引用副本也适用于parse_sub
。但是parse\u sub
更改字符串的原因是,您直接在my\u var\u sub
引用上调用一个方法。执行此操作时,解释器将获取my\u var\u sub
指向的对象,然后对其进行修改。因此,该更改将显示在my_var\u a
引用中,因为它仍然指向相同的字符串
irb(main):008:0* a = 'abc'
=> "abc"
irb(main):009:0> a.replace('def')
=> "def"
irb(main):010:0> a
=> "def"
在我用Ruby编程的这些年里,我不得不使用replace
整整零次。我想知道是否有更好的代码设计
大多数更改接收器的字符串方法的后缀为!(sub!、capitalize!、chomp!、等)某些更改接收器的后缀不是!(替换为一个)。如果调用更改接收器的方法,则对该对象的任何和所有引用都将看到更改。如果调用一个不改变接收方的方法,该方法将返回一个新字符串
gsub不修改接收器,而是返回字符串的新实例:
a = "foo"
b = a
p a.sub(/o/, '#') # "f##"
p a # => "foo"
p b # => "foo"
gsub!是否修改接收器:
a = "foo"
b = a
p a.sub!(/o/, '#') # => "f#o"
p a # => "f#o"
p b # => "f#o"
“如何避免使用sub!但却产生相同的结果?”
将其设置为对象的实例变量(尽管这仅适用于主脚本,但如果您希望使用实例变量方法,我建议您创建自己的类)
你能换个说法吗?我真的不明白关于重新打印的部分:)(我还更改了变量名以减少歧义),我如何在不使用可笑的sub的情况下更改值!还有regex?我补充了一些信息,希望能让事情变得更清楚。按值传递引用是复杂的,需要一段时间才能了解发生了什么。另外,要在不使用sub的情况下更改值,只需让
parse
方法返回一个值,并将其分配给原始变量:my\u var\u a=some\u parse\u method(my\u var\u a)
。哇,这是一个非常好且简单的解释。非常感谢。“按值传递引用”是描述Ruby工作原理最准确的方法。感谢您指出替换方法。但是卡莱布的回答向我解释了内部情况,这样我才能理解发生了什么,否则我会接受你的回答:D
@my_var_a = "nothing happend to me"
def parse_set()
@my_var_a = "my value changed"
end