理由はそのうち考える

まずやってみよう

Python学習メモ:特殊メソッド

gihyo.jp

特殊メソッド

特殊メソッドとは、Pythonが暗黙的に呼び出す特別なメソッド。メソッド名の前後にアンダースコア2つが付いているのが特徴。例として、組み込み関数len()は引数に渡したオブジェクトの特殊メソッド__len__()を暗黙的に利用する。

class A:
    def __len__(self):
        return 5

a = A()
len(a) # 5

特殊メソッドの例

__str__()、__repr__()

どちらもオブジェクトを文字列で表現する特殊メソッドだが用途が異なる。__repr__()はデバッグなどに役立つ情報を提供するために利用される特殊メソッド。対話モードでオブジェクト名のみを入力した際にも__repr__()が呼ばれる。__str__()は、組み込み関数のprint()やstr()、f’{}’などで利用される文字列を返す特殊メソッド。このとき__str__()が実装されていない場合は__repr__()が呼ばれる。

__bool__()

Pythonではすべてのオブジェクトが真理値評価でき、偽となるオブジェクト以外は全て真となる。ユーザー定義のクラスやインスタンスはデフォルトで真と評価されるが、これを実装するとその判定処理を変更することができる。なお真理値評価に影響する特殊メソッドは__bool__()のみではなく、__len__()も該当し、__len__()が0を返すとそのオブジェクトは偽となる。

__call__()

これを実装したクラスでは、インスタンスを関数のように呼び出すことができる。インスタンス名()とすれば、__call__()で定義された処理が実行される。

__setattr__()

__setattr__()は属性への代入で呼ばれる特殊メソッド。__setattr__()を利用して特定の条件下でしか実行されないように制限するなどできる。なお__setattr__()内で属性への代入をすると再帰的に__setattr__()が呼ばれることになりRecursionErrorとなる。このため、__setattr__()内で自分自身に属性を追加する際は、必ず組み込み関数super()を使って基底クラスの__setattr__()を呼び出す。

__delattr__()

属性の削除時に呼び出される以外は__setattr__()と同じ。

__getattr__()、__getattribute__()

__getattr__()は属性辞書(__dict__)に存在しなかった際に呼ばれ、__getattribute__()はすべての属性アクセスで呼び出される。これらの特殊メソッドを使用すると、実際にはインスタンスが持っていない属性でもあたかもその属性をもっているかのようなふるまいを定義することができる。

__iter__()、__next__()

for i in x と書いたとき、for文はxの__iter__()を呼び出し、その戻り値を利用する。この戻り値はイテレータと呼ばれ、__iter__()と__next__()が実装されている。__next__()はループのたびに呼ばれ、for i in x のiに渡される。__next__()で返す値がなくなった際にはStopIterationを送出してループを終了させる。なおPythonにはイテラブルオブジェクトという言葉がよく出てくるが、イテラブルと イテレータは異なる概念なので注意。

  • イテラブル:for文や内包表記で使えるオブジェクト
    __iter__()を実装したオブジェクト
    __iter__()の戻り値は任意のイテレータ
  • イテレータ
    __iter__()と__next__()を実装したオブジェクト
    __iter__()の戻り値は自分自身(self)
その他の特殊メソッド

その他の特殊メソッドは 3. データモデル — Python 3.9.0 ドキュメント を参照。

特殊メソッドは暗黙的に呼ばれ、標準的な動作をフックして自分が意図した動作に変更することができるので上手く使えば非常に強力な機能だが、反面上手く使えないとその強力さゆえに危険なものにもなり得るように思う。しっかりとした知識と理解がないと使いこなすのは難しそう。