ASPN : Python Cookbook : Semi-automatic resource management with AutoClose
"Python does not make any guarantee at all about *when* the destructor will be called."というわけで、__del__に書いたコードが想定どおりに動かないケースが紹介されている。
で終了時に確実にインスタンスの後かたづけをするためのレシピ。AutoCloseクラスを継承したクラスを作ってcloseメソッドを実装しておくと、Pythonが終了する時にAutoCloseのクラスメソッドcloseallが呼び出されて、生成した全てのインスタンスのcloseメソッドが実行される。
調べたこと。
- typeを継承
- __metaclass__属性
- __new__メソッド
- __call__メソッド
- __subclasses__メソッド
- atexitモジュール
typeを継承/__metaclass__属性
typeはメタクラス。(=クラス・オブジェクトを生成するクラス。)
静的なクラス定義がなくても動的にクラスを生成することができる。
用例としては、生成するインスタンスを状況に応じて違うクラスのインスタンスにしたり。
使い方は、typeを継承したクラスを別のクラスの__metaclass__属性に入れておく。
__new__メソッド
objectクラスのスタティックメソッド。
__init__はインスタンスが生成された時に呼ばれるが、__new__は生成しよっかなーという時に呼ばれる。
親クラスの__new__を自分で呼び出してやる必要がある。
__new__が結果インスタンスを返すと、それがそのまま__init__に渡る。
コード添削道場のシングルトンの問題で出てた。
サンプルで、AutoCloseMetaの__new__はCやDのクラス宣言時に呼ばれてる。AutoCloseクラスオブジェクトを作るのに必要だから。
mcl._instances.append(cls)は後で使ってる様子がないが何のためだろう。コメントアウトしてもうまく動く。
__call__メソッド
インスタンスを関数みたいに書ける。つまりinstance.__call__(args)の代わりにinstance(args)とできる。
リファレンスによるとそれだけのものだが、メタクラスのメソッドとして定義しておくとインスタンス生成時のコンストラクタ直前に処理を挟めるみたい。
AutoCloseMetaの__call__はCやDの__init__の直前に呼ばれて、後かたづけリストにインスタンスを登録している。
__subclasses__メソッド
ドキュメントが見つからないが、typeクラスのメソッドでサブクラスを全て取得するものらしい。