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ヶ月前にクローズされました