Program学習Python

Pythonの基礎③(関数応用:クロージャ/デコレータ/ラムダなど)

Program学習

Python基礎的な使い方について忘れ気味だったので自分ようにメモを残しておきます。

少し規模が大きいシステムではデコレータやラムダを使ってすっきり記載することができます。

Python関数応用:クロージャ/デコレータ/ラムダなど

関数内関数

・関数内部で利用するだけの関数

def outer(a, b):
    def plus(c, d):
        return c + d

    r1 = plus(a, b)
    r2 = plus(b, a)
    print(r1 + r2)

outer(1, 2)

// 結果
6

クロージャー

・後ほど実行したい関数などで利用
・関数のオブジェクトをリターンする

def outer(a, b):

    def inner():
        return a + b

    return inner
    
print( outer(1,2))

// 結果 inner関数のオブジェクト
<function outer.<locals>.inner at 0x00000246129DE700>

--------------------------------
f = outer(1,2)
r = f()
print(r)

// 結果
3
def circle_area_func(pi):
    def circle_area(radius):
        return pi * radius * radius

    return circle_area

ca1 = circle_area_func(3.14)
ca2 = circle_area_func(3.141592)

print(ca1(10))
print(ca2(10))

// 結果
314.0
314.1592

デコレータ

・関数の前後などで決まった動作をしたい場合に利用
・1回デコレータを作れば、多くの関数から利用することができる

// 第1段階
def add_num(a, b):
    return a + b

print('start')
r = add_num(10, 20)
print(r)
print('end')

// 結果
start
end
30

---------------------------------------
// 第2段階
def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

def add_num(a, b):
    return a + b

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

// 結果
start
end
30

---------------------------------------
// 第3段階
def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_info
def add_num(a, b):
    return a + b

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

・デコレータは2つ以上設定できる

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')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_info
@print_more
def add_num(a, b):
    return a + b

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

// 結果
start
func: add_num
args: (10, 20)
kwargs {}
result: 30
end
30

ラムダ

・Lamdaを使うことで簡単な関数などを1行で記載できる。

l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'sat', 'Sun']

// lambdaを使わない場合:関数Functionを受け取って処理する
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
-----------------------------------------

// lambdaを使った場合の書き方(1)
sample_func = lambda word: word.capitalize()
change_words(l,sample_func)

// lambdaを使った場合の書き方(2/3)
change_words(l,lambda word: word.capitalize())
change_words(l,lambda word: word.lower())

ジェネレーター

・ジェネレーターは、通常の関数の、return文をyieldに置き換えたもの
・ジェネレーターは呼び出されるたびに、行われた処理を記憶、ステートをもつ
・nextで順番に値を取得できる


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'
    
for g in greeting():
    print(g)

// 結果
Good morning
Good afternoon  
Good night      
################
Good morning    
Good afternoon  
Good night 


--------------------------------------------
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

・一度に処理しなくてもより場合などには有効
・yieldで返すアイテムがなくなるとエラーになる

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(c))

// 結果
Good morning
run
run
run
run
run
Good afternoon
run
run
run
run
run
Traceback (most recent call last):
  File "c:\PythonProject\aaaaaa.py", line 29, in <module>
    print(next(c))
StopIteration

Pythonのオススメ勉強方法

私がオススメするPython初心者向けの最初に購入すべき書籍は「シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全です。

シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全

この書籍は実際にシリコンバレーの一流エンジニアとして活躍している酒井潤さんが書いた本です。

内容も初心者から上級者までまとめられており、各Lessonも長すぎずに分かりやすくまとめられているので、初心者の方にもおすすめです。

シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全

今回は以上となります。

コメント