2009年12月25日

Descriptor:__get__とかそのあたりのスペシャルメソッド

スペシャルメソッドの__get__や__set__に注目してみる。
代入したり、されたりする場合に呼ばれる。
こいつらをオーバーライドすれば、代入時の処理を追加できるというわけ。
propertyもこれを使って実装できる。
試しに、intのみ受け取り、最大値を制限できるプロパティを作ってみた。


""" descriptor test
>>> class Sample(object):
... value = IntProperty('value', max=10)
... def __init__(self):
... self.value = 10
>>> s = Sample()
>>> s.value
10
>>> s.value = 9
>>> s.value
9
>>> s.value = 'a'
Traceback (most recent call last):
...
TypeError
>>> s.value = 11
Traceback (most recent call last):
...
ValueError: 11 is greater than 10
"""

class IntProperty(object):
def __init__(self, name='var', max=None):
self.name = name
self.max = max

def _assert(self, value):
if not isinstance(value, int):
raise TypeError

if self.max is not None and self.max < value:
raise ValueError, '%d is greater than %d' % (value, self.max)

def __get__(self, obj, objtype):
return obj.__dict__[self.name]

def __set__(self, obj, value):
self._assert(value)
obj.__dict__[self.name] = value

if __name__ == '__main__':
import doctest
doctest.testmod()


__dict__に値を入れるための名前が必要なのがいまいち><


参考:How-To Guide for Descriptors