Skip to content
This page has been auto-translated and may contain errors.View in English

ラムダと内包表記

docs.scrimba.com

これら3つの機能には共通点があります。通常は数行かかるアイデアを、単一の読みやすい式で表現できます。うまく使えば、コードはより短く明確になります。下手に使えば、読めなくなります。この章では、それぞれをいつ使うか、いつ止めるかをカバーしています。

ラムダ、内包表記、zipは、一般的なパターンを式に圧縮する3つのツールです。必須ではありませんが、Pythonコード全体に現れ、認識して流暢に書く価値があります。指導原則は「より短くするためだけでなく、意図をより明確にするときに使う」です。

これらのツールはすべて、ステップバイステップで結果を構築する命令型ループではなく、(値に評価されるコード片)として変換を表現します。ラムダはインラインで小さな無名関数を提供します。内包表記は1回のパスでコレクションを構築します。ジェネレータは遅延評価(すべて一度にではなく、要求に応じて値を生成)であるため、メモリには全シーケンスではなく1項目だけを保持します。zipは複数のシーケンスを並行して進みます。利点は「それを組み立てる方法」ではなく「私が望むもの」として読めるコードです(ただし、ワンライナーが読めなくなるまで続けないこと)。

ラムダ関数

ラムダは名前のない1式関数です。lambdaキーワードで作成します。その真の有用性は、最初に名前付き関数を定義することなく、必要な場所にインラインで書けることです。これがsorted()で有用にしています。

ラムダは無名の単一式関数です。複数の引数を取ることができますが、本体は単一の式であり、ステートメントではありません。主な用途は、フルdefが不要な複雑さのみを追加する場所でインラインkey=またはコールバック引数です。より複雑な場合はdefを使ってください。

ラムダはdefが生成するのと同じ種類の関数オブジェクトで、3つの制限があります。名前がありません(トレースバック(Pythonが何かを発生させるときに出力されるエラーレポート)では<lambda>として表示されます)、本体は1式なのでステートメントは保持できません、ドキュメント文字列を持ちません。実際のデバッグ時間がかかるトラップは、クロージャ内の遅延バインディング(クロージャの周りのスコープから変数をキャプチャする関数)です。ループ内に構築されたラムダはループ変数を参照でキャプチャするため、すべてのラムダはラムダが作成されたときの値ではなく、変数の最終値を見ます。

python
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])        # [2, 2, 2], [0, 1, 2]ではない

funcs = [lambda i=i: i for i in range(3)]
print([f() for f in funcs])        # [0, 1, 2]: i=iは現在の値を作成時にバインドする

i=iトリックは作成時にデフォルト引数として現在の値を固定します。ループでコーラブルを構築するときはいつでもこれに頼ってください。

python
double = lambda x: x * 2
double(5)   # 10

これは以下と同等です。

python
def double(x):
    return x * 2

ほとんどの場合、defを使ってください。ラムダの本当の利点は1つです。必要な場所にインラインで書くことができ、名前を付ける必要がありません。これがsorted()map()filter()で有用にしています。

python
players = [("太郎", 87), ("花子", 74), ("次郎", 92)]

sorted(players, key=lambda p: p[1])              # スコアでソート(昇順)
sorted(players, key=lambda p: p[1], reverse=True)  # スコアでソート(降順)

ラムダなしで、key=引数のためだけに名前付き関数を定義する必要があります。ラムダは意図をローカルで見えるようにします。

ラムダは複数の引数を取ることができます。

python
add = lambda a, b: a + b
add(3, 4)   # 7

ラムダをいつ使うか: 1か所で使われる小さい式の場合のみです。成長している場合、または再利用する必要がある場合は、適切なdefを書いてください。複数の演算子にまたがるラムダまたは条件が必要なラムダは、通常defに切り替えることを示唆しています。

Junoラムダ関数 ラムダはlambdaキーワードで書かれた、名前のない小さい1行関数です。存在する全理由は、sorted()のインラインkey=になることで、1つの仕事のためだけに別の関数を定義しないようにすることです。1つのきれいな式を超えて長くなった瞬間、私は実際のdefを書いて、それについてより良い気分になります。
Junoラムダ関数 ラムダは無名の単一式関数で、名前付きdefがノイズのみを追加するインラインkey=またはコールバックとして便利です。本体は1式で、ステートメントは許可されていません。より複雑なもの、defに到達します。
Junoラムダ関数defと同じ関数オブジェクト、名前、ステートメント、ドキュメント文字列なし、つまり1ライナーkey=に保ってください。トラップは遅延バインディング:ループで構築されたラムダはループ変数の最終値を読み、lambda i=i: iと書いてそれを固定してください。それは誰もが正確に1回かみます。

リスト内包表記

Pythonで最も一般的な変換:シーケンスを取り、各項目に何かをし、新しいリストを返します。リスト内包表記はこれを1つの読みやすい行で行います。[expression for item in iterable]ifでフィルタを追加することもできます。

リスト内包表記は、ループで構築するパターンの簡潔な置き換えです。通常、.append()でループと同等の場合より高速です。Pythonは各パスでメソッドを呼び出さないためです。構造は[expression for item in iterable if condition]です。if句はオプションです。

内包表記は、各パスで.append()を呼ぶのと同じループより意味のある方法で高速なため、変換からリストを構築するための慣用的な方法です。また、独自のスコープ(名前が見える領域)で実行されます。つまり、ループ変数は周囲のコードにリークしません。[n ** 2 for n in numbers]の後、名前nは内包表記の外には存在しません。注意すべきトラップは、本体が実際の仕事をするところに達することです。式が清潔な変換を超えて成長したら、またはロギングまたはtryブロックを追加したい場合、内包表記は式のみを保持でき、ステートメントは保持できないため、明示的なループはより良いツールです。

長いやり方:

python
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
    squares.append(n ** 2)

リスト内包表記:

python
squares = [n ** 2 for n in numbers]

構造は常に同じです。[expression for item in iterable]

python
scores = [87, 42, 96, 55, 71]
scaled = [s * 1.1 for s in scores]          # 10%のボーナスを適用
as_grades = [f"{s}/100" for s in scores]    # 各1つをフォーマット
Junoリスト内包表記[expression for item in iterable]はシーケンスを取り、各項目に1つのことを行い、新しいリストを返します。左から右に読むと、それは正確に何をするかを言います。これが、別の言語から翻訳するのではなく、Pythonを書いているように感じさせてくれた最初のPython機能でした。
Junoリスト内包表記[expression for item in iterable]はループで構築し.append()するパターンを置き換え、より清潔に行います。新しいリストを生成し、何も変異させません。式をシンプルに保つ、またはあなたが得た読みやすさは消えています。
Junoリスト内包表記 `.append()`ループより高速で、独自のスコープで実行されるため、ループ変数は決してリークしません。保つ線:内包表記は式を取り、ステートメントではなく、tryブロックまたはログ行が必要な場合、明示的なループが勝ちます。

条件でフィルタリング

テストに合格した項目のみを含めるためのif句を追加してください。結果は、条件がTrueである項目のみを含む新しいリストです。

内包表記のif句はフィルタであり、if/elseではありません。各項目に対して1回実行され、条件が真実である項目のみを含めます。条件付き変換(条件に基づいて1つの値を別の値にマップする)の場合、メイン式内でテリー式を使用してください。

ifの位置は、フィルタリングするか変換するかを決定し、それらを混ぜることは、間違った長さの結果の一般的な原因です。終わり時点のifフィルタ:[x for x in data if x > 0]はアイテムをドロップします。前面の条件マップ:[x if x > 0 else 0 for x in data]はすべての項目を保持し、失敗したものを書き換えます(ここでは、負のものを0にクランプします)。1つの内包表記で両方を組み合わせることができます。[x * 2 for x in data if x > 0]。複数の後続if句をスタックでき、andとして連鎖します。

python
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
evens = [n for n in numbers if n % 2 == 0]    # [2, 4, 6, 8]
odds = [n for n in numbers if n % 2 != 0]     # [1, 3, 5, 7]
python
scores = [87, 42, 96, 55, 71, 38]
passing = [s for s in scores if s >= 60]    # [87, 96, 71]
failing = [s for s in scores if s < 60]     # [42, 55, 38]
Juno条件でフィルタリング 最後にif conditionを追加して、テストに合格した項目のみを保つ:[x for x in data if x > 0]。偽りに来るものはすべて新しいリストの外に残されます。それはドアマンがいる同じ内包表記です。
Juno条件でフィルタリング 後続の`if`はフィルタリング、条件が真実である項目のみを保つ。それは式内の条件とは異なります:`[x if x > 0 else 0 for x in data]`は値を書き換えるのではなくドロップします。書く前にどちらが欲しいかを知ってください。
Juno条件でフィルタリング 終わり時点の`if`はフィルタリングして長さを変更します。前面の条件マップしてそれを保ちます。2つを混ぜると、間違ったサイズの結果を送ります。スタックされた後続`if`句は`and`で連鎖します。

ネストされた内包表記

内包表記をネストして、リストのリストを単一のリストにフラット化できます。左から右に読んでください。各行について、その行の各項目について、項目を含めます。

ネストされた内包表記は左から右に実行されます。最初のfor句は外側のループで、2番目は内側です。単一のフラット結果を生成し、2D構造ではありません。内包表記が一目で読むのが難しい場合は、ループを明示的に書きます。

句の順序は同等のネストループと同じ順序で読みます。最初のforは外側のループ、2番目は内側、後の句は以前の句によってバインドされた名前を使用できます。これが給与を得るのは、フラット化するときです。実際のグリッド(2つのシーケンスからすべてのペア)で傷つくのは、ダブルforよりitertools.productがより明確に読まれることです。コードベースを理性的に保つ規則:内包表記の解析に1秒以上かかる場合、明示的なループはより良いドキュメントなので、その代わりに書いてください。

python
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [item for row in matrix for item in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

左から右に読んでください。matrixの各行について、その行の各項目について、itemを含めます。

ネストされた内包表記は急速に混乱する可能性があります。解析に1瞬以上かかる場合は、ループを明示的に書いてください。

Junoネストされた内包表記 1つの内包表記に2つの`for`句があり、リストのリストを単一のフラットリストにフラット化します。`[item for row in matrix for item in row]`。左から右に読み、最初の外側のループ、ループを書く正確な順序です。目が引っかかれば、それは代わりに実際のループを書く合図です。
Junoネストされた内包表記 2つの`for`句をスタックし、最初は外側のループで、2番目は内側です。`[item for row in matrix for item in row]`は2Dリストを1つにフラット化します。結果はフラットであり、グリッドではありません。一目で読みやすくなくなったら、明示的なループはより良くなります。
Junoネストされた内包表記 最初の`for`は外側のループで、後の句は前の句の名前を使用できます。フラット化のために素晴らしい、すべてのペアの組み合わせのために悪い、そこで`itertools.product`がより明確に読みます。解析に1秒以上かかる場合、ループはより良いドキュメントです。

辞書内包表記

辞書内包表記は辞書を1つの式で構築し、リスト内包表記と同じ考えを使用します。{key: value for item in iterable}。リスト内包表記と同様にifでフィルタを追加してください。

辞書内包表記は、キーと値のペアを生成する任意のイテラブルから新しい辞書を作成します。構文は{key_expr: val_expr for item in iterable if condition}です。ループからの重複キーは最後の値を使用し、静かに行われます。既存の辞書の.items()は、辞書内包表記の最も一般的なソースイテラブルです。

2つのことが実際のコードで噛まれます。最初に、すべてのキーはハッシュ可能である必要があります(Pythonが固定ルックアップ番号に削減できる値、つまり決して変わらないため、文字列と数字とタプルは適格ですが、リストと辞書は適格ではありません)。リストを生成するキー式はTypeErrorを発生させます。2番目に、重複キーはエラーになりません。ループが同じキーを2回生成する場合、後の値は静かに早期のものを上書きします。これは、実際には一意でないソースから辞書を構築するときの、静かなドロップされたデータのソースです。2つの既存の辞書をマージしたい場合、|演算子(辞書マージ形式、Python 3.9以降)は、内包表記より意図を明確に述べています。

python
names = ["太郎", "花子", "次郎"]
scores = [87, 74, 92]

score_map = {name: score for name, score in zip(names, scores)}
# {"太郎": 87, "花子": 74, "次郎": 92}

フィルタ付き:

python
passing = {name: score for name, score in score_map.items() if score >= 80}
# {"太郎": 87, "次郎": 92}
python
words = ["apple", "banana", "cherry"]
word_lens = {word: len(word) for word in words}
# {"apple": 5, "banana": 6, "cherry": 6}
Juno辞書内包表記{key: value for item in iterable}は1行で辞書を構築し、キーと値の間にコロンがあるリスト内包表記と同じ形です。`.items()`と組み合わせて、既に持っている辞書を再形成したり、`zip()`と組み合わせて2つのリストを1つのマッピングに縫い合わせたりします。最後に`if`を追加して、欲しいペアのみを保ちます。
Juno辞書内包表記{key: value for item in iterable}はペアの任意のソースから辞書を作成します。2つの毎日のソースは、既存の辞書の`.items()`と2つのリスト上の`zip()`です。重複キーを監視してください。最後のものが勝ち、静かです。
Juno辞書内包表記 キーはハッシュ可能である必要があり(リストなし)、重複キーはエラーになり、後の値は静かに上書きし、ソースが一意でない場合にデータを食べます。そのため、信頼する前に一意性を確認してください。2つの辞書をマージするために、`|`は内包表記より平に述べます。

セット内包表記

セット内包表記は、1つの式でセットを構築し、波括弧とコロンなし。結果はセットであるため、重複は自動的に削除されます。

セット内包表記は{expression for item in iterable}を使用し、setを生成します。自動的に重複排除します。順序が重要でない場合、変換から構築されたユニークなコレクションが必要な場合に使用します。

結果はsetなため、リスト版が与えない2つのことが従います。式からの重複値は自動的に1つに崩壊します。これがポイントです。これは単一の式での変換の重複排除の最もクリーンな方法です。代価はセットに順序がないため、項目がどんな特定のシーケンスでも出てくることに依存することができません。メンバーもハッシュ可能である必要があり、同じルール辞書キーに適用されます。Pythonが固定ルックアップ番号に削減できる値であり、これはリストを除外します。

python
words = ["apple", "banana", "cherry", "apple"]
unique = {w.lower() for w in words}    # {"apple", "banana", "cherry"}

セット内包表記は、ユニークな値が必要で、順序を気にしない場合に使用します。

Junoセット内包表記 `{expr for item in iterable}`で波括弧とコロンなしはセットを構築し、セットは無料で重複を捨てます。だからあなたの仕事が「ユニークなものをくれ」なら、これは1行でそれをします。ただし、任意の特定の順序で戻ってくると数えないでください。
Junoセット内包表記 `{expr for item in iterable}`は`set`を生成し、進むにつれて重複排除します。変換から一意なコレクションが必要で、順序が重要でない場合に到達します。波括弧とコロンなし、それはそれを辞書内包表記から分離している唯一のものです。
Junoセット内包表記 セットは重複を自動的にドロップし、これはリスト内包表記を超えて選ぶ全理由です。トレードは依存する順序なし、メンバーはハッシュ可能である必要があり、内部にリストなし。ベストフィット:1つの式で変換を重複排除します。

ジェネレータ式

ジェネレータは、角括弧の代わりに括弧を持つリスト内包表記のようです。重要な違い:リスト内包表記はメモリ全体をすべて一度に構築します。ジェネレータは必要に応じて1回に1つの値を生成します。大きなシーケンスの場合、これははるかに少ないメモリを使用します。

ジェネレータ式はコレクションではなく、イテレータを生成します。遅延値を計算します。次の値は要求されたときのみ生成されます。これは、sum()max()、またはany()のような関数によって結果がすぐに消費されるときに最も価値があり、最初にフルリストを構築するポイントはありません。

ジェネレータは遅延評価(1回に1つ、次のリクエストされた場合のみ)を生成するため、メモリはインプットがどれほど大きくても平坦に保たれます。それは決して現在の値を超えてメモリに保持しません。リスト内包表記はすべての要素を一度に保持します。これは大きなまたはストリーミングソースがフィードsum()max()、またはany()への正しい呼び出しになります。覚えるべき失敗モードは、ジェネレータは単一使用です。何かがそれをの終わりまで繰り返したら、それは尽きて、これ以上何も生成し、同じジェネレータを超える2番目のループはゼロ回実行され、エラーは発生しません。2回データを歩く必要がある場合は、1回リストを構築し、それを繰り返してください。

python
squares_gen = (n ** 2 for n in range(1000000))
python
total = sum(n ** 2 for n in range(1000000))   # sum()はジェネレータを消費する

sum()max()min()any()のような関数にジェネレータを直接渡す場合、追加の括弧を削除できます。

python
total = sum(n ** 2 for n in range(1000))   # 2つでなく1セットの括弧

ほとんどの毎日のコードでは、リスト内包表記は問題ありません。大規模なデータセットまたはストリーミングデータを処理する場合、メモリ内のすべての保持は浪費になる場合、ジェネレータを使用します。

Junoジェネレータ式 ジェネレータは、角括弧の代わりに括弧を持つリスト内包表記のようですが、全体のリストアップフロント構築ではなく、1回に1つの値を作成します。巨大なシーケンスについてメモリのパイルを保存します。ネット場合:1つを直接`sum()`または`max()`にドロップし、構築の全リストをスキップします。
Junoジェネレータ式 ジェネレータ式は遅延イテレータを返す:次の値は、リスト内のメモリ全体が構築されないよう要求される場合のみを計算します。`sum()`、`max()`、または`any()`に結果がフィードされるときに最適です。覚えておいてください、それは単一使用です。消費されたら、空です。
Junoジェネレータ式 入力がどれほど大きくてもメモリの遅延で平坦なため、大規模またはストリーミングソースがフィード`sum()`または`any()`に供給される正しいツールです。キャッチ:単一使用で、疲れたジェネレータを超える2番目のループはエラーなし0回実行されます。2パスが必要なのですか?リストを構築してください。

zip()

zip()は2つ以上のシーケンスからの項目をペアにして、それらを並行してループできます。最も短いシーケンスで停止します。2つのリストが互いに対応する場合、インデックスの管理を避けるクリーンな方法です。

zip()は遅延タプルのイテレータを返し、ステップ内の入力イテラブルを消費します。最短入力時に停止します。長いシーケンスは静かに切り詰められます。長さが異なる場合がある場合、itertools.zip_longest()は指定された値で短いものを埋めます。

zip()はステップ内で入力を進み、最短の1つが実行されるのをやめます。その切り詰めは設計するあたりの落とし穴です。1000レコードのリストを999のリストとペアにし、静かに最後のレコードを失い、エラー、警告なし。長さが一致するはずの場合、zip(seq_a, seq_b, strict=True)(Python 3.10以降)は異なる場合に発生させます。ドロップの代わりにデータ、itertools.zip_longestは異なることが許可される場合、ギャップを埋めます。知る価値がある別のトリック:zip(*rows)は行のリストを列のリストに変える、転置し、*外側のリストを別の引数にアンパックするため。

python
names = ["太郎", "花子", "次郎"]
scores = [87, 74, 92]

for name, score in zip(names, scores):
    print(f"{name}: {score}")
# 太郎: 87
# 花子: 74
# 次郎: 92

zip()は最短のシーケンスで停止します。シーケンスが異なる長さの場合、埋め値でitertools.zip_longest()を使用します。

ジッピングされたペアのリストから2つの別のリストに変換するには、zip(*pairs)を使用します。

python
pairs = [("太郎", 87), ("花子", 74), ("次郎", 92)]
names, scores = zip(*pairs)
# names = ("太郎", "花子", "次郎")
# scores = (87, 74, 92)

*pairsはリストを別の引数にアンパックするため、zip(*pairs)zip(("太郎", 87), ("花子", 74), ("次郎", 92))になります。*演算子は関数章で説明されています。

zip()は、インデックスを手動で管理せずに複数のシーケンスを並行して繰り返すクリーンな方法でもあります。

python
before = [10, 20, 30]
after = [15, 18, 35]

for b, a in zip(before, after):
    change = a - b
    print(f"{b} -> {a} ({'+' if change >= 0 else ''}{change})")
Junozip() `zip()`は2つ以上のシーケンスをペアにして、インデックスジャグルなしでそれらをループできます。最短のもので停止するため、不一致の長さは静かに追加を失うため。`zip(*pairs)`はそれを逆に実行し、タプルのリストを別のリストに分割して戻ります。
Junozip() `zip()`は遅延タプルのイテレータを返し、その入力を並行してステップします。最短で停止するため、長いシーケンスはピープなしで切り詰められます。`itertools.zip_longest()`は長さが正当に異なる場合、ギャップを埋め、`zip(*pairs)`はアンジップされます。
Junozip() 遅延、並行、最短入力で停止し、長さが一致するはずの場合、データは静かにドロップされます。`strict=True`を渡して、不一致を発生させます。`zip(*rows)`は、1つの呼び出しで列が行からあるものです。転置。

map()とfilter()

map()filter()は、内包表記がする何をしている古い関数スタイルのツールです。古いコードでそれらを見かけるため、それが意味することを知る価値があります。新しいコードでは内包表記を好みます。ほとんどのPython開発者にはより読みやすいです。

map(func, iterable)は各項目にfuncを適用する遅延イテレータを返します。filter(func, iterable)funcが真実である項目の遅延イテレータを返します。両方とも内包表記を先行します。新しいコードで内包表記を好みます。既に持っている名前付き関数を使用して、map()を使用する場合は、あなたが必要とするものをします。

どちらも遅延イテレータを返します。リストではなく、値を今したい場合はlist()で包みます。彼らは既に知っている内包表記にマップします:map(f, it)(f(x) for x in it)であり、filter(pred, it)(x for x in it if pred(x))です。その同等性は決定規則です。インラインlambdaで、内包表記はより良く読み、現代的なデフォルトです。既に仕事をする名前付き関数で、list(map(int, strings))は「stringにmapの上にmapint」として読み、より清潔な選択です。唯一の本当の呼び出しは、既に関数が手にあるかどうかです。

python
numbers = [1, 2, 3, 4, 5]

list(map(lambda x: x ** 2, numbers))         # [1, 4, 9, 16, 25]
list(filter(lambda x: x % 2 == 0, numbers))  # [2, 4]

内包表記を好みます。ほとんどのPython開発者にはより読みやすいです。既に存在する名前付き関数がある場合、map()を使用します。

python
strings = ["1", "2", "3"]
numbers = list(map(int, strings))   # [1, 2, 3] (内包表記より清潔)
Junomap()とfilter() `map(func, iterable)`はすべての項目を超えて関数を実行します。`filter(func, iterable)`は関数がtruthyで来る項目のみを保ちます。彼らは内包表記がする何をしている古い方法なため、他の人のコードで彼らに会うでしょう。あなた自身、内包表記についてより多くの人々に読みやすい。
Junomap()とfilter() `map()`は各項目を変換し、`filter()`はtruthy 1つを保ち、両方の遅延、リストで包みます。内包表記は新しいコードのデフォルトです。`map()`が勝つ1つのスポット:既に持っている名前付き関数:`map(int, strings)`は内包表記より清潔に読みます。
Junomap()とfilter() `map(f, it)`は`(f(x) for x in it)`で、`filter(pred, it)`は`(x for x in it if pred(x))`、両方遅延です。そのため、選択は純粋に読みやすさです。インラインラムダで、内包表記が勝つ。既に命名された関数で、`map(int, strings)`が勝ちます。

実践で

プレイヤーリストをフィルタリング、スコアでランク付けしsortedとラムダで、列挙位置で印刷します。

python
players = [
    {"name": "太郎", "score": 87},
    {"name": "花子", "score": 42},
    {"name": "次郎", "score": 96},
    {"name": "三郎", "score": 55},
]

passing = [p for p in players if p["score"] >= 60]
ranked = sorted(passing, key=lambda p: p["score"], reverse=True)
score_map = {p["name"]: p["score"] for p in ranked}

for i, (name, score) in enumerate(score_map.items(), start=1):
    print(f"{i}. {name}: {score}")

アクティブな管理者のユーザーリストをフィルタリング、idとname参照辞書を構築し、ソートされた名前を1つのパスで各収集します。

python
raw_users = [
    {"id": 1, "name": "太郎", "role": "admin", "active": True},
    {"id": 2, "name": "花子", "role": "user", "active": False},
    {"id": 3, "name": "次郎", "role": "admin", "active": True},
    {"id": 4, "name": "三郎", "role": "user", "active": True},
]

active_admins = [u for u in raw_users if u["active"] and u["role"] == "admin"]
id_map = {u["id"]: u["name"] for u in raw_users}
names = sorted(u["name"] for u in raw_users if u["active"])

print(f"Active admins: {[u['name'] for u in active_admins]}")
print(f"All active: {names}")

zipを使用して機能名と重要度スコアをペアにし、辞書内包表記を構築し、ラムダでソートし、2番目の内包表記で値を正規化します。

python
feature_names = ["age", "income", "score", "tenure"]
importances = [0.12, 0.34, 0.28, 0.26]

feat_dict = {f: i for f, i in zip(feature_names, importances)}
top_feats = sorted(feat_dict.items(), key=lambda x: x[1], reverse=True)[:2]

print("Top 2 features:")
for name, score in top_feats:
    print(f"  {name}: {score:.2f}")

# 1.0に合計を正規化します(値はここで既に1に合計されていますが、パターンとして表示されます)
total = sum(feat_dict.values())
normalised = {k: round(v / total, 4) for k, v in feat_dict.items()}
print(f"Normalised: {normalised}")

zipは中間タプルを構築することなく2つのリストをペアにします。辞書内包表記は1つの式でマッピングを構築します。ソートラムダは名前付きキー関数を避けます。正規化内包表記は、元の辞書を変異させることなく値を変換します。