webサイト制作、便利アプリ、Apple製品について考えるブログ

Python学習記録:関数内関数、クロージャー、デコレーター、ラムダ、ジェネレーター

2020年10月17日 2021年02月21日

プログラム言語Pythonを学んでいます。
その中で、あとで振り返ったときに覚えておいた方が良さそう、ということをピックアップしてまとめます。

1. 関数内関数

関数の中で関数を定義する。

def outer(a, b):
    def inner(c, d):
        return c + d
    r = inner(a, b)
    print(r)
    
outer(1, 2)

結果はこちら

3

outer関数を実行すると、まずその中でplus関数が呼ばれ、rをプリントしている。

使う場面

関数の中でしかその関数を使わない場合。

2. クロージャー

関数そのものを戻り値(return)にする。

# 円の面積を求める関数
def circle_area_func(pi):
    def circle_area(radius):
        return pi * radius * radius

    return circle_area

# パラメータが違う2パターンの関数をクロージャー関数として定義
ca1 = circle_area_func(3.14)
ca2 = circle_area_func(3.141592)

# パラメータが違う2パターンの関数をそれぞれ実行
print(ca1(10))
print(ca2(10))

結果はこちら

314.0
314.1592

使う場面

すぐ実行したくない時。
実行するタイミングを指定したい時。
引数を変えて違う条件で関数を処理したい時。

3. デコレーター

追加処理を定義した関数。
定義した関数名の前に「@」を付けてやると、それをデコレーターであると認識して、実行してくれる。
デコレーター関数の引数に実行したい関数を渡してあげる。
やりたい処理をデコレーターで包み込む。
一回定義してしまえば、使い回せる。

# print_infoがデコレーター関数
def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper


# 実行されるのはadd_num関数だが、その前にprint_info関数が呼ばれる
@print_info
def add_num(a, b):
    return a + b


r = add_num(10, 20)
print(r)

結果はこちら

start
end
30

使う場面

定義している関数に対して、何らか汎用的な追加処理を加えたい場合。

4. ラムダ

無名関数。
関数をシンプルに書く方法。

# 以下曜日のリストの頭の文字が大文字にする処理を考える
days = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'sat', 'sun']


# 引数の言葉を、func関数に渡して処理してください、という関数
def change_words(words, func):

    for word in words:
        print(func(word))

# 関数を別に定義せずに、「ラムダで関数化」したものを引数に放り込む
change_words(days, lambda word: word.capitalize())

結果はこちら

Mon
Tue
Wed
Thu
Fri
Sat
Sun

使う場面

関数を引数として使う必要があるが、新たにそれ用の関数を定義したくないとき。

5. ジェネレーター

yieldで個別の反復処理要素を定義。
繰り返し処理を拡張するもの。

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

使う場面

繰り返し処理の間に処理を挟み込みたい時。