7

I've been learning Ruby and Python concurrently and one of the things I noticed is that these 2 languages seem to treat scope differently. Here's an example of what I mean:

# 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"

It appears that def block can access variables declared outside of its immediate scope in Python but not in Ruby. Can someone confirm whether my understanding is correct? And if so, whether one of these ways of thinking of scope is more common in programming?

Paolo
  • 20,112
  • 21
  • 72
  • 113
wmock
  • 5,382
  • 4
  • 40
  • 62
  • For the Python side, you're right (there's obviously more to scoping, but your phrasing does not contradict any of it). –  Feb 23 '13 at 16:24
  • Possible Python answer here: http://stackoverflow.com/questions/370357/python-variable-scope-question – Todd A. Jacobs Feb 23 '13 at 16:27

3 Answers3

5

Disclaimer: I'm no python expert

In python, where variables defined in a module are, by default, module variables and as such global to that module. In Ruby, when you define a lowercase variable, it is always a local variable. Local variables are only accessible in the block that defined them and in procs/lambdas defined in that block that wrap the variable.

In Ruby, for a variable to cross scopes, it needs to be either:

  • A constant (ALL_CAPS): Always accessible, if prefixed with the right scope
  • Class variable (@@double_at): Always accessible from the defining class and any subclasses, but not from outside
  • Instance variable (@single_at): Accessible only from within that object, and from outside with getter methods/get_instance_variable.
  • Global ($starts_with_dollar): A bad idea. Crosses all scopes, no scoping needed. Do not use!
Linuxios
  • 34,849
  • 13
  • 91
  • 116
  • Ah I see, so for Python, when you define a variable outside of any class or block, by default it will be in the global scope. This contrasts with Ruby where Ruby treats each scope as its own separate entity and you define global variables accessible within all scopes via using $. Is that an accurate summary? – wmock Feb 23 '13 at 17:30
  • @WillsonMock: Pretty much. – Linuxios Feb 23 '13 at 19:04
  • 2
    Minor nitpick: constants are not ALL_CAPS, they just start with a capitalized letter. Classnames for instance are constants. – steenslag Feb 23 '13 at 20:34
  • @steenslag: True, but unless you're defining a class or module, it's good form to use ALL_CAPS. – Linuxios Feb 23 '13 at 21:32
1

In Ruby if you want to access a variable defined outside the method you are invoking you need to define it as global. Ruby try to match the variable defined in the local scope, if does not find it, throw an exception.

You can define a global variable with $ sign.

$a = 5
def myfunc
  puts $a
end

myfunc

However as a general rule is not a good practice to define global variables otherwise will risk to pollute the global namespace.

Endre Simo
  • 11,330
  • 2
  • 40
  • 49
1

You can use dis module to see what Python is doing.

import dis

a = 5
def myfunc():
  print a

Result:

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

So you can see that a is in the global scope.

Akavall
  • 82,592
  • 51
  • 207
  • 251