Python(内包表記)

リスト内包表記について 、以前に Python(リスト内包表記)の投稿をしましたが、他に内包表記の種類として集合内包表記辞書内包表記ジェネレータ式があるので、それぞれについて確認していきます。

# 集合(セット)内包表記
{x*x for x in range(10)}
7 in {x*x for x in range(10)}
49 in {x*x for x in range(10)}
{ x+y for x in [1,2,3] for y in [1,2,3] }
[ x+y for x in [1,2,3] for y in [1,2,3] ]

集合(set)はリストに似ていて、複数の値を記録することができますが、「重複する値を持たせる事はできない」「順序をつけることができない」という特徴があります。
上記のように{}を使ってリスト内包と同様の記述で処理を行うことができます。
集合はset()メソッドで生成することも可能で、差分を「-」、結合を「|」、交差を「&」の演算子で行うことができます。

# 辞書内包表記
{"abc":10,10:-10}["abc"]
{"abc":10,10:-10}[10]
{str(x):x*x for x in range(10)}
{str(x):x*x for x in range(10)}["5"]

辞書はPython(36進数→10進数変換)Python(Tableクラス設計)で活用してきましたが、キーと値をペアとして記録することができ、引数にキーを指定することで、その値を取り出すことができます。また、keys()メソッドでキーを列挙したり、values()メソッドで値の一覧を得たり、items()メソッドでキーと値の組み合わせをタプルにしたリストを得たりすることができます。
辞書内包表記ではキーと値を組にして記述します。

# ジェネレータ式
sum(2 ** a * x for a,x in enumerate(int(s) for s in "1010"[::-1]))

(x*x for x in range(10))
a=(x*x for x in range(10))
next(a)
next(a)

def f(x):
    pass

f(x*x for x in range(10))

def g(a,b):
    pass

g((x*x for x in range(10)),0)

ジェネレータ式ではリスト内包の[]の代わりに()と変えるだけですが、他の種類のように即時リストを返すのではなく、値を1つずつ取り出すジェネレータを返します。
関数の引数にジェネレータ式を利用する場合、少し記法に特徴があり、引数が一つの場合は()で閉じなくても実行されますが、引数が2つ以上の場合にジェネレータ式を利用する場合は()で閉じて記述する必要があります。
リスト内包ではリストを生成が必要なため、メモリを消費するので巨数の処理には向きませんが、ジェネレータ式では、その度、値を返すのでメモリ効率がよく、リストが必要ない場合はジェネレータ式を活用していきましょう。

# リスト内包とジェネレータ式
any([isinstance(x,int) for x in ["a",1,(1,2)]])
any(isinstance(x,int) for x in ["a",1,(1,2)])
all([isinstance(x,int) for x in [1,1,2]])
all(isinstance(x,int) for x in [1,1,2])

any()やall()メソッドで要素を判定したり、sum()メソッドで合計を出したりする場合、リストを保持する必要がなければジェネレータ式を活用する機会です。

# forループ、map,filter → リスト内包
data = []
for i in range(1,6):
    data.append(i * 2)
print(data)

data=[i*2 for i in range(1,6)]
print(data)

data = list(map(lambda x:x*2,range(1,6)))
print(data)

data2 = [x for x in range(1,6) if x%2 == 0 ]
print(data2)

data2 = list(filter(lambda x:x%2==0,range(1,6)))
print(data2)

# リスト内包と三項演算子
res=["Fizz Buzz" if i%15==0 else "Fizz" if i%3==0 else "Buzz" if i%5==0 else str(i)
     for i in range(1,21)]
print("\n".join(res))

forループやmap()、filter()はリスト内包に書き換えることが可能です。実行速度としてもリスト内包の方が速く、プログラムの行数を少なく書ける利点があります。
ただ、凝った内包表記を書くと可読性が低くなり、トラブルの原因にもなるので、関数を活用し、シンプルで読みやすいプログラムを心がけましょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Python

前の記事

Python(Tableクラス設計)
Python

次の記事

Python(デスクトップアプリ)