【问题标题】:Scope in Ruby and PythonRuby 和 Python 中的作用域
【发布时间】:2013-02-09 03:55:32
【问题描述】:

我一直在同时学习 Ruby 和 Python,我注意到的一件事是这两种语言似乎对作用域的处理方式不同。这是我的意思的一个例子:

# Python
a = 5
def myfunc():
  print a

myfunc() # => Successfully prints 5

# Ruby
a = 5
def myfunc
  puts a
end

myfunc # => Throws a "NameError: undefined local variable or method `a' for main:Object"

似乎 def 块可以访问在 Python 中声明在其直接范围之外的变量,但在 Ruby 中则不能。有人可以确认我的理解是否正确吗?如果是这样,这些考虑范围的方式中的一种是否在编程中更常见?

【问题讨论】:

标签: python ruby scope


【解决方案1】:

免责声明:我不是 python 专家

在 python 中,模块中定义的变量默认是模块变量,因此对于该模块是全局的。在 Ruby 中,当您定义一个小写变量时,它始终是一个局部变量。局部变量只能在定义它们的块中以及在包装变量的块中定义的 procs/lambdas 中访问。

在 Ruby 中,对于跨范围的变量,它需要是:

  • 常量 (ALL_CAPS):如果前缀正确,则始终可访问
  • 类变量 (@@double_at):始终可以从定义类和任何子类访问,但不能从外部访问
  • 实例变量 (@single_at):只能从该对象内部访问,并且可以从外部使用 getter 方法/get_instance_variable
  • 全球 ($starts_with_dollar):一个坏主意。跨越所有范围,不需要范围。请勿使用!

【讨论】:

  • 啊,我明白了,所以对于 Python,当您在任何类或块之外定义变量时,默认情况下它将在全局范围内。这与 Ruby 形成鲜明对比,其中 Ruby 将每个作用域视为其自己的单独实体,并且您可以通过使用 $ 定义在所有作用域内可访问的全局变量。这是一个准确的总结吗?
  • @WillsonMock:差不多。
  • 次要的 nitpick:常量不是 ALL_CAPS,它们只是以大写字母开头。例如,类名是常量。
  • @steenslag:没错,但除非你定义一个类或模块,否则最好使用 ALL_CAPS。
【解决方案2】:

在 Ruby 中,如果您想访问在您正在调用的方法之外定义的变量,您需要将其定义为全局变量。 Ruby 尝试匹配本地范围内定义的变量,如果没有找到,则抛出异常。

您可以使用$ 符号定义一个全局变量。

$a = 5
def myfunc
  puts $a
end

myfunc

但是,作为一般规则,定义全局变量并不是一个好习惯,否则会冒着污染全局命名空间的风险。

【讨论】:

    【解决方案3】:

    您可以使用dis 模块来查看 Python 正在做什么。

    import dis
    
    a = 5
    def myfunc():
      print a
    

    结果:

    >>> dis.dis(myfunc)
     15           0 LOAD_GLOBAL              0 (a)
                  3 PRINT_ITEM          
                  4 PRINT_NEWLINE       
                  5 LOAD_CONST               0 (None)
                  8 RETURN_VALUE
    

    所以你可以看到a在全局范围内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多