はじめに
この記事では、pythonのselfについてまとめていきます。
自分の中でselfへの理解が曖昧だったので、記事を書くことにしました。
まず、初めにクラスとインスタンスから説明していきます。
クラスとはオブジェクトの処理を一つにまとめたものです。よく金型とか設計図みたいな表現がされます。 インスタンスはクラスの実体化を意味します。 Aの設計図からAを作り出すことです。
では、実際のPythonのソースコードでこの挙動を見ていきましょう。
class Student:
def __init__(self, name):
self.name = name
def hello(self):
print(self.name)
exe = Student("山田太郎")
exe.hello()
exe=Student("山田太郎")の部分でインスタンスを生成しています。
def __init__(self, name):
self.name = name
このdef__init__()は特殊な関数でクラスを呼び出した時に最初に呼ばれる関数。
イニシャライザとも呼ばれてたりします。
処理の流れとしては、exe=Student("山田太郎")でインスタンスを生成→イニシャライザが呼び出される流れです。
selfって何?
それではこの記事の主題であるselfについて書いていきます。
selfとは、インスタンス自身。
selfは慣例的にselfとなっているだけで、実はここの名前は指定がない。
ただ、selfにしておいた方が無難。
class Student:
def __init__(self, name):
self.name = name
def hello(self):
print(self.name)
exe = Student("山田太郎")
exe.hello()
exe = Student("山田太郎")
イニシャライザにはselfとnameの二種類があるが、インスタンスの生成時に引数が1つなのはselfがインスタンス自身のため。
インスタンスそのものを引数として渡す必要がないため、山田太郎だけ引数として渡せばいい。
イニシャライザにselfを使わないとどうなるの?
class Student:
def __init__(self):
name = "山田太郎"
def hello(self):
print(self.name)
exe = Student()
exe.hello()
AttributeError: 'Student' object has no attribute 'name'
先程、説明した通り、selfとはインスタンスそのものを指します。
self.nameとnameの違いとして、self.nameはインスタンスにnameという属性を追加している。
これがインスタンス変数と呼ばれるものの正体
一方の先程のコードではnameだけの指定なのでインスタンスにname属性が追加される訳ではない。
なので値が参照できないとのエラーが出力される。
インスタンスメソッドにselfを渡さないとどうなる?
def hello(self):
print(self.name)
先程のhelloメソッドはインスタンスメソッドと呼ばれるメソッドです。
インスタンスメソッドとはインスタンスを用いて使用するメソッドです。
def hello():
print("あいうえお")
つまり、引数にselfがない関数を定義すると、
TypeError: hello() takes 0 positional arguments but 1 was given
この様に引数が定義されていないとエラーが返ってきます。
インスタンスメソッド以外にもクラスメソッドやスタティックメソッドなどあり、クラスメソッドやスタティックメソッドを使う場合はデコレートする必要がある。
インスタンスメソッドの中でクラス変数を参照する時はどうする?
class Student:
hoge = "hoge"
def __init__(self, name):
self.name = name
このhogeの部分はクラス変数です。
クラスで共通して使用する変数です。
インスタンスはクラスを実体化したものなので、インスタンスからクラス変数へアクセスすることができます。
class Student:
hoge = "hoge"
def __init__(self, name):
self.name = name
def hello(self):
print(self.hoge)
exe = Student("山田太郎")
exe.hello()
なので、上のコードの様にselfからクラス変数へアクセスできます。
では、クラス変数とインスタンス変数の変数名が同じ場合はどうなるでしょうか?
class Student:
name = "hoge"
def __init__(self, name):
self.name = name
def hello(self):
print(self.name)
exe = Student("山田太郎")
exe.hello()
インスタンス変数とクラス変数が同じ場合はインスタンス変数が優先される。
なので、ここでは山田太郎が出力される。
2022/08/15 追記
あくまでインスタンス変数の属性が優先して使用されるだけであって、クラス変数の値を書き換えている訳ではない。
クラス変数はインスタンス変数によって隠蔽される。
なので、クラス変数を参照すると、hogeがそのまま出力されてくる。
ただ同名の場合はインスタンス変数が優先されてしまうので、インスタンス変数とクラス変数の名前を同じにすることは極力避けるべき。
まとめ
selfとはインスタンスそのものを表す。
インスタンスはクラスを実体化させたもの。
参考にさせて頂いた記事