24

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")"".get()

私が今これを解決している方法は、try-except.get("")呼び出しの周りに一連のシーケンシャルを使用することですが、それは愚かでunpythonのようです---デフォルトのリターン"skip"または"pass"チェーンをサポートし、深くではなくインテリジェントに失敗する何かがあります-存在しないキーに飛び込みますか?

理想的には、これをフォームのリスト内包表記にしたいと思います。

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

しかし、親がいないために.get("child")呼び出しが私のプログラムを終了させる場合、これは現在不可能です。

4

4 に答える 4

82

これらはすべてPythonであり、それらに対してメソッドdictを呼び出しているdict.get()ため、空dictを使用してチェーンを作成できます。

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

最後のデフォルトをオフのままにすると、.get()にフォールバックしNoneます。これで、中間キーのいずれかが見つからない場合、チェーンの残りの部分は空の辞書を使用して検索し、で終了し.get('child')ますNone

于 2013-01-23T16:32:26.603 に答える
8

別のアプローチは、キーが見つからない場合はを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???

XMartijnの答えと同じように、これは反復可能(非)であることを保証するものではありませんNonegetただし、チェーンの最後をデフォルトで空のリストを返すようにすることで、これを修正できます。

 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、発生した例外のタイプに基づいて、のいずれかが失敗したかどうかを知ることができることです。getが間違ったタイプを返す可能性があります。そうすると、が得られますTypeError。ただし、辞書にキーがない場合は、が発生しKeyErrorます。それらは別々にまたは一緒に扱うことができます。ユースケースに最適なものは何でも。

于 2013-01-23T16:38:38.377 に答える
5

小さなヘルパー関数を使ってみませんか?

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]
于 2013-01-23T16:41:41.363 に答える
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
于 2016-01-23T00:13:17.983 に答える