環境
Python3.6.3
前提
オブジェクト指向は得意ではありません。
Pythonも今まで手続き型で書いておりました。
質問
Pythonのメソッドで渡す「self
」とは何なのでしょうか?
手続き型で書いていたときも、tkinterのマウスアクションで呼び出されるメソッドにも、メソッドの引数にself
を書いていました。書かないとエラーも出ますし……
なのでおまじない的に書いておりました。
しかし、最近業務でもPythonを使い始め、オブジェクト指向型でコードを書いているのですが、
このself
の意味がわからずモヤモヤし始め、質問させていただいております。
ちょいちょい調べていると、どうもプロパティなどにアクセスするときに使うもの……のようにも見えますが……
ご存知の方がいらっしゃいましたら、ご教示いただけますと幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
少し深い話をします。今はわからなくても、大丈夫ですので、読み物程度でお読みください。
self
を「インスタンスメソッドにおけるレシーバーのインスタンスオブジェクト自身」と思っていてもほとんどの場合は問題はありませんが、Pythonの文法上はそのコードは偶々そうなっているにすぎないという話です。
まずは、サンプルコードを作りましょう。
Python
1class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def overAge(self, age): 7 return self.age >= age 8 9 def say(self): 10 print('私の名前は%sです。' % self.name) 11 12taro = Person('太郎', 18) 13taro.say() 14if taro.overAge(20): 15 print('%sは成年です。' % taro.name) 16else: 17 print('%sは未成年です。' % taro.name)
さて、上のコードでのself
の正体ですがただのメソッドの仮引数です。それ以上でもそれ以下でもありません。他のname
やage
と言った仮引数と同等の価値しかありません。self
と付けているのは単に慣習やコーディング規約であり、hoge
と名付けても正常に動きます。
Python
1class Person: 2 def __init__(hoge, name, age): 3 hoge.name = name 4 hoge.age = age 5 6 def overAge(hoge, age): 7 return hoge.age >= age 8 9 def say(hoge): 10 print('私の名前は%sです。' % hoge.name) 11 12taro = Person('太郎', 18) 13taro.say() 14if taro.overAge(20): 15 print('%sは成年です。' % taro.name) 16else: 17 print('%sは未成年です。' % taro.name)
ましてや、メソッド同士で同じ名前にする必要すらありません。
Python
1class Person: 2 def __init__(foo, name, age): 3 foo.name = name 4 foo.age = age 5 6 def overAge(bar, age): 7 return bar.age >= age 8 9 def say(baz): 10 print('私の名前は%sです。' % baz.name) 11 12taro = Person('太郎', 18) 13taro.say() 14if taro.overAge(20): 15 print('%sは成年です。' % taro.name) 16else: 17 print('%sは未成年です。' % taro.name)
上の三つのコードは全て同じ動作になりますし、同じ結果になります。self
はそのオブジェクト自身と教わったはずなのに、self
じゃなくてもいいなんて、ますますわからなくなりましたね。それを理解するには、メソッド呼出しの仕組みを知る必要があります。
Pythonの素晴らしいところは、インスタンスメソッドとクラスメソッドの区別が無い事です。もっと言うと全てクラスメソッドです。インスタンスメソッド呼出しだと思っていたものは、第一引数に自分自身を入れてクラスメソッドを呼び出しているに過ぎません。
説明は以上ですが、もうちょっと詳しく見ましょう。オブジェクト指向のメソッド呼出しは「レシーバー」と「メソッド」と「引数」の組合せです。
レシーバー . メソッド ( 引数... )
こんな感じが基本形であり、Pythonも同じです。でもここからがPythonの素晴らしいところです。Pythonでこのようなコードを書いた場合、次のように解釈されます。
レシーバーのクラス . メソッド ( レシーバー, 引数... )
そうです。クラスメソッドの呼出しになっているのです。上のコードの後半をクラスメソッドを呼び出す形で書き直すと次のようになります。
Python
1taro = Person('太郎', 18) 2Person.say(taro) 3if Person.overAge(taro, 20): 4 print('%sは成年です。' % taro.name) 5else: 6 print('%sは未成年です。' % taro.name)
全く同じように動作します。クラス定義にあるメソッドの定義と引数が合うようになりましたので、taro
がself
の実引数として呼び出されているのがわかると思います。
では__init__
はどうなのかというと、これもオブジェクト生成というコードにはあらわれない処理をしてから、Person.__init__(生成したオブジェクト, 18)
を呼び出して、最後に生成したオブジェクトを返しているだけになります。
どうですか?わかりましたか?もっと詳しく知りたいのであれば、下記も参考になるでしょう。
参考: クラス — Python 3 ドキュメント
今はよくわからなくて、self
はメソッドを呼びだしたインスタンスオブジェクト自身と思っていても大丈夫です。ですが、深いところを知っておくことは悪いことではありません。時が経ってからでも良いので、読み返してみてください。
投稿2017/12/29 04:04
総合スコア21739
0
ベストアンサー
self
は名前のとおり、インスタンス自身のことです。クラスから作られたインスタンス自体を指します。
例えば以下のようなクラスの場合、
python
1class Cat: 2 def __init__(self, color): 3 self.color = color 4 5 def walk(self): 6 return "A " + self.color + " cat is walking"
self.color = color
の部分で、インスタンスに紐づく変数(インスタンス変数)としてcolor
を定義しています。=
の右側にあるcolor
は引数として渡してきた値です。
こうすることで、
python
1jack = Cat("black") 2print(jack.color) # black
というように、クラスの外側で作ったインスタンスからアクセスできます。
もし左側のself.color
を単にcolor
としてしまうと、それはその関数の中でしか使えないローカル変数になってしまいます。そのため、外からアクセスすることができません。
また、メソッドの第一引数にself
が入っているのも、メソッド内でインスタンス変数にアクセスするために、インスタンスを指定する必要があるからです。
上の例では、walk
メソッドの引数にself
を指定し忘れると、self.color
を取り出すことができません。
投稿2017/12/29 03:01
総合スコア1524
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。