Pythonリスト内包表記の正しい使用(2)

高度な分析

条件付きロジック
前に、次の式を示しました。

python学习交流群:660193417###
new_list = [expression for member in iterable]

式はやや不完全かもしれません。解析のより完全な説明は、オプションの条件のサポートを追加します。リスト内包表記に条件付きロジックを追加する最も一般的な方法は、式の最後に条件を追加することです。

new_list = [expression for member in iterable (if conditional)]

ここで、条件文は右側の括弧内にあります。

条件は、リスト内包表記で不要な値を除外できるため重要です。これにより、一般的な場合はfilter()を呼び出すこともできます。

numbers = [number for number in range(20) if number % 2 == 0]
print(numbers)

出力:

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

ご覧のとおり、この分析では、2で割り切れ、余りのない数値が収集されます。

より複雑なフィルターが必要な場合は、条件付きロジックを別の関数に移動することもできます。

def is_prime(number):
    if number > 1:
        for el in range(2, int(number/2)+1):
            if (number % el) == 0:
                return False 
        else:
            return True
          
numbers = [number for number in range(20) if is_prime(number)]
print(numbers)

出力:

[2, 3, 5, 7, 11, 13, 17, 19]

is_prime(number)を作成して、それが素数であるかどうかを判別し、ブール値を返します。次に、分析条件に関数を追加する必要があります。

この式を使用すると、条件付きロジックを使用して、いくつかの可能な出力オプションから選択できます。たとえば、製品の価格表がある場合、負の数がある場合は、それらを正の数に変換する必要があります。

price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [price if price > 0 else price*-1 for price in price_list]
print(normalized_price_list)

出力:

[1.34, 19.01, 4.2, 6, 8.78, 1,1]

ここで、式の価格には、価格が0より大きい場合は条件付きステートメントがあり、それ以外の場合は価格*-1です。これは、価格が正の場合は価格値を出力するようにPythonに指示しますが、価格が負の場合は価格を正の値に変換します。これは強力であり、条件付きロジックをそれ自体の関数と見なすと非常に便利です。

def normalize_price(price):
    return price if price > 0 else price*-1
    
price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [normalize_price(price) for price in price_list]
print(normalized_price_list)

出力:

[1.34, 19.01, 4.2, 6, 8.78, 1,1]

画像の説明を追加してください

分析を設定する

コレクションリゾルバーを作成することもできます!基本的にリスト内包表記と同じです。違いは、集合の内包には重複が含まれていないことです。角かっこではなく中かっこを使用して、リスト内包表記を作成できます。

string = "Excellent"
unique_string = {letter for letter in string}
print(unique_string)

出力:

{"E", "e", "n", "t", "x", "c", "l"}

セット解析には、一意の文字のみが含まれています。リストとは異なり、セットはアイテムが特定の順序でデータを格納することを保証しません。そのため、文字列の2番目の文字はxですが、セット出力の2番目の文字はeです。

辞書理解

辞書内包表記は似ていますが、キーを定義する必要があります。

string = "Words are but wind"
word_order = {el: ind+1 for ind, el in enumerate(string.split())}
print(word_order)

出力:

{"Words": 1, "are": 2, "but": 3, "wind": 4}

語順辞書を作成するには、式で中括弧({})とキーと値のペア(el:ind + 1)を使用します。

セイウチのオペレーター

Python 3.8で導入されたwalrus演算子を使用すると、2つの問題を一度に解決できます。変数に値を割り当て、その値を返します。

温度データを返すAPIを10回適用する必要があるとします。必要なのは華氏100度を超える結果です。また、リクエストごとに異なるデータが返される場合があります。存在

この場合、Pythonでリスト内包表記を使用して問題を解決する方法はありません。反復可能メンバーの式(条件付きの場合)は、条件付き割り当てデータを作成できません

式からアクセスできる変数。

Walrus演算子はこの問題を解決します。式の実行中に出力値を変数に割り当てることができます。次の例は、これを使用してこれを実現する方法を示しています。

get_weather_data()は、疑似気象データを生成します。

import random
def get_weather_data():
    return random.randrange(90, 110)
hot_temps = [temp for item in range(20) if (temp := get_weather_data()) >= 100]
print(hot_temps)

出力:

[108, 100, 106, 103, 108, 106, 103, 104, 109, 106]

画像の説明を追加してください

分析式を使用しない場合

リスト内包表記は、クリーンで読みやすくデバッグしやすいコードを作成するのに非常に役立ちます。ただし、場合によっては、コードの実行が遅くなったり、より多くのメモリを使用したりする可能性があります。コードの効率が低下したり、理解しにくくなったりする場合は、別の方法を検討してください。

ネストされた解析に注意してください

パーサーをネストすることにより、リスト、辞書、およびセットの組み合わせコレクションを作成することができます
たとえば、ある会社が1年間に5つの異なる都市で収益を追跡しているとします。このデータを格納するための完璧なデータ構造は、辞書内包表記内にネストされたリスト内包表記です。

cities = ['New York', 'Oklahoma', 'Toronto', 'Los Angeles', 'Miami']
budgets = {city: [0 for x in range(12)] for city in cities}
print(budgets)

出力:

{
    "NewYork": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Oklahoma": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Toronto": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "LosAngeles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Miami": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}

辞書内包表記を使用して予算コンテナを作成しました。式は、別の分析式を含むキーと値のペアです。このコードは、都市の各都市のデータのリストをすばやく生成します。

ネストされたリストは、通常は数学的な目的で、行列を作成する一般的な方法です。以下のコードブロックを確認してください。

matrix = [[x for x in range(7)] for y in range(6)]
print(matrix)

出力:

[
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6]
]

外側のリスト内包[…foryin range(6)]は6行を作成し、内側のリスト内包[x for x in range(7)]はこれらの各行に値を入力します。

これまでのところ、ネストされたすべての解析の目標は非常に単純です。ただし、フラット化されたネストされたリストを作成する場合のように、ロジックによってコードが非常に読みにくくなる場合もあります。ネストされたリスト内包表記を使用して行列を平坦化する次の例を見てみましょう。

matrix = [
    [0, 1, 0],
    [1, 0, 1],
    [2, 1, 2],
]
flat = [num for row in matrix for num in row]
print(flat)

出力:

[0, 1, 0, 1, 0, 1, 2, 1, 2]

マトリックスを平坦化するためのコードは本当にきれいですが、それがどのように機能するかを理解するために時間をかける必要があることを理解するのは非常に難しいです。一方、forループを使用して展開する場合

同じ行列をフラット化すると、コードがよりシンプルで読みやすくなります。

matrix = [
    [0, 1, 0],
    [1, 0, 1],
    [2, 1, 2],
]
flat = []
for row in matrix:
    for num in row:
        flat.append(num)
print(flat)

出力:

[0, 1, 0, 1, 0, 1, 2, 1, 2]

これで、コードが一度に1行の行列を通過し、次の行に移動する前にその行のすべての要素を取り出していることがわかります。

ネストされたリスト内包表記はPythonのように見えるかもしれませんが、チームが簡単に理解して変更できるコードを記述できることがより重要です。方法を選択するときは、構文解析が読みやすさを向上させるか、または損なうかどうかに基づいて判断する必要があります。

大規模なデータセットにはジェネレーターを使用する

Pythonのリスト内包表記は、リスト全体をメモリに保存することで機能します。これは通常、中小規模のリストには問題ありません。最初の1000個の整数を追加する場合は、

次に、リスト内包はこのタスクを簡単に解決します。

summary = sum([x for x in range(1000)])
print(summary)

出力:499500

しかし、10億の数字を合計する必要がある場合はどうなりますか?これを試すことはできますが、コンピューターが応答しない可能性があります。これが可能なのは、コンピュータに大量のメモリが割り当てられているためです。たぶんあなたはあなたのコンピュータがそれほど多くのメモリリソースを持っていないからです。

たとえば、最初の10億個の整数が必要なので、ジェネレーターを使用しましょう。これにはしばらく時間がかかる場合がありますが、コンピューターはそれを乗り越えることができるはずです。

summary = sum((x for x in range(1000000000)))
print(summary)

出力:

499999999500000000

どちらの方法が良いかを比較してみましょう!

import timeit
def get_sum_with_map():
    return sum(map(lambda x: x, range(1000000000)))
def get_sum_with_generator():
    return sum((x for x in range(1000000000)))
print(timeit.timeit(get_sum_with_map, number=100))
print(timeit.timeit(get_sum_with_generator, number=100))

出力:

4940.844053814  # get_sum_with_map
3464.1995523349997  # get_sum_with_generator

ご覧のとおり、ジェネレーターはmap()よりもはるかに効率的です。

要約する

この記事では、リスト内包表記と、それを使用してコードを難しくすることなく複雑なタスクを解決する方法を紹介しました。

では、あなた:

リストを作成するためのいくつかの代替方法を学びました。

•各方法の利点を確認します。

•リスト内包表記は、ループとmap()呼び出しのために簡略化できます。

•分析式に条件付きロジックを追加する方法を理解します。

•セットと辞書内包表記を作成できます。

•分析式を使用しない場合を学びます。

今日共有されているリスト内包表記のスタイルを学びましたか?記事は非常に長く、退屈に見えますが、最後までこだわるのは素晴らしいことです。

おすすめ

転載: blog.csdn.net/m0_67575344/article/details/124368468