Python メモ – __init__() と self
クラスに定義されている__init__()はインスタンス生成時に呼び出される。
例えば次のコードだと、Personクラスのインスタンス生成時に引数としてYamadaを渡すと、nameにYamadaがセットされて、p.nameで名前を参照できる。厳密には、インスタンス生成時に__new__()が呼ばれて、__new__()が__init__()を呼び出しているらしい。
>>> class Person:
... def __init__(self, name):
... self.name = name
...
>>> p = Person('Yamada')
>>>
>>> p.name
'Yamada'
ここで疑問が出てくる。Person('Yamada')のように、引数は1つしか渡していない。しかし、__init__(self, name)と引数は2つになっている。それは何故か?このselfとは何なのか。
実は内部の処理では、__new__(インスタンス生成するクラス, インスタンス生成時に渡した引数)でインスタンスを生成して、生成されたインスタンスがselfになる。そして、__new__()が__init(self, name)__を呼び出している。
上の例だと、__new__(Person, 'Yamada')が__init__(self, 'Yamada')を呼び出し、self.nameに'Yamada'をセットしている。
Pythonでは__init__()だけでなく、クラスに定義するメソッドの第一引数にはselfが必須である。
例えば、次の例だとget_name_wit_titleでselfを定義している。これによりインスタンス生成時に設定したself.nameを参照できる
>>> class Person:
... def __init__(self, name):
... self.name = name
...
... def get_name_with_title(self):
... return 'Mr. ' + self.name
...
>>> p = Person('Yamada')
>>> p.get_name_with_title()
'Mr. Yamada'
引数が不要なメソッドであればselfは不要に思えるが、指定しないとエラーになる。
>>> class Person:
... def __init__(self, name):
... self.name = name
...
... def hello():
... return 'Hello!'
...
>>> p = Person('Yamada')
>>> p.hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() takes 0 positional arguments but 1 was given
不要でもselfを指定しましょう。
>>> class Person:
... def __init__(self, name):
... self.name = name
...
... def hello(self):
... return 'Hello!'
...
>>>
>>> p = Person('Yamada')
>>> p.hello()
'Hello!'
実は、selfは別の名前でも問題ないが、慣習としてselfを使うことになっているので、selfを指定しましょう。
参考情報
https://docs.python.org/ja/3/reference/datamodel.html#object.__new__