#おことわり
自分自身、Python始めたてほやほやでわからないことだらけです。
(本記事も間違ってたらごめんなさい)
ほぼ自分の備忘録的な記事になります。
#はじめに
Pythonでクラスについて勉強しているとselfというものが出てくる。
けれども、おまじないのようでいまいちわからないので調べたことをまとめます。
##今回の全体のコード
class Cat():
def __init__(self,name):
self.name = name
def naku(self):
print("にゃー")
tama = Cat("タマ")
tama.naku()
Cat.naku(tama)
#本題に入る前に
Pythonでは
レシーバー.メソッド(引数…)
を、
レシーバーのクラス.メソッド(レシーバー,引数…)
として、解釈します。
なぜかは知りません。(本当にごめんなさい)
でも、どちらで書いても同じ動作をしますし、selfを理解する上では、前者を後者として解釈する、と考えたほうが理解が楽なので、そういう流れで説明します。
#本題
ひとまず、全体のコードを順を追ってみていきます。
まず、Catクラスがあります。
class Cat():
def __init__(self,name):
self.name = name
def naku(self):
print("にゃー")
インスタンス変数にnameがあって、
naku関数で「にゃー」って鳴きます。
クラスは概念みたいなものなので、「タマ」という名前で実際に召喚(インスタンス化)します。
tama = Cat("タマ")
はい、これで猫のタマちゃんが召喚されました。
次は鳴いてもらいます。
#レシーバー.メソッド(引数…)
tama.naku() #=>にゃー
はい、鳴きました。
これは、もう一つの書き方ができましたよね。
#レシーバーのクラス.メソッド(レシーバー,引数…)
Cat.naku(tama) #=>にゃー
はい、ここで見てほしいのが引数丸括弧のレシーバーの部分に「tama」が来ていることです。
そこで、もう一度クラスで定義されているnaku関数と比べてみると、
#neko関数定義
def naku(self):
#関数呼び出し
Cat.naku(tama)
引数が一致しました。これがselfの正体です。
つまり、ここでは「tama = self」ということです。
よく、「selfはインスタンス自体のこと」という説明がされてますが、ただ単純にpythonの文法上、「レシーバーのクラス.メソッド(レシーバー,引数…)」という関数の呼び出され方をするので、第一引数(レシーバー)にインスタンス自体を入れておかないと引数の数があわないからだめだよー、ということみたいです。
init関数も同じことが言えます。
ここでタマちゃん召喚時に呼び出されるinit関数の動作を考えると、
#レシーバーのクラス.メソッド(レシーバー,引数…)
Cat.__init__(tama,"タマ")
というコードが内部的に行われていると理解できます。
いやいや、Cat()の引数の「タマ」がなんでinit関数の引数になっちまってんだ!?
というのは確かに浮かぶ疑問なんですが、よくよく考えてみると、init関数は自分で定義する関数と違ってインスタンス化の時必ず呼び出される特殊なものなので、Cat()の引数にとったものが、自動的にinit関数の引数に入っているんだろうなーと僕は考えることにしてます。(知っている方がいたら教えてください。)
それにクラスは関数ではないので引数いらないですしね。
#わかったこと
- selfの正体はただの引数
- 内部的には「レシーバーのクラス.メソッド(レシーバー,引数)」で呼び出される
- 気にしなくてもなんとかなる
- 僕の書く文章は長い!!