質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

2回答

35648閲覧

python3 「self」とは何なのでしょうか?

nnahito

総合スコア2004

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

3グッド

8クリップ

投稿2017/12/29 02:34

環境

Python3.6.3

前提

オブジェクト指向は得意ではありません。
Pythonも今まで手続き型で書いておりました。

質問

Pythonのメソッドで渡す「self」とは何なのでしょうか?

手続き型で書いていたときも、tkinterのマウスアクションで呼び出されるメソッドにも、メソッドの引数にselfを書いていました。書かないとエラーも出ますし……
なのでおまじない的に書いておりました。

しかし、最近業務でもPythonを使い始め、オブジェクト指向型でコードを書いているのですが、
このselfの意味がわからずモヤモヤし始め、質問させていただいております。

ちょいちょい調べていると、どうもプロパティなどにアクセスするときに使うもの……のようにも見えますが……

ご存知の方がいらっしゃいましたら、ご教示いただけますと幸いです。

razerot, namnium1125👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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の正体ですがただのメソッドの仮引数です。それ以上でもそれ以下でもありません。他のnameageと言った仮引数と同等の価値しかありません。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)

全く同じように動作します。クラス定義にあるメソッドの定義と引数が合うようになりましたので、taroselfの実引数として呼び出されているのがわかると思います。

では__init__はどうなのかというと、これもオブジェクト生成というコードにはあらわれない処理をしてから、Person.__init__(生成したオブジェクト, 18)を呼び出して、最後に生成したオブジェクトを返しているだけになります。


どうですか?わかりましたか?もっと詳しく知りたいのであれば、下記も参考になるでしょう。
参考: クラス — Python 3 ドキュメント
今はよくわからなくて、selfはメソッドを呼びだしたインスタンスオブジェクト自身と思っていても大丈夫です。ですが、深いところを知っておくことは悪いことではありません。時が経ってからでも良いので、読み返してみてください。

投稿2017/12/29 04:04

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

Udomomo

総合スコア1524

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2017/12/29 03:07

ご回答ありがとうございます。 なるほど、PHPでいう「public」と「private」の設定を、メソッドの引数にselfを渡すか渡さないかで決定すている感じですね。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問