pythonで辞書に構造体っぽくアクセスするメモ¶
(2009/3/24 追記)
あるライブラリの関数で引数objに、obj.yearとかobj.monthとかでアクセスする関数があって、テスト用にこのobjをでっち上げる必要が出てきました。素直に書くと
class MockData:
year = 2000
month = 1
obj = MockData()
というふうに書かないといけないのですが、このMockを使うのはunittestの中なので、以下のようにして使いたいと思いました。
obj = {'year':2000, 'month':1}
ということで、これを実現するために以下のようなクラスを用意してみました。
class DictMapper(dict):
def __getattr__(self, name):
try:
attr = super(DictMapper, self).__getattr__(name)
except:
if not self.has_key(name):
raise AttributeError,name
attr = self.get(name)
return attr
obj = DictMapper({'year':2000, 'month':1})
激しく既出の予感。あともっと簡単な方法がありそうな予感。
2009/3/24 追記
今日,使いたくなって DictWrapper で検索して見つからなかったので、 DictWrapper でも検索されるようにコメントしておく。
それはそれとして手元に__setattr__してる版が見つかった。あと__getattr__で辞書に無い値にアクセスしたときにNoneを返しているあたりRubyっぽい感じで緩い。__getattr__は属性値があればメソッド呼び出されないので、上記エントリに書いていたsuper(...)は不要だった。
class DictMapper(dict):
def __getattr__(self, name):
if name in self:
return self[name]
def __setattr__(self, name, value):
self[name] = value
In [1]: obj = DictMapper({'year':2000, 'month':1})
In [2]: obj.keys()
Out[2]: ['year', 'month']
In [3]: obj.keys
Out[3]: <built-in method keys of DictMapper object at 0x02444A48>
In [4]: obj.keys = 1
In [5]: obj.keys
Out[5]: 1