数弱の文系大学生によるブログです。

Python、Webデザイン関連の記事を投稿していけたらなと思っています。

備忘録的なブログなので、読みにくい文章だと思います。ご了承ください。

Python3の復習(デコレータ)

こんにちは。

かにたまごです。
怒涛の復習ラッシュです。


今回は

  • デコレータ

について、復習していきたいと思います。

・・・ちょっと前から思ってたけど、初めて知ること多いから復習じゃないな。
でも途中から題名変更するのは気持ち悪いので、このまま進めていきます。


今までのPython3 復習履歴は以下の通り。

  1. 数値・文字列
  2. リスト・タプル
  3. 辞書・集合
  4. if文・while文・for文
  5. 内包表記
  6. 関数
  7. ジェネレータ

デコレータ

一度定義した関数に変更を加えたい場合、ソースコードを書き換えるのは面倒だ。
そんな時、デコレータを使うことで既存の関数を書き換えずに処理を付け加えたり、変更したりすることができる。

デコレータのポイントは以下の3つ。

  • *argsとkwargs
  • 関数内関数
  • 引数としての関数


以前の記事で少し書いた覚えがあるが、ログインチェックを例にデコレータを理解していこうと思う。

def login_check(func):
    def inner_function(*args, **kwargs):
        #ユーザー名とパスワードの二つが入力されていた場合
        if len(args) == 2:
            func(*args)
        #それ以外はスルー
        else:
           pass
    return inner_function

def login(user_name, password):
    print("ログインしました")

login_obj = login_check(login)

#二つとも入力されている場合
login_obj("かにたまご", "473975032")

出力 ->
ログインしました


#どちらか一方の値が渡されていない場合
login_obj("かにたまご")

出力 ->
(なし)

かなりガバガバなコードだけど、こんな感じかな・・・?
ここで気になることは、毎回のログインチェック時に

login_obj = login_check(login)

を書かなきゃいけないってこと。
つまり、デコレートしてくれる関数の戻り値を毎回受け取らないといけない。非常に面倒。

この面倒さを一瞬で吹き飛ばしてくれるのが "@デコレータ名" の存在。
いわゆるシンタックスシュガーと呼ばれるもの。

シンタックスシュガーって何ぞやって思った僕みたいな方のために。

糖衣構文(とういこうぶん、英: syntactic sugarあるいはsyntax sugar)は、プログラミング言語において、読み書きのしやすさのために導入される書き方であり、複雑でわかりにくい書き方と全く同じ意味になるものを、よりシンプルでわかりやすい書き方で書くことができるもののことである。構文上の書き換えとして定義できるものであるとも言える。

糖衣構文・・・。「なんか甘そう・・・」って思った僕みたいな方のために。

語源は「取り扱いやすい」を意味するsweetの第一義が「(砂糖のように)甘い」であることから。

数弱に限らず英弱の僕はsweetにそんな意味があるなんて知らなかった。


まぁそれは置いておいて、さっそく試してみよう。

@login_check
def login(user_name, password):
    print("ログインしました")

#二つとも入力されている場合
login("かにたまご", "759832758")

出力 ->
ログインしました


#どちらか一方の値が渡されていない場合
login("かにたまご")

出力 ->
(なし)

すげえ。


複数のデコレータを使うこともできる。
先ほどのコードに、お忘れですかページを表示させるコードをデコレートしてみる。

def login_check(func):
    def inner_function(*args, **kwargs):
        #ユーザー名とパスワードの二つが入力されていた場合
        if len(args) == 2:
            #loginを実行する
            func(*args)
        else:
            pass
    return inner_function

def show_support(func):
    def inner_function(*args, **kwargs):
        #片方のみの入力の場合
        if len(args) <= 1 or "" in args:
            print("ログインエラー")
            print("お忘れですかページを表示する")
        else:
            #login_checkのinner_function実行する
            func(*args)
    return inner_function

@show_support
@login_check
def login(user_name, password):
    print("ログインしました")

#二つとも入力されている場合
login("かにたまご", "50328059")

出力 ->
ログインしました


#どちらか一方の値が渡されていない場合、あるいはどちらか一方が空白の場合
login("かにたまご", "")

出力 ->
ログインエラー
お忘れですかページを表示する

流れとしては

  1. login_checkの引数にloginが入る
  2. login_checkに修飾されたloginがshow_supportに入る
  3. show_supportの関数内関数で入力チェック
  4. 入力漏れが合った場合はお忘れですかページを表示
  5. 問題ない場合はlogin_checkのinner_functionを実行
  6. login_checkに渡されたloginを実行

という感じ?コード追ってたら頭クラクラしてきた(´ー`)


ちゃんと書けているのか不安だ・・・。
それデコレータ使う意味ある?って感じのコードになってる気がする。
もう少し他の人のコード見て勉強しよ。


以上です。