Pythonのdict型のようなデータの配下の特定のプロパティに、「a.b.c.d」のような表記でアクセスできると、試験ツールやチェックツールで確認したいパターンを外部から入力として与えやすくなにかと便利だと感じています。
こういった使い捨てツールなどのために、言語をかえたりしながら、アクセスDSLの関数が必要になることが一年のうち2、3回あります。
基本は再帰を使うことになり、毎度その場その場の要件や気分を表していておもしろいなと思ったのでメモってみました。
今回はこんな感じ↓
d = { "a": {"b": {"c": "あああ", "d": ["いいい"]}}, "x": "ううう" } # 指定のフィールドを取り出す def findfield(obj, path): k = path.pop(0) if isinstance(obj, dict): if len(path) == 0: if k in obj.keys(): return obj[k] return None return findfield(obj[k], path) return None # 指定のフィールドを削除する def delfield(obj, path): k = path.pop(0) if isinstance(obj, dict): if len(path) == 0: obj.pop(k, None) return delfield(obj[k], path) print('f1', findfield(d, 'a.b'.split('.'))) print('f2', findfield(d, 'a.b.c'.split('.'))) print('f3', findfield(d, 'a.b.d'.split('.'))) print('f4', findfield(d, 'a.err'.split('.'))) print('f5', findfield(d, 'a.b.d.err'.split('.'))) delfield(d, 'a.b.d.err'.split('.')) print('d1', d) delfield(d, 'a.err'.split('.')) print('d2', d) delfield(d, 'a.b.d'.split('.')) print('d3', d) delfield(d, 'a.b.c'.split('.')) print('d4', d) delfield(d, 'a.b'.split('.')) print('d5', d)
なお、「a.b.c.d」のようなアクセスに向かないプロパティにぶち当たった場合、例えば、a.b.cがリストの場合は強制的にNoneを戻すこととしています。
■hoge.pyの実行結果
f1 {'c': 'あああ', 'd': ['いいい']} f2 あああ f3 ['いいい'] f4 None f5 None d1 {'a': {'b': {'c': 'あああ', 'd': ['いいい']}}, 'x': 'ううう'} d2 {'a': {'b': {'c': 'あああ', 'd': ['いいい']}}, 'x': 'ううう'} d3 {'a': {'b': {'c': 'あああ'}}, 'x': 'ううう'} d4 {'a': {'b': {}}, 'x': 'ううう'} d5 {'a': {}, 'x': 'ううう'}
大事なことを見逃しているかもしれないが、今回の用途ぐらいには対応できた気がする。