복붙노트

[PYTHON] 사슬로 묶인, 중첩 된 dict ()는 파이썬에서 호출을받습니다.

PYTHON

사슬로 묶인, 중첩 된 dict ()는 파이썬에서 호출을받습니다.

dict.get ( 'keyword') 메소드를 사용하여 중첩 된 사전을 조사합니다. 현재 내 구문은 ...

M = cursor_object_results_of_db_query

for m in M:
    X = m.get("gparents").get("parent").get("child")
    for x in X:
        y = x.get("key")

그러나 때때로 "부모"또는 "자식"태그 중 하나가 존재하지 않고 스크립트가 실패합니다. get ()을 사용하여 키가 폼에 존재하지 않는 경우 기본값을 포함시킬 수 있음을 알고 있습니다 ...

get("parent", '') or
get("parent", 'orphan') 

그러나 null을 포함 시키면 빈 줄 생각할 수 있습니다. .get ( "child")는 ".get ("child ")에서 호출 될 때 chained .get ("child ")이 실패합니다.

지금이 문제를 해결하는 방법은 각각의 .get ( "") 호출에 대해 일련의 try-except를 사용하는 것이지만 어리석은 unpython처럼 보인다 --- 기본 반환 방법 인 "skip"또는 "pass"가 있습니다. "존재하지 않는 키들로 깊숙이 뛰어 들기보다는 연쇄를 지원하고 지능적으로 실패 할 수있는 무엇인가?

이상적으로, 나는 이것을 다음과 같은 형식의 목록으로 이해하고 싶습니다 :

[m.get("gparents").get("parent").get("child") for m in M]

결석 한 부모가 .get ( "child") 호출로 인해 내 프로그램을 종료하게되면 현재로서는 불가능합니다.

해결법

  1. ==============================

    1.이들은 모두 파이썬 dicts이고 dict.get () 메소드를 호출하고 있으므로 빈 dict을 사슬로 사용할 수 있습니다.

    이들은 모두 파이썬 dicts이고 dict.get () 메소드를 호출하고 있으므로 빈 dict을 사슬로 사용할 수 있습니다.

    [m.get("gparents", {}).get("parent", {}).get("child") for m in M]
    

    마지막 .get ()에 대한 기본값을 그대로두면 None으로 돌아갑니다. 이제 중개 키가 발견되지 않으면 체인의 나머지 부분은 빈 사전을 사용하여 .get ( 'child')로 끝내고 None을 반환하여 종료합니다.

  2. ==============================

    2.또 다른 방법은 키가 발견되지 않으면 dict.get이 None을 반환한다는 것을 인식하는 것입니다. 그러나 None은 속성 .get을 가지지 않으므로 AttributeError를 던집니다 :

    또 다른 방법은 키가 발견되지 않으면 dict.get이 None을 반환한다는 것을 인식하는 것입니다. 그러나 None은 속성 .get을 가지지 않으므로 AttributeError를 던집니다 :

    for m in M:
        try:
           X = m.get("gparents").get("parent").get("child")
        except AttributeError:
           continue
    
        for x in X:
            y = x.get("key")
            #do something with `y` probably???
    

    Martijn의 답변과 마찬가지로 X가 반복 가능하다는 것을 보증하지 않습니다 (비 - 없음). 하지만, 체인의 마지막 get을 빈리스트를 리턴하도록 디폴트로 설정함으로써이를 수정할 수 있습니다 :

     try:
        X = m.get("gparents").get("parent").get("child",[])
     except AttributeError:
        continue
    

    마지막으로, 아마도이 문제에 대한 최선의 해결책은 reduce를 사용하는 것입니다.

    try:
        X = reduce(dict.__getitem__,["gparents","parent","child"],m)
    except (KeyError,TypeError):
        pass
    else:
        for x in X:
           #do something with x
    

    이점은 발생 된 예외의 유형에 따라 실패한 가져 오기가 있는지 여부를 알 수 있다는 것입니다. get이 잘못된 타입을 반환 할 가능성이 있습니다. 그런 다음 TypeError를 얻습니다. 그러나 사전에 키가 없으면 KeyError가 발생합니다. 그것들을 개별적으로 또는 함께 처리 할 수 ​​있습니다. 유스 케이스에 가장 적합한 것은 무엇이든간에.

  3. ==============================

    3.작은 헬퍼 함수를 ​​사용하는 것은 어떻습니까?

    작은 헬퍼 함수를 ​​사용하는 것은 어떻습니까?

    def getn(d, path):
        for p in path:
            if p not in d:
                return None
            d = d[p]
        return d
    

    그리고

    [getn(m, ["gparents", "parent", "child"]) for m in M]
    
  4. ==============================

    4.나는 약간 늦었다는 것을 알지만 비슷한 문제에 직면했을 때의 해결책은 여기에있다.

    나는 약간 늦었다는 것을 알지만 비슷한 문제에 직면했을 때의 해결책은 여기에있다.

    def get_nested(dict_, *keys, default=None):
        if not isinstance(dict_, dict):
            return default
        elem = dict_.get(keys[0], default)
        if len(keys) == 1:
            return elem
        return get_nested(elem, *keys[1:], default=default)
    

    예 :

    In [29]: a = {'b': {'c': 1}}
    In [30]: get_nested(a, 'b', 'c')
    Out[30]: 1
    In [31]: get_nested(a, 'b', 'd') is None
    Out[31]: True
    
  5. from https://stackoverflow.com/questions/14484386/chained-nested-dict-get-calls-in-python by cc-by-sa and MIT license