Python Accessing Dict Items through Dot

reference

All lines below will show the result which you expect.

#types/__init__.py
from typing import Iterable


class adict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    @staticmethod
    def _convert(obj):
        if not isinstance(obj, Iterable):
            raise RecursionError(f"{obj} is not {Iterable}")
        if hasattr(obj, "items"):
            for k, v in obj.items():
                if isinstance(v, dict):
                    obj[k] = adict(v)
        return obj

    def __init__(self, *args, **kwargs):
        _args = (self._convert(args[0]),)
        super().__init__(*_args, **kwargs)


    def update(self, E=None, **kwargs):
        super().update(adict(E))


def trav_d(obj):
    print(f"Traverse {obj}")
    def _trav(obj):
        print(type(obj), obj)
        if hasattr(obj, "items"):
            for k, v in obj.items():
                print(f"{v} is {type(v)}")
                if isinstance(v, Iterable) and not isinstance(v, list):
                    _trav(v)
    _trav(obj)


__all__ = [adict, trav_d]

Loading json with this custom dictionary.

이거 하려고 metaclass 까지 찾고 헛고생을 했지만, 문득 json의 소스코드를 봐볼까 ? 라는 생각이 들었고, 모든게 해결되었다. json 소스코드를 깊게 알 필요는 없고 딱 parameter만 보면 감이 잡힌다. 사실 json.load() 쓰면서 그냥 파일포인터 넣을 생각만 하고있었는데, object_hook이 있는게 아닌가. 사실.. Documentation 보는 습관이 없어서 생긴 문제다…. 기르도록 하자.

사용법은 이곳

with open(filepath, 'r') as f:
    _data = json.load(f, object_hook= lambda d: adict(d))
    return _data

Json으로 로드할때 nested는 죽어도 끝까지 dict로만 되던 것이 위 방법으로써 해결됐다.