Closed10

Python3_内包表記, ジェネレーター, アンパック

かじるかじる

Python実践レシピより

Python3エンジニア認定実践試験メモ

内包表記

main.py
# 0 ~ 10までのリスト
nums = [i for i in range(10)]
print(nums)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 偶数のみ
evens = [i for i in range(10) if i%2==0]
print(evens)
# [0, 2, 4, 6, 8]

# 奇数のみ
odds = [i for i in range(10) if i%2!=0]
print(odds)
# [1, 3, 5, 7, 9]
かじるかじる

内包表記のネスト1

"["と"]"でリスト、"{"と"}"でセット、"("と")"でジェネレーターを返す

main.py
# ネスト1(九九表をリストで取得)
kuku = [a*b for a in range(1,10) for b in range(1,10)]
print(kuku)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, ...45, 54, 63, 72, 81]

# ネスト2(九九表をセットで取得)
kuku = {a*b for a in range(1,10) for b in range(1,10)}
print(kuku)
# {1, 2, 3, 4, 5, 6, 7, 8, 9, ...56, 63, 64, 72, 81}

# ネスト3(九九表をジェネレーターで取得)
kuku = (a*b for a in range(1,10) for b in range(1,10))
print(kuku)
# <generator object <genexpr> at 0x10bfd4ba0>

# ジェネレーターからデータを取り出す時に作成される
for i in kuku:
    print(i)
# 0 1 2 3...
かじるかじる

内包表記のネスト2

main.py
# ネスト4(リスト同士の組み合わせ)
drinks = ["Coffe", "Tea", "Miso"]
sizes = ["S", "M", "L"]
menu = [(drink, size) for drink in drinks for size in sizes]
print(menu)
# [('Coffe', 'S'), ('Coffe', 'M'), ('Coffe', 'L'), 
# ('Tea', 'S'), ('Tea', 'M'), ('Tea', 'L'), 
# ('Miso', 'S'), ('Miso', 'M'), ('Miso', 'L')]

# ネスト5(辞書で取得)
drinks = ["Coffe", "Tea", "Miso"]
sizes = ["S", "M", "L"]
menu = {drink: size for drink in drinks for size in sizes}
print(menu)
# {'Coffe': 'L', 'Tea': 'L', 'Miso': 'L'}
かじるかじる

ジェネレーターで等差数列の和

main.py
# 等差数列の和
# 初項:1, 等差:1

# 1 + 2 + 3 + ...
def my_gen1():
    num = 1
    total = num
    while True:
        yield total # 結果を返し一時停止
        num += 1
        total += num # 次の呼び出しで実行

# ジェネレーターオブジェクト
gen = my_gen1()
print(gen)
# <generator object my_gen1 at 0x1092347c0>

# イテレーション
print(next(gen))
# 1
print(next(gen))
# 3
print(next(gen))
# 6
かじるかじる

ジェネレーターで等比数列の和

main.py
# 等比数列の和
# 初項:1, 公比:2

# 1 + 2 + 4 + ...
def my_gen2():
    num = 1
    total = num
    while True:
        yield total
        num *= 2
        total += num

gen = my_gen2()
print(gen)
# <generator object my_gen2 at 0x104534a00>

# イテレーション
print(next(gen))
# 1
print(next(gen))
# 3
print(next(gen))
# 7
かじるかじる

ジェネレーターで大きなファイルを扱う

容量が大きいファイルを、少ないメモリで効率よくアクセスできる。

main.py
import re

# 1行づつ取り出す
def search_text(path, pattern):
    with open(path, mode="r") as f:
        for row in f:
            if re.match(pattern, row):
                yield row.strip()

# "吾輩は...。"のパターンで始まる行のみを取り出す
for row in search_text("./story.txt", "^(\s*吾輩は).*\n$"):
    print(row)

# 吾輩は猫である。
# 吾輩はここで始めて人間というものを見た。
# ...(省略)
# 吾輩は死ぬ。
かじるかじる

アンパック

main.py
# タプルのアンパック
a, b, c = (1, 2, 3)
print(f"{a}, {b}, {c}")
# 1, 2, 3

# タプルの"()"は省略可能
a, b, c = 1, 2, 3
print(f"{a}, {b}, {c}")
# 1, 2, 3

# リストのアンパック
a, b, c = [1, 2, 3]
print(f"{a}, {b}, {c}")
# 1, 2, 3

# ディクショナリ(キー)
key1, key2, key3 = {"a": 1, "b": 2, "c": 3}
print(f"{key1}, {key2}, {key3}")

# ディクショナリ(値)
val1, val2, val3 = {"a": 1, "b": 2, "c": 3}.values()
print(f"{val1}, {val2}, {val3}")
かじるかじる

ネストしたタプル、リストのアンパック

main.py
# 変数とタプルにアンパック
a, b, c = (0, 1, (2, 3, 4))
print(f"{a}, {b}, {c}")
# 0, 1, (2, 3, 4)

# それぞれの変数にアンパック
a, b, (c, d, e) = (0, 1, (2, 3, 4))
print(f"{a}, {b}, {c}, {d}, {e}")
# 0, 1, 2, 3, 4
かじるかじる

*を使ったアンパック

main.py
a, b, *c = (0, 1, 2, 3, 4)
print(f"{a}, {b}, {c}")
# 0, 1, [2, 3, 4]

a, *b, c = (0, 1, 2, 3, 4)
print(f"{a}, {b}, {c}")
# 0, [1, 2, 3], 4

*a, b, c = (0, 1, 2, 3, 4)
print(f"{a}, {b}, {c}")
# [0, 1, 2], 3, 4

# *を2つ使うとエラー
#*a, *b, c = (0, 1, 2, 3, 4)
かじるかじる

リスト,辞書のアンパック

main.py
def my_func(a, b, c):
	print(f"{a}, {b}, {c}")

# リストを位置引数にアンパック
commands = ["Punch", "Kick", "Chop"]
my_func(*commands)
# Punch, Kick, Chop

# 辞書をキーワード引数にアンパック
commands = {"a": "Punch", "b": "Kick", "c": "Chop"}
my_func(**commands)
# Punch, Kick, Chop
このスクラップは2ヶ月前にクローズされました