BlankTar

about | blog | works | photo

昨日の__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みたいな記述。無限ループするからね。
< pythonには__getattr__の他に__getattribute__なんてものがあるらしい。 pythonのベンチマーク用モジュールtimeitの使い方と落とし穴。 >