Skip to main content

Python メモ – __init__() と self

クラスに定義されている__init__()はインスタンス生成時に呼び出される。 例えば次のコードだと、Personクラスのインスタンス生成時に引数としてYamadaを渡すと、nameYamadaがセットされて、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_titleselfを定義している。これによりインスタンス生成時に設定した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__