【问题标题】:ruby unintended variable assignment/changeruby 意外变量赋值/更改
【发布时间】:2013-11-27 21:00:21
【问题描述】:

我在编程方面是个外行,并且对 ruby​​ 很陌生,但无论如何我觉得它对我的工作很有用。目前我正在编写一个相当大的脚本,它带来了以下意想不到的效果:

def my_reduce_method(value_hash,some_keys)
  value_hash.delete(some_keys) 
end

puts all_values
=> all_values

some_values = all_values # start my block with all values (class: hash)

some_values = my_reduce_method(some_values,keys_to_reduce) 
# here only some_values should be effected!

puts all_values
=> some_values

就在方块中没有损坏,但原来的all_values丢失了!如何确保在某个代码块中某个变量绝对没有改变?

提前感谢您的任何意见!!!

【问题讨论】:

  • 您发布的代码中的任何内容都不会修改all_values,所以我猜my_reduce_method 中的某些内容正在修改它。
  • 这是 all_values 的浅拷贝。那就是问题所在。 my_reduce_method 正在修改 some_values,它指向的数据与 all_values 指向的数据相同。
  • 没有充分的理由投反对票。我见过的第一次发布海报中最合适的问题。
  • @Plasmarob,并且像往常一样,没有为否决票提供任何解释/理由。
  • 一种简单的方法来制作任何对象o 的深层副本,可以是dup'ed:Marshal.load(Marshal.dump(o))

标签: ruby variables variable-assignment


【解决方案1】:

Ruby 中的所有对象赋值都是引用赋值。

也就是说,当你这样做时:

some_values = all_values

您正在复制 all_values 正在引用(或指向)的对象的引用(或地址)。

您的情况的解决方案很简单:

some_values = all_values.clone

.dup 通常也可以工作(可能因对象而异)。

另一件需要注意的事情是,当all_values[:x] 有一个字符串并且你这样做时:

some_values = all_values.clone
some_values[:x] += 'abc'

这不会改变all_values[:x],因为some_values[:x] 获得(分配了)一个新的字符串对象。

但如果你这样做:

some_values = all_values.clone
some_values[:x] << 'abc'

all_values[:x]some_values[:x] 都发生了变化,因为它们都引用了同一个字符串对象。

这是@Plasmarob提到的浅拷贝的效果。

【讨论】:

  • 字符串也是引用。
  • 您真好。有一天,我希望看到 SO 实现一个干净的界面,供人们合并他们的答案和所有权。
  • 同上,同上,同上。
  • @Plasmarob 我的意思是,.clone 和 .dup 也会制作浅拷贝。感谢您的友好评论。
  • @jaeheung:字符串是可变的,因此在将它们分配给变量时不会被复制。他们只是得到一个新的参考。然后两个变量都指向同一个 String 对象(由其object_id 验证)
【解决方案2】:

Object#clone 保留了冻结属性和单例方法。如果你 不需要那些,你的例子会发生什么,Object#dup 就足够了。

【讨论】:

    猜你喜欢
    • 2021-10-17
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多