パラメータ付きアクセラレータを定義するには

1665 ワード

パラメータ付きアクセラレータを定義するには
に質問
パラメータを受け入れる装飾器を定義したいのですが
ソリューション
パラメータを受け入れる処理過程を一例で詳細に述べた.デザイナを書き、関数にログ機能を追加し、ユーザーがログのレベルと他のオプションを指定できるようにするとします.以下に、この装飾品の定義と使用例を示します.
from functools import wraps
import logging

def logged(level, name=None, message=None):
    """
    Add logging to a function. level is the logging
    level, name is the logger name, and message is the
    log message. If name and message aren't specified,
    they default to the function's module and name.
    """
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, logmsg)
            return func(*args, **kwargs)
        return wrapper
    return decorate

# Example use
@logged(logging.DEBUG)
def add(x, y):
    return x + y

@logged(logging.CRITICAL, 'example')
def spam():
    print('Spam!')


最初は、このような実現は複雑に見えたが、核心思想は簡単だった.最外層の関数logged()は、パラメータを受け入れ、内部の装飾関数に作用する.内層の関数decorate()は、パラメータとして関数を受け入れ、その後、関数の上にパッケージを配置する.ここで重要な点は、パッケージがlogged()に渡されるパラメータを使用することができることである.
ディスカッション
パラメータを受け入れるパッケージを定義するのは、主に最下位の呼び出しシーケンスのために複雑に見えます.特に、次のコードがあれば、
@decorator(x, y, z)
def func(a, b):
    pass


装飾器の処理過程は以下の呼び出しと等価である.
def func(a, b):
    pass
func = decorator(x, y, z)(func)

decorator(x, y, z)の戻り結果は、パラメータとして関数を受け入れてパッケージする呼び出し可能なオブジェクトである必要があります.9.7節の他のパラメータを受け入れるパッケージの例を参照してください.