PythonとRubyにおけるself.変数の違い
はじめに
私はPython→Rubyの順に勉強し始めたのですが、インスタンス変数の表記の違いに戸惑ったことがあり、記事にしました。
Pythonではインスタンス変数をself.var
のように書きますが、Rubyでは@var
のように書くことができます。例えば下記は同じ内容のコードで、いずれも"Hello, Taro!"と出力されます。
# Python
class User:
def __init__(self, name):
self.name = name
def hello(self):
print(f'Hello, {self.name}!')
user = User('Taro')
user.hello()
# Ruby
class User
def initialize(name)
@name = name
end
def hello
puts "Hello, #{@name}!"
end
end
user = User.new("Taro")
user.hello
ところが、Rubyでも(Pythonに似た)self.var
のような表記を目にすることがあったため、そのような表記が可能になる条件を調べてみました。
Rubyでself.変数を使ってみる
さっそく初期化メソッドでself.name
に代入しようとしたところ、エラーが出ました。
class User
def initialize(name)
self.name = name
end
def hello
puts "Hello, #{self.name}!"
end
end
user = User.new("Taro")
user.hello
# => in `initialize': undefined method `name=' for #<User:0x000014db28437548> (NoMethodError)
エラー内容を読むと、self.name
に代入しようとすると内部的にはインスタンス変数name
に対応したセッターメソッドを呼んでいることが推察されます。今回はセッターメソッドを定義していないのでエラーが出たようです。
次にセッターメソッドを設定してみると[1]、初期化メソッドの箇所ではエラーが出なくなりました。
class User
def initialize(name)
self.name = name
end
def hello
puts "Hello, #{self.name}!"
end
# セッターメソッド
def name=(name)
@name = name
end
end
user = User.new("Taro")
user.hello
# => in `hello': undefined method `name' for #<User:0x00001544c1297398 @name="Taro"> (NoMethodError)
今度はhelloメソッド内でエラーが出ていますが、これもインスタンス変数name
に対応した(未定義の)ゲッターメソッドを呼んでいるためのようです。
最後にゲッターメソッドも追加すると[2]、エラーが全く出なくなりました。
class User
def initialize(name)
self.name = name
end
def hello
puts "Hello, #{self.name}!"
end
# セッターメソッド
def name=(name)
@name = name
end
# ゲッターメソッド
def name
@name
end
end
user = User.new('Taro')
user.hello()
# => Hello, Taro!
以上の検証結果から、クラス内部でself.var
のような表記で読み書きしようとすると、対応するインスタンス変数のゲッター/セッターメソッドが呼ばれ、存在しない時にはエラーが出るらしいということが分かりました。
Rubyでは、クラス外部からインスタンス変数を(インスタンス名.var
のような表記で)読み書きしようとすると、ゲッター/セッターメソッドが呼ばれます。クラス内においても同じような挙動になると言えそうです。
まとめ
- インスタンス変数はPythonだと
self.var
、Rubyでは@var
のように表記する - Rubyで
self.var
のような表記を使って読み書きするには、対応するインスタンス変数についてのゲッター/セッターメソッドが必要
この記事が同じような疑問を覚えた方に役立てば嬉しいです。
Discussion