Python の機能についての深い理解 - リスト内包表記とジェネレーター式

皆さんこんにちは。今日は Python の 2 つの機能、リスト内包表記とジェネレーター式を紹介します。

今日は、Python 言語の 2 つの非常に便利な機能、リスト内包表記とジェネレーター式を紹介したいと思います。これらの機能の両方を使用すると、ループや関数を作成せずに、1 行の簡潔なコードでシーケンスを作成できます。しかし、それらの間にはいくつかの重要な違いもありますので、見てみましょう。

写真

技術交流

テクノロジーは共有とコミュニケーションを学ぶ必要があり、密室で作業することはお勧めできません。1 人で速く進むこともできますし、グループでより遠くまで進むこともできます。

この記事は、ファンによって共有および推奨されています。ドライ データ、データ共有、データ、および技術交換の改善はすべて、交換グループを追加することで取得できます。グループには 2,000 人を超えるメンバーがいます。メモを追加する最適な方法は次のとおりです。ソース + 興味の方向、これは便利です 同じ考えを持つ友達を見つける。

方法①、WeChatアカウント追加:pythoner666、備考:CSDNから+グループ追加
方法②、WeChat検索公式アカウント:Python学習とデータマイニング、バックグラウンド返信:グループ追加

リストの内包表記

リスト内包表記は、1 つ以上の反復子からリストを生成する角括弧で囲まれた式です。たとえば、1 から 10 までの平方数のリストを生成したい場合は、次のように記述できます。

squares = [x**2 for x in range(1, 11)]
print(squares)
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

リスト内包表記に条件判断を追加して、不要な要素を除外することもできます。たとえば、偶数の平方数のみを生成したい場合は、次のように記述できます。

even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares)
# [4, 16, 36, 64, 100]

リスト内包表記で複数の反復子を使用してデカルト積を生成することもできます。たとえば、2 つのリストの可能なすべての組み合わせを生成したい場合は、次のように記述できます。

colors = ["red", "green", "blue"]
shapes = ["circle", "square", "triangle"]
combinations = [(c, s) for c in colors for s in shapes]
print(combinations)
# [('red', 'circle'), ('red', 'square'), ('red', 'triangle'), ('green', 'circle'), ('green', 'square'), ('green', 'triangle'), ('blue', 'circle'), ('blue', 'square'), ('blue', 'triangle')]

リスト内包表記の利点は、リストが迅速に作成され、構文が明確で読みやすいことです。ただし、すべての要素を一度にメモリに格納するため、特に結果のリストが大きいか無限である場合に、多くのスペースを占有する可能性があるという欠点もあります。現時点では、ジェネレーター式を使用してこの問題を解決できます。

ジェネレーター式は、リスト内包表記とよく似た括弧で囲まれた式ですが、リストをすぐに生成する代わりにジェネレーター オブジェクトを返す点が異なります。ジェネレーター オブジェクトは、すべての要素を事前に計算して保存することなく、オンデマンドで次の要素を生成する特別な種類のイテレーターです。たとえば、1 から 10 までの平方数を含むジェネレータ オブジェクトを生成したい場合は、次のように記述できます。

squares_gen = (x**2 for x in range(1, 11))
print(squares_gen)
# <generator object <genexpr> at 0x000001F7E8C6D740>

ここで出力されるのはリストではなく、ジェネレーター オブジェクトであることに注意してください。ジェネレーター オブジェクト内の要素を取得する場合は、 next() 関数または for ループを使用して反復処理します。例えば:

print(next(squares_gen))
# 1
print(next(squares_gen))
# 4
for square in squares_gen:
    print(square)
# 9
# 16
# ...

next() 関数が呼び出されるたび、またはジェネレーター オブジェクトがトラバースされるたびに、現在の状態を記憶しながら次の要素が動的に計算されることに注意してください。

ジェネレータ式

ジェネレーター式の構文は、角括弧の代わりに括弧が使用されることを除いて、基本的にリスト内包表記の構文と同じです。リスト内包表記と同様に、条件文や複数の反復子をジェネレーター式に追加することもできます。例えば:

even_squares_gen = (x**2 for x in range(1, 11) if x % 2 == 0)
combinations_gen = ((c, s) for c in colors for s in shapes)

ジェネレーター式の利点は、リストを一度に作成するのではなく、オンデマンドで次の要素を生成するため、メモリ領域を節約できることです。こうすることで、メモリ オーバーフローを心配することなく、非常に大きなシーケンスや無限のシーケンスを処理できます。たとえば、無限のフィボナッチ数列を生成したい場合は、次のように記述できます。

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib_gen = (x for x in fib())

ここではジェネレーター関数を使用してフィボナッチ数列を定義し、それをジェネレーター式でラップしていることに注意してください。ジェネレーター関数は、yield ステートメントを使用して値を返す関数であり、ジェネレーター オブジェクトも返します。ジェネレーター関数とジェネレーター式は、ジェネレーターを作成する 2 つの異なる方法であり、どちらも遅延評価シーケンスの作成に使用できます。

ジェネレーター式のもう 1 つの利点は、不必要な計算や中間変数が回避されるため、パフォーマンスが向上することです。たとえば、シーケンス内のすべての要素の合計を計算したい場合は、次のように記述できます。

total = sum([x**2 for x in range(1, 11)])

ただし、これでは最初にリストを作成し、次にリスト内の要素を合計することになるため、時間とスペースが無駄になります。ジェネレーター式を使用する場合は、次のように記述できます。

total = sum(x**2 for x in range(1, 11))

これはリストを作成せず、各要素の平方数を sum() 関数に直接渡します。これにより、処理が高速になり、スペースが節約されます。実際、多くの組み込み関数 (min()、max()、all()、any() など) は引数としてジェネレーターを受け入れることができます。また、ジェネレーターを list() 関数または set() 関数に渡して、リストまたはセットに変換することもできます。

要約する

写真

リスト内包表記とジェネレーター式の類似点としてレストランの例を使用できます。あなたがレストランのオーナーで、ゲストにメニューを提供し、好きな料理を選んでもらいたいとします。メニューを作成するには 2 つの方法があります。

  • 1 つはリスト理解法を使用する方法です。つまり、すべての料理を事前に準備し、ゲストが自由に選択できるように大きな皿に盛り付けます。これの利点は、ゲストがすべての料理を見ることができ、複数回摂取することもでき、スピードが非常に速いことです。しかし、キッチンのスペースや食材が多く取られ、料理によっては冷めてしまったり傷んでしまったりして無駄になってしまうのがデメリットです。

  • もう 1 つはジェネレーター表現を使用する、つまりゲストのニーズに応じてその場で料理を作り、ゲストのテーブルに届けるというものです。この利点は、キッチンのスペースや食材を多く取らずに済み、どの料理も新鮮で無駄がないことです。ただし、ゲストはすべての料理を見ることができず、何度も料理を受け取ることができず、速度が遅くなる可能性があるという欠点があります。

したがって、さまざまな状況に応じて、適切なメニューの作成方法を選択する必要があります。ゲストが多く、全員が異なる料理を食べるのが好きな場合は、リスト内包表記の使用の方が適している可能性があります。ゲストの数が少なく、全員が新鮮な料理を食べるのが好きな場合は、ジェネレーター式を使用する方が適している可能性があります。

要約すると、リスト内包表記とジェネレーター式は、整然としたコード行でシーケンスを作成できる非常に便利な機能です。リスト内包表記は、何度も走査または操作する必要があるシーケンスに適していますが、ジェネレーター式は、一度だけ走査する必要があるシーケンスや、大きなシーケンスまたは無限のシーケンスを処理する必要があるシーケンスに適しています。コードの効率と読みやすさを向上させるには、さまざまなシナリオに応じて適切な方法を選択する必要があります。

おすすめ

転載: blog.csdn.net/m0_59596937/article/details/132024892