💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 10.可变范围 在上一节中我们已经了解了函数,而在之前我们已经了解了变量。 我认为现在是时候输入变量范围了。 在本章中,我们将探讨在程序的特定部分中声明变量时有价值的时间或长度。 让我们从一个例子开始。 启动你的文本编辑器,输入下面的代码( [variable_scope.rb](code/variable_scope.rb) )并执行它。 ```rb #!/usr/bin/ruby # variable_scope_.rb x = 5 def print_x puts x end print_x ``` 输出量 ```rb variable_scope.rb:7:in `print_x': undefined local variable or method `x' for main:Object (NameError) from variable_scope.rb:10 ``` 好吧,你得到一个错误。 看到你已经通过输入`x = 5`声明了一个变量。 在函数`print_x`中,你告诉 ruby 程序打印出变量 x,但会引发错误。 看一下输出,它说`undefined local variable or method `x' for main:Object (NameError) from variable_scope.rb:10`,那么我们已经定义了`x`并在开始时将其分配为值 5,那么 Ruby 如何抛出错误? 好吧,我们在函数`print_x`之外定义了`x`,因此`x`内部没有作用域,因此会出现错误。 优秀的程序员可以利用编程语言提供的优势,并且足够聪明,可以按其施加的规则和限制发挥作用。 对于新手来说,我们无法访问我们在函数外部分配的变量似乎是一个真正的障碍,但是当你的程序成为成熟的程序员时,你会变相地实现它的祝福。 要了解更多信息,请在文本编辑器中键入以下程序(variable_scope_1.rb)并执行。 ```rb #!/usr/bin/ruby # variable_scope_1.rb x = 5 def print_x x=3 puts x end print_x puts x ``` Output ```rb 3 5 ``` 仔细看一下输出。 首先在程序中声明变量`x = 5`,然后在函数`print_x`中声明变量`x = 3`。 注意,在函数`print_x`中声明的变量与在函数外部声明的变量不同。 接下来,我们调用函数`print_x`,该函数将输出打印为 3,这是预期的结果,因为在`print_x`内部我们在`x = 3`之后编写了`puts x`。 下一个语句是此处的英雄,(在函数外)我们在`print_x`之后写了`puts x`,如果你希望打印 3,则你错了。 这里`x`是我们在函数外部声明的`x`,在这里它将被打印为 5。这意味着在函数内部声明的变量在其外部没有作用域。 要了解更多信息并说服函数内部声明的变量在函数外部没有作用域,我们将尝试另一个程序。 在文本编辑器中输入程序 [variable_scope_2.rb](code/variable_scope_2.rb) 并执行它。 ```rb #!/usr/bin/ruby # variable_scope_2.rb def print_variable y = 3 puts y end print_variable puts y ``` Output ```rb 3 variable_scope_2.rb:10: undefined local variable or method `y' for main:Object (NameError) ``` 这是该程序的工作方式,或者我应该说这是该程序因抛出错误而无法工作的方式。 看一下函数`print_variable`,在其中我们使用语句`y = 3`声明了一个名为`y`的变量,并告诉 ruby 解释器使用语句`puts y`打印其值。 因此,在程序中,当我们调用`print_variable`时,将声明`y`,并且其值 3 不会出现故障。 接下来,我们在函数`print_variable`之外说`puts y`,因为`y`仅在函数内声明,所以在变量`y`之外不存在,并且从技术上讲它没有作用域,因此 Ruby 解释器抛出 错误。 所以我们得到如下错误信息: ```rb variable_scope_2.rb:10: undefined local variable or method `y' for main:Object (NameError) ``` * * * Matz(Ruby 的创建者)似乎没看过电影《回到未来》。 让我们看看另一个证明时间旅行没有内置的程序,在文本编辑器中输入以下程序( [variable_scope_3.rb](code/variable_scope_3.rb) )并执行它。 ```rb #!/usr/bin/ruby # variable_scope_3.rb puts a # you can't access a variable that will be created in future a = 10 ``` Output ```rb variable_scope_3.rb:4: undefined local variable or method `a' for main:Object (NameError) ``` 如果你预期正确,程序将抛出错误。 我们已经在声明`a`之前给了`puts a`。 Ruby 解释器不会考虑将来声明的内容,因此,在遇到`puts a`时,此时将不会声明`a`,因此会引发错误。 换句话说,变量的作用域仅在声明后才开始。 ### 10.1。 全局变量 如果你不喜欢无法从函数外部访问声明的变量的想法,那么 Ruby 提供了一种方法。 有一些称为全局变量的特殊变量,可以从任何地方访问。 全局变量前面带有美元($)符号。 要了解全局变量,请看一个示例。 在下面键入程序( [global_variables.rb](code/global_variables.rb) )并执行它。 ```rb #!/usr/bin/ruby # global_variables.rb $x = 5 def print_x $x = 3 puts $x end print_x puts $x ``` Output ```rb 3 3 ``` 成功运行它,让我们看看它是如何工作的。 首先,我们声明一个全局变量$ x 并将其分配给语句`$x = 5`中的值 5。 接下来,我们定义一个函数`print_x`,其中使用语句`$x = 3`将`$x`的值更改为 3,然后使用`puts $x`打印`$x`的值。 因此,显然我们调用`print_x`,将得到的输出为 3。接下来,在调用`print_x`之后的函数外部,我们将使用`puts $x`打印`$x`的值。 如果你认为它将打印出 5,那么你就错了。 由于可以从任何位置访问`$x`,因此我们将其称为`print_x`,在`print_x`中,无论如何,我们都将`$x`的值更改为 3,即使在函数范围之外,也将`$x`的值更改为 `$x`将被更改。 让我们来看另一个示例,以更好地理解全局变量。 查看下面的示例( [global_variables_1.rb](code/global_variables_1.rb) ),在文本编辑器中键入并执行它 ```rb #!/usr/bin/ruby # global_variables_1.rb $x = 5 def print_x puts $x end print_x $x = 7 print_x $x = 3 print_x ``` 这是程序输出的样子 ```rb 5 7 3 ``` 让我们看看程序如何工作。 首先,我们声明一个全局变量`$x`并使用`$x = 5`将其分配给值 5,然后定义一个名为`print_x`的函数,在其中我们只需使用`puts $x`语句打印出`$x`的值。 当我们调用第一个 print_x 语句时,`$x`的值为 5,因此将输出 5。 接下来,在语句`$x = 7`中将`$x`的值更改为 7,然后调用`print_x`时,将打印现在为 7 的`$x`的值。 最后,使用`$x = 3`将`$x`设置为 3,当最后一次调用`print_x`时,将打印出 3 个。 该程序证明了可以从任何地方操作全局变量,并且可以从任何地方访问这些操作值。 接下来出现一个问题,天气全局变量和局部变量可以具有相同的名称。 答案是肯定的。 这是因为全局变量以`$`符号开头,而局部变量以字母或下划线字符开头,因此 ruby 可以清楚地区分它们之间的区别。 让我们来看一个证明这一点的程序,阅读,学习类型并执行下面给出的程序( [global_variables_2.rb](code/global_variables_2.rb) )。 完成操作后,我们将看到其工作原理。 ```rb #!/usr/bin/ruby # global_variables_1.rb $x = 5 x = 5 def print_x $x = 3 x = 3 puts "In print_x" puts "$x = "+$x.to_s puts "x = "+x.to_s end print_x puts "Outside print_x" puts "$x = "+$x.to_s puts "x = "+x.to_s ``` Output ```rb In print_x $x = 3 x = 3 Outside print_x $x = 3 x = 5 ``` 在上面的程序中,我们在以下几行中声明两个变量,一个是全局变量`$x`并将其分配给值 5,另一个是局部变量`x`并将它分配给值 3 ```rb $x = 5 x = 5 ``` 接下来,我们创建一个函数`print_x`,在其中将`$x`的值更改为 3,因为`$x`是全局的,所以更改在程序中的每个位置都受到影响,接下来我们有了`x = 3`语句,此变量`x`是局部的,与我们在函数外部定义的`x = 5`不同。 接下来,我们将使用以下语句告诉程序打印`$x`和本地`x`的值 ```rb puts "In print_x" puts "$x = "+$x.to_s puts "x = "+x.to_s ``` 好,当程序遇到`print_x`调用时,我们得到以下输出 ```rb In print_x $x = 3 x = 3 ``` 请注意,`$x`现在为 3,本地`x`也为 3。现在,在函数外部,我们使用以下语句(程序的最后 3 行)打印`$x`和`x`的值 ```rb puts "Outside print_x" puts "$x = "+$x.to_s puts "x = "+x.to_s ``` 当执行这些语句时,我们得到以下输出 ```rb Outside print_x $x = 3 x = 5 ``` 由于`$x`已分配给 3,因此将 3 作为其值打印。 此处的`x`仍为 5,因为此处`x`并非指`print_x`内部定义的`x`,而是指其中定义的那个。