【问题标题】:In Ruby, what does a top-level assignment do?在 Ruby 中,顶级作业有什么作用?
【发布时间】:2019-02-20 08:56:48
【问题描述】:

我在.rb 文件的顶层有以下代码:

class Times
    def initialize(n)
        @n = n               
    end
    def each()        
        (1..@n).each {yield}
    end
end
three_times = Times.new(3)

def f()
    Times.new(3).each {puts 'Test'}
end
f()

这可以正常工作,并按预期打印 'Test' 三次。但是,如果我将f 中的Times.new(3) 替换为three_times,即three_times.each {puts 'Test'},则会出现错误:

`f': undefined local variable or method `three_times' for main:Object (NameError)

为什么这不起作用?为什么Times 可以从f 中访问,而不是three_times?

更一般地说,顶层的分配(例如three_times = Times.new(3))究竟有什么作用?

【问题讨论】:

    标签: ruby global-variables variable-assignment toplevel


    【解决方案1】:

    因为

    • three_times 是一个局部变量
    • 局部变量只能在特定范围内访问
    • ruby 中的def 创建一个新作用域

    所以当 f 被调用时,它看不到或无法访问three_times

    要访问three_times,请将其更改为全局变量$three_times或实例变量@three_times

    您能够引用 Times 类的原因是它是一个常量,而 ruby​​ 会通过一个单独的过程来查找常量。


    def 的回避问题

    您还可以通过使用块来定义您的方法来访问局部变量,从而回避整个范围门问题。我有时在编写 rake 任务时这样做,但很少在脚本之外这样做。

    three_times = Times.new(3)
    define_method :foo do
      three_times.each { puts 'Tests'}
    end
    foo
    

    【讨论】:

      【解决方案2】:

      为什么这不起作用?为什么Times 可以从f 中访问,而不是three_times?

      名称以小写字母开头的变量是局部变量。局部变量在它们定义的范围内是局部的(这就是为什么它们被称为 local 变量。)

      名称以大写字母开头的变量是常量。常量首先在默认常量范围内查找,然后按词法向外查找,然后通过继承动态向上查找。

      更一般地说,顶层的分配(例如three_times = Times.new(3))究竟有什么作用?

      没什么特别的。它的作用与其他任何地方的赋值相同。在这种情况下,它:

      1. 解引用变量(常量)Times,我们称这个对象为o1。
      2. 评估字面整数表达式3,我们将结果对象称为o2。
      3. 将消息new 发送到o1,将o2 作为参数传递。让我们将该消息的答案发送 o3。
      4. 将 o3 绑定到名为 three_times 的局部变量。

      如您所见,其中没有任何特定于脚本范围或顶级的内容。

      【讨论】:

        【解决方案3】:

        这是因为它正在寻找一个名为“three_times”的局部变量。如果您希望将“three_times”设置为“顶级”或“全局”,请在变量名称前加上 $,使其为“$three_times”。

        【讨论】:

          【解决方案4】:

          您的代码对我有用,没有错误。你可以拨打f()成功

          【讨论】:

          • 如前所述,如果我将f 中的Times.new(3) 替换为three_times,代码将停止工作。
          猜你喜欢
          • 2014-07-24
          • 2011-12-04
          • 2011-06-29
          • 1970-01-01
          • 2011-06-12
          • 2014-06-10
          • 2019-03-01
          • 1970-01-01
          • 2023-01-12
          相关资源
          最近更新 更多