(たぶんけっこう基本的な話)
{key1: value1,
key2: value2, ...,
subdic1: {
key_s1: value_s1,
key_s2: value_s2, ...
},
subdic2: {
sub2sub1: {
key_s2s1: value_s2s1,
}
}
のような構造の辞書をクラスで定義して簡単に生成できないかなーと思ってやってみた。
まずは1階層のクラス。
class MyData:
def __init__(self):
self.prop1 = 0
data = MyData()
print(data)
<__main__.MyData instance at 0x...>
うん、これじゃない。これを回避するには組み込み関数vars()を使うといいとのこと。
data = vars(MyData())
print(data)
{'prop1': 0}
そうそう、こういうこと。次に2階層では、
class MyData:
class MySubData:
def __init__(self):
self.subprop1 = 0
def __init__(self):
self.prop1 = 0
self.sub1 = MyData.MySubData()
data = MyData()
print(data)
{'prop1': 0, 'sub1': <__main__.MySubData instance at 0x...>}
うん、これじゃない。これを回避するには、
self.sub1 = vars(MyData.MySubData())
{'prop1': 0, 'sub1': {'subprop1': 0}}
そうそう、こういうこと。
・・・でもなんか違う。子の要素を直接設定することもできなくはないけど、なんとなくこれじゃないと誰かが叫んでいる。
教えてぐーぐる先生!ということで、
こちらの記事 (http://blog.beanz-net.jp/happy_programming/2008/11/python-5.html) が参考になった。(ありがとうございます。)
共通のメソッドは親で定義して、
class Oya:
def __str__(self):
return str(self.__dict__)
def __repr__(self):
return str(self.__dict__)
def __iter__(self):
return self.__dict__.iteritems()
def __getitem__(self, key):
return self.__dict__[key]
def __setitem__(self, key, value):
self.__dict__[key] = value
class MyData(Oya):
class MySubData(Oya):
def __init__(self):
self.subprop1 = 0
def __init__(self):
self.prop1 = 0
self.sub1 = MyData.MySubData()
data = MyData()
data.prop1 = 9
data['sub1']['subprop1'] = 99
print(data)
{'prop1': 9, 'sub1': {'subprop1': 99}}
たぶんこれでいい。
階層がどんなに深くなってもOK。プロパティには辞書的にもプロパティ的にもアクセスできる。辞書として使うときにはvars()なりで。
(追記)
と思ったんだけど、vars()で取り出した辞書でtype(data['sub1'])すると<type 'instance'>ってなっちゃうので、inner classまではうまく辞書化できていない模様。これは難しい。
暫定対処としてinner classは個別にvars()して置換してあげればなんとかならないことはない。
とりあえずinstanceとかいう意味不明なものに判定されないよう、クラスの定義時に
class Oya(object):
としておくと、typeしたときクラス名で表示されるようになるようだ。(python 2.x)
あとは再帰的にvars()するような関数を持たせる感じかなぁ。
こんな感じ。
def zenvars(obj):
dic = {}
if isinstance(obj, Oya): dic = vars(obj)
else: return dic
for i in dic:
if isinstance(dic[i], Oya):
dic[i] = zenvars(dic[i])
return dic