Difference between Ruby and Python in terms of variables

Local variable scope

In ruby, local variable references are only within the defined scope.

ruby


a = 1

def func
  puts a
end

func #=> error (undefined local variable)

In python it can also be referenced from the offspring scope.

python


a = 1

def func():
  print(a)

func() #=> 1

Furthermore, even if the defined scope disappears, the local variable will not be deleted as long as it is referenced from the offspring scope. You can also apply this property to create something like a class with instance variables. This class-like instance method-like is called a closure.

python


def cls(): #Class-like
  x = {} #Instance variable-like

  def a(): #Closure
    x['a'] = 1

  def b(): #Closure
    x['b'] = 1

  def g(): #Closure
    return x

  return a, b, g

#The scope of x disappears when the function call ends
a, b, g = cls()
a(); b();
print(g()) #=> {'a': 1, 'b': 1}

Constant closure

Even with ruby, if it is a constant, there is a closure. Before giving an example, let me explain a little about ruby.

In ruby, constants and variables are managed in completely different ways. The scope of variables changes depending on the function definition (not including do syntax etc.) and class definition. On the other hand, the scope of constants changes only in module definitions (including class definitions). And the search for constants

If a nest exists, this constant is searched sequentially within the elements of that nest. (From Automatic loading and reloading of constants)

It is done like this (however, in the case of open class, it is not searched). That is, the constant can also be referenced from the offspring scope.

You can use this property to make closures.

ruby


module A
  X = 'x' #Instance variable-like

  module B #Class-like
    def show #Closure
      puts X
    end
  end
end

class C #Instance-like
  extend A::B
end

C.show #=> x

Instance methods that look like local variables

A reference to a local variable whose definition is missing may actually be an instance method call with no arguments. I meet really often.

ruby


class C
  def hoge #Instance method
    return "hoge"
  end

  def show
    fuga = "fuga"

    puts hoge #Instance method call
    puts fuga #Local variable reference
  end
end

In addition, the class macros attr_accessor, attr_reader, and attr_writer make it easy to create instance methods that look like local variables. The substance of the variable is an instance variable whose name is prefixed with @ in the argument symbol.

ruby


class C
  attr_accessor :hoge #Instance variables@hoge is an entity

  def initialize
    self.hoge = "hoge" #Instance method hoge=Call
  end

  def show
    fuga = "fuga" #Define local variable fuga&Initialization

    puts hoge #Call instance method hoge
    puts fuga #See local variable fuga
  end
end

C.new.methods.include?(:hoge) #=> true
C.new.methods.include?(:hoge=) #=> true

In the case of python, it is easy to distinguish because the instance method call has self attached and the parentheses of the function call cannot be omitted. Instead, it's harder to distinguish between instance method calls and class method calls.

python


class C:
  def hoge(self):
    return "hoge"

  @classmethod
  def piyo(cls):
    return "piyo"

  def show(self):
    fuga = "fuga"

    print(self.hoge()) #Instance method call
    print(fuga) #Local variable reference

    print(self.piyo()) #Class method call

Overwrite with local variables

(Added based on comments from scivola)

When calling the instance method hoge = in the previous example, we specified self as the receiver.

ruby (repost)


class C
  attr_accessor :hoge

  def initialize
    self.hoge = "hoge" #here
  end
  ...

This is because if self is not specified, it will be treated as the definition of the local variable hoge.

ruby


class C
  attr_accessor :hoge

  def initialize
    hoge = "hoge" #Definition of local variable hoge
  end

  def show
    puts hoge
  end
end

C.new.show #=> nil

The same can happen with python. For example, in the case of the class-like introduced earlier, the instance variable-like cannot be updated.

python


def cls():
  x = {} #Behave like an instance variable

  def u():
    x = 'updated' #Actually, the definition of the local variable x

  def g():
    return x

  return u, g

#The scope of x disappears when the function call ends
u, g = cls()
u();
print(g()) #=> {}

You can't omit self in python, so you won't make a mistake when updating instance variables.

python


class C:
  def __init__(self):
    self.hoge = "not updated"

  def wrong(self):
    hoge = "updated" #Easy to notice mistakes

  def correct(self):
    self.hoge = "updated"

  def show(self):
    #print(hoge) #=> error (name 'hoge' is not defined)
    print(self.hoge)

c = C()
c.wrong(); c.show(); #=> not updated
c.correct(); c.show(); #=> updated

Refer to the instance variable to include

ruby


module M
  def show
    puts @message
  end
end

class C
  include M
  def initialize
    @message = "accessible"
  end
end

C.new.show #=> accessible

You can do something similar with python.

python


class S:
  def show(self):
    print(self.message)

class C(S):
  def __init__(self):
    self.message = "accessible"

C().show() #=> accessible

Assign a function to a variable

In ruby, you can omit the parentheses of the function call. Therefore, you cannot assign a function to a variable.

ruby


def func
  return "called"
end

a = func #Calling the function func
puts a #=> called

Object # method You can use an instance method to convert a function to a Method object and assign it to a variable.

ruby


def func
  return "called"
end

a = method(:func) #Method object assignment
puts a #=> #<Method: main.func>
puts a.call #=> called

On the other hand, in python you can assign a function to a variable.

python


def func():
  return "called"

a = func #Substitution of function func
print(func) #=> <function func at 0x...>

Recommended Posts

Difference between Ruby and Python in terms of variables
[python] Difference between variables and self. Variables in class
Difference between Ruby and Python split
Difference between list () and [] in Python
Difference between == and is in python
Differences between Ruby and Python in scope
difference between statements (statements) and expressions (expressions) in Python
Difference between @classmethod and @staticmethod in Python
Difference between append and + = in Python list
Difference between nonlocal and global in Python
Difference in how to write if statement between ruby ​​and python
About the difference between "==" and "is" in python
[python] Calculation of months and years of difference in datetime
Difference between return, return None, and no return description in Python
Difference in writing method to read external source code between Ruby and Python
Difference between python2 series and python3 series dict.keys ()
[Python] Difference between function and method
Python --Difference between exec and eval
[Python] Difference between randrange () and randint ()
[Python] Difference between sorted and sorted (Colaboratory)
Python module num2words Difference in behavior between English and Russian
List concatenation method in python, difference between list.extend () and β€œ+” operator
Reference order of class variables and instance variables in "self. Class variables" in Python
[Python] Strengths and weaknesses of DataFrame in terms of time required
Differences in authenticity between Python and JavaScript
Big difference in ruby, python, httpd performance
Differences in syntax between Python and Java
Difference between PHP and Python finally and exit
[Python] Difference between class method and static method
[Python Iroha] Difference between List and Tuple
[python] Difference between rand and randn output
Transcendental simple and clear! !! Difference between single quotes and double quotes in Python
Differences in multithreading between Python and Jython
File open function in Python3 (difference between open and codecs.open and speed comparison)
Differences between Ruby and Python (basic syntax)
Project Euler # 1 "Multiples of 3 and 5" in Python
Correspondence summary of array operation of ruby and python
The answer of "1/2" is different between python2 and 3
Specifying the range of ruby and python arrays
[Python] Chapter 02-01 Basics of Python programs (operations and variables)
Practice applying functions and global variables in Python
Project Euler # 6 "Difference in sum of squares" in Python
About shallow and deep copies of Python / Ruby
Explanation of edit distance and implementation in Python
Comparison of Python and Ruby (Environment / Grammar / Literal)
Ruby, Python and map
Python and Ruby split
Differences in string processing between Python, Ruby, JS, PHP (combination and variable expansion)
I compared the speed of regular expressions in Ruby, Python, and Perl (2013 version)
Divides the character string by the specified number of characters. In Ruby and Python.
"Linear regression" and "Probabilistic version of linear regression" in Python "Bayesian linear regression"
Full-width and half-width processing of CSV data in Python
Calculation of standard deviation and correlation coefficient in Python
AtCoder ARC080 D simulation solved in Ruby and Python
[Ruby vs Python] Benchmark comparison between Rails and Flask
Indent behavior of json.dumps is different between python2 and python3
Ruby, Python code fragment execution of selection in Emacs
Mutual conversion between JSON and YAML / TOML in Python
Interprocess communication between Ruby and Python (POSIX message queue)
Overview of generalized linear models and implementation in Python
Compare "relationship between log and infinity" in Gauche (0.9.4) and Python (3.5.1)