pythonの__setattr__をオーバーライドしてみたら楽しいかもしれない。

昨日の__getattr__に引き続いてメタプログラミングシリーズですよ。 調子に乗るとグチャグチャになるのでほどほどに。

getattr関数と並び立つ(?)のがsetattr関数。 その名の通り、クラスインスタンスに値をセットできます。

値じゃなくて関数もセット出来るのだけれど、バインドされないのでちょっと面倒臭い。 バインドされないと何が起こるかというと、instance.method()って呼び出し方をしてもselfが渡されないので、selfが必要ならinstance.method(instance)ってやらないとになっちゃう。

まあそんな事はともかくだ。 setattr(a, 'key', value)とすると、内部的にはa.__setattr__('key', value)みたいに処理されているらしい。 しかも、a.key = valueとした場合も__setattr__が呼ばれているみたい。

この__setattr__ってやつも普通に上書きできるので、

>>> class Test(object):
... 	def __setattr__(self, key, value):
... 		print key, '<=', value
...
>>> a = Test()
>>> a.test = 123
test <= 123
>>> a.test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute 'test'

代入できないクラス的な事ができる。どうでもいいね。

何かしら処理をした上で代入したい場合は

>>> class Double(object):
... 	def __setattr__(self, key, value):
... 		object.__setattr__(self, key, value*2)
...
>>> a = Test()
>>> a.one = 1
>>> a.one
2
>>> a.two = 2
>>> a.two
4

みたいな感じになります。入れた値が倍になる謎クラス。

当然普通の関数として書けるので、かなり自由っぽい。 ただ気をつけなきゃいけないのは、self.var = valueみたいな記述。無限ループするからね。