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()
は失敗します。 。
私が今これを解決している方法は、各.get("")
呼び出しの周りに一連のシーケンシャルtry-except
を使用することですが、それは愚かでunpythonのようです---デフォルトで"skip"
または"pass"
またはそれでも何かを返す方法はありますか存在しないキーを深く掘り下げるのではなく、チェーンをサポートし、インテリジェントに失敗しますか?
理想的には、これをフォームのリスト内包表記にしたいと思います。
[m.get("gparents").get("parent").get("child") for m in M]
しかし、親がいないために.get("child")
呼び出しが発生してプログラムが終了した場合、これは現在不可能です。
これらはすべてpython dict
sであり、それらに対してdict.get()
メソッドを呼び出しているため、空のdict
を使用してチェーンを作成できます。
_[m.get("gparents", {}).get("parent", {}).get("child") for m in M]
_
最後の.get()
のデフォルトをオフのままにすると、None
にフォールバックします。これで、中間キーのいずれかが見つからない場合、チェーンの残りの部分は空の辞書を使用して検索を行い、.get('child')
で終了してNone
を返します。
別のアプローチは、キーが見つからない場合、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
が反復可能(非None
)であることを保証するものではありません。ただし、チェーンの最後の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
sのいずれかが失敗したかどうかを知ることができることです。 get
が間違ったタイプを返す可能性があり、その場合はTypeError
を取得します。ただし、辞書にキーがない場合は、KeyError
が発生します。それらは別々にまたは一緒に扱うことができます。ユースケースに最適なものは何でも。
小さなヘルパー関数を使ってみませんか?
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]
私はその部分に少し遅れていることに気づきましたが、同様の問題に直面したときに私が思いついた解決策は次のとおりです。
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