selfとは?そして、インスタンス変数とは?
def __init__(self, word):
self.word = word
selfは、インスタンス自身を指します
self.word = word # self.インスタンス変数 = 値
そして、上記のコードではインスタンス自身(self)のwordという変数へ、引数として与えられたwordという変数を代入しています。
インスタンス変数について
インスタンス変数の特徴としては、
| 特徴 | |
|---|---|
| 1 | 生成されたインスタンスごとに別の値を持つ変数 |
| 2 | クラス内の全メソッドで使用できる |
| 3 | クラスの外からインスタンス変数へアクセスしたい場合、インスタンスを作成しなければならない |
以上のものがあります。詳しく記載します。
以下のコードは、Dogクラスから、犬種のインスタンスを作成してます
class Dog:
def __init__(self, name):
self.name = name # self.インスタンス変数 = 引数のname(ここでは"チワワ")
def bark(self):
return "吠えたのは、" + self.name # self.name:インスタンス変数へアクセス
chihuahua = Dog("チワワ")
print(chihuahua.name)
# > チワワ
print(chihuahua.bark())
# > 吠えたのは、チワワ
1. 生成されたインスタンスごとに別の値を持つ変数
chihuahua = Dog("チワワ")
print(chihuahua.name)
# > チワワ
dachshund = Dog("ダックスフンド")
print(dachshund.name)
# > ダックスフンド
引数によって、インスタンスがダックスフンドになったりします。
2. クラス内の全メソッドで使用できる
def bark(self):
return "吠えたのは、" + self.name
def bite(self):
return "噛み付いたのは、" + self.name
例ではbarkメソッドしか記載がないですが、bite(噛み付く)メソッドとかを作ってもそこでself.nameが使用できます
3. クラスの外からインスタンス変数へアクセスしたい場合、インスタンスを作成しなければならない
chihuahua = Dog("チワワ")
chihuahua.name
# インスタンス名.インスタンス変数
インスタンスを生成してアクセスしています。
そもそもな何故に、まどろっこしいselfを書くのか?
以下の記事でわかりやすく書かれているので、理解することが出来ます
簡単にまとめてみます。
selfを書く意味
結論から言うと、
オブジェクトからメソッドへアクセスした時に、引数であるオブジェクトが省略されているため、selfを記載しています
どういうことかというと、
実は、組み込み関数にヒントがあります。
組み込み関数
プログラミング言語ごとにあらかじめ用意されている関数の事です。
例えば、最初の文字列を大文字で返すcapitalize()であれば
print(str.capitalize("python"))
# > Python
引数に"python"というオブジェクトをとっています
続いてこちら、
language = "python"
print(language.capitalize())
# > Python
なんと、引数を取っていないにも関わらず期待通りの出力がされています。
なぜか?
実は、暗黙的にlanguage.capitalize(language)が実行されています
こちらがcapitalize()が定義された場所
class str(Sequence[str], _str_base):
# 省略
def capitalize(self) -> str: ...
引数には、selfをとっています。
そして、
language.capitalize(language)が見ずらいということで、引数となるオブジェクトを省略したlanguage.capitalize()でOKってことになっています
selfを書かなかった場合について考えてみる
正:コンストラクタ
class SampleClass():
def __init__(self, word):
self.word = word
sample = SampleClass("Hello World")
print(sample.word)
# > Hello World
__init__というコンストラクタが最初に実行されます
クラスの外で、sampleというインスタンスを作成して、インスタンス変数wordへアクセスしています
Hello Worldが正しく出力されています
誤:selfを抜いてみる
class SampleClass():
def __init__(word):
word = word
sample = SampleClass("Hello World")
print(sample.word)
# > TypeError: __init__() takes 1 positional argument but 2 were given
selfをそのまま取り外したコードになります
すると案の定エラーですね。
TypeError: __init__() takes 1 positional argument but 2 were given
以下の例でも確認してみましょう
正:クラスメソッド
class SampleClass():
def call(language):
print(language)
SampleClass.call("python")
# > python
こちらのコードはSampleClassというクラスから、クラスメソッドにアクセスしています
直接だと、selfがなくても問題なく出力できました
一方で、、、
誤:インスタンスを作成してアクセス
class SampleClass():
def call(language):
print(language)
language = SampleClass() # インスタンス作成
language.call("python")
# > TypeError: call() takes 1 positional argument but 2 were given
インスタンスを作成して、そこからSampleClass()クラス内のメソッドを呼び出してみると、
TypeError: call() takes 1 positional argument but 2 were given
引数は1つ欲しいのに、2つ与えられているとエラーが
これがつまり、インスタンスからアクセスしたため、
隠れたselfが与えられているということですね
参考