リスト内包表記と辞書内包表記は強力で高速ですが、読みにくい場合があります。特にそれらが深くネストされている場合、私の精神的な読み取りバッファーはすぐにいっぱいになります。これらを読みやすくする方法はありますか?
2 に答える
あなたが正しい。;) 読みにくく、作成とデバッグが難しくなる可能性があります。次の辞書内包表記の例を見てみましょう:
current_team = dict((k,v) for k,v in list(team.items()) for player in v[‘player’] if player['year'] == 2013)
C と Java のプログラミングを何年にもわたって行ってきたため、これを読むのが難しくなりました。理解は論理的にさまざまな部分に分かれていますが、分解するにはまだそれをじっと見つめる必要があります。
覚えておくべき重要なことは、理解はステートメントではなく式であるということです。したがって、式を括弧で囲み、暗黙的な行結合を使用して、ネスト レベルに基づいて式を編成する改行を追加できます。
current_players = (dict((k,v)
for k,v in list(team.items())
for player in v['player']
if player['year'] == 2013))
ここで、「<a href="http://www.python.org/dev/peps/pep-0202/" rel="nofollow">最後のインデックスが、ネストされた for ループのように、最も速く変化することがより明確になります。 」</p>
空白行やコメントを追加することもできます:
current_players = (dict((k,v) # dict comprehension:
for k,v in list(team.items()) # let’s filter the team member dict...
for player in v['player'] # for players...
if player['year'] == 2013)) # who are playing this year
1 つの注意点: Python 言語リファレンスには、「継続行のインデントは重要ではない」と記載されています。したがって、読みやすさを向上させるために任意の形式のインデントを使用できますが、インタープリターは追加のチェックを行いません。
別のアプローチは、内包の力を維持することですが、ジェネレーター上にジェネレーターを構築してネストを削除し、組み込みのlist
/ set
/dict
などを使用します...-次のようなもの:
{k:v for k, v in enumerate(range(10)) if v % 2 == 0}
次のように分割できます。
with_idx = enumerate(range(10))
is_even = (el for el in with_idx if el[1] % 2 == 0)
as_dict = dict(is_even)
これは実際にはもっと冗長ですが、ネストされたレベルに同様のロジックを適用すると、実際にはより意味があります。