ASPN : Python Cookbook : Autoslots
インスタンス変数を固定する__slots__というのがある。それを自動で設定するメタクラスのレシピ。
inspectモジュールでソースコードを取ってきて構文解析させるという強引な方法をとっているようだ。
メタクラスについてはASPN : Python Cookbook : Semi-automatic resource management with AutoCloseで少し勉強した。
調べたこと。
- inspectモジュール
- compile関数
- _astモジュール
- __slots__変数
compile関数
組み込み関数。文字列をコンパイルする!
compile(string, filename, kind[, flags[, dont_inherit]])
戻り値はコードオブジェクト(_ast.Module)。
コードオブジェクトの実行はeval()で。
_astモジュール
Python2.5で導入された。Abstract Syntax Treesの略らしい。
Pythonがソースコードを構文解析した結果のツリーを扱うことができる。
Module->ClassDef->FunctionDef->...
で文まで分解できる。
その下は、代入文はAssignオブジェクトだったりprint文はPrintオブジェクトだったり。
レシピでは、Assignの場合にtarget属性を見てインスタンス変数名を取得している。
__slots__変数
クラス変数。
__slots__ = ["var1", "var2"]
のように変数名をセットすると、インスタンス変数を制限できる。objectを継承した新スタイルクラスで有効。
未定義のインスタンス変数を禁止する使い方ができるほかに、__dict__を作らないのでメモリなどのコストが少なくて済むというメリットがある。
class SlotsTest(object): __slots__ = ["var1", "var2"] def __init__(self): pass
としておくと以下のようになる。
>>> t = SlotsTest() >>> dir(t) ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__slots__', '__str__', 'var1', 'var2']
dictがないのが確認できる。
>>> t.var1 = "a" >>> t.var2 = "b" >>> t.var3 = "c" Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'SlotTest' object has no attribute 'var3'
__slots__に定義していない属性は使えなくなっている。