Python資格取得への道のり 9日目
・複数のデコレーター(が残っていました)
def print_more(func):
def wrapper(*args, **kwargs):
print('func', func.__name__)
print('args', args)
print('kwargs', kwargs)
result = func(*args, **kwargs)
print('result', result)
return result
return wrapper
def print_info(func):
def wrapper(*args, **kwargs):
print('start')
r = func(*args, **kwargs)
print('end')
return r
return wrapper
@print_more
def add_num(a, b):
return a + b
print(add_num(20, 10))
#func add_num
#args (20, 10)
#kwargs {}
#result 30
#30
「@print_more」と「@print_info」を同時に表示させたい場合は、下記となる。
@print_info
@print_more
def add_num(a, b):
return a + b
print(add_num(20, 10))
#start
#func add_num
#args (20, 10)
#kwargs {}
#result 30
#end
#30
順番を一部変更するだけで結果は全く異なる結果になる。
@print_more
@print_info
def add_num(a, b):
return a + b
print(add_num(20, 10))
#func wrapper
#args (20, 10)
#kwargs {}
#start
#end
#result 30
#30
順番が重要である
・ラムダ
l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'Sat', 'sun']
def change_words(words, func):
for word in words:
print(func(word))
def sample_func(word):
return word.capitalize()
change_words(l, sample_func)
#Mon
#Tue
#Wed
#Thu
#Fri
#Sat
#Sun
「change_words(l, sample_func)」よりword = l を func = sample_funcを代入して代入して、print(sample_func(l))を行い、l内の単語の頭文字だけ大文字にしていく処理。
ラムダを使うと、
l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'Sat', 'sun']
def change_words(words, func):
for word in words:
print(func(word))
#def sample_func(word):
# return word.capitalize()
sample_func = lambda word: word.capitalize()
change_words(l, sample_func)
#で定義した2行を1行の「sample_func = lambda word: word.capitalize()」に集約することも可能
l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'Sat', 'sun']
def change_words(words, func):
for word in words:
print(func(word))
#def sample_func(word):
# return word.capitalize()
#sample_func = lambda word: word.capitalize()
change_words(l, lambda word: word.capitalize())
change_words(l, lambda word: word.lower())
上記でも同様の結果が得られる。
・ラムダの活用
l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'Sat', 'sun']
def change_words(words, func):
for word in words:
print(func(word))
change_words(l, lambda word: word.lower())
#mon
#tue
#wed
#thu
#fri
#sat
#sun
コード量を抑えた状態で、さらに関数を定義せず、処理が行える。
・ジェネレーター
l = ['Good morning','Good afternoon', 'Good night']
for i in l:
print(i)
print('##################')
def greeting():
yield 'Good morning'
yield 'Good afternoon'
yield 'Good night'
g = greeting()
print(next(g))
print("@@@@@@@@@@@")
print(next(g))
print("@@@@@@@@@@@")
print(next(g))
#Good morning
#Good afternoon
#Good night
##################
#Good morning
#@@@@@@@@@@@
#Good afternoon
#@@@@@@@@@@@
#Good night
for文でもlの中身を返してくれるが、間に異なる処理(上記だとprint("@@@@@@@@@@@")のような処理)が入ると、出力してくれない。
しかしジェネレーターを使用すれば、好きなタイミングでprint(next(g))を使い、出力ができる。どこまでのyieldまで処理したのかを覚えているのがジェネレーター。
もう1つの例として、
def counter(num=10):
for _ in range(num):
yield 'run'
def greeting():
yield 'Good morning'
yield 'Good afternoon'
yield 'Good night'
g = greeting()
c = counter()
print(next(g))
print(next(c))
print(next(c))
print(next(c))
print(next(c))
print(next(c))
print(next(g))
print(next(c))
print(next(c))
print(next(c))
print(next(c))
print(next(c))
print(next(g))
#Good morning
#run
#run
#run
#run
#run
#Good afternoon
#run
#run
#run
#run
#run
#Good night
2つのジェネレータを組み合わせて出力することも可能。
しかしこれ以上「print(next(c))」や「print(next(g))」をしてもエラーが返される。それはyieldで定義されていないからである。
・ジェネレーターの活用
def greeting():
yield 'Good morning'
for i in range(10):
print(i)
yield 'Good afternoon'
yield 'Good night'
g = greeting()
print(next(g))
#Good morning
「print(next(g))」が1つだけだと最初の処理のみですが、
def greeting():
yield 'Good morning'
for i in range(10):
print(i)
yield 'Good afternoon'
yield 'Good night'
g = greeting()
print(next(g))
print(next(g))
#Good morning
#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
#Good afternoon
最後の行にprint(next(g))を追加しただけで出力結果は異なります。
今日はここまで!
ラムダやジェネレーターなど段々面白いものが増えてきています。
「試験のために覚えなきゃ」ではなく、自分の武器を増やしていく気持ちに切り替えるだけで吸収力は変わってきますね。
明日は「リスト内包表記」から
いいかげんセクション5を終わらせて先に行かないと。。。
この記事が気に入ったらサポートをしてみませんか?