Python Decorator引数付きPython Decoratorチュートリアル


あなたが本当に深いダイビングをしたいならば、あなたはこれらのexhaustive articlesによって読まなければなりません...しかし、あなたが始めて、Python装飾者を読んで/書くことでよりよくなるつもりであるならば、この記事は十分でなければなりません.
すべてはPythonでさえ、オブジェクトでもオブジェクトです.関数は変数に代入でき、別の関数に渡され、別の関数から返される.以下の例を見てください.
[1]: def outer_function():
   ...:     print "1. This is outer function!"
   ...:     def inner_function():
   ...:         print "2. This is inner function, inside outer function!"
   ...:     print "3. This is outside inner function, inside outer function!"
   ...:     return inner_function()
   ...:

[2]: func_assign = outer_function()
1. This is outer function!
3. This is outside inner function, inside outer function!
2. This is inner function, inside outer function!
上記の実行では、内部関数の内部のステートメントを最後に、どのようにinnerlose関数を返すか、outerRange関数の末尾に表示し、実行中に実行を見ることができます.
Python Decoratorは関数を引数として受け取り、他の関数を戻り値として返す関数です.デコレータに対する仮定は、引数として関数を渡し、デコレータの内部関数のシグネチャは、装飾する関数と一致する必要があります.

関数デコレータ
では、簡単な関数デコレータを自分で書きましょう.渡された関数の実行時間を測定するデコレータを書きます.
import time

def timetest(input_func):

    def timed(*args, **kwargs):

    start_time = time.time()
    result = input_func(*args, **kwargs)
    end_time = time.time()
    print "Method Name - {0}, Args - {1}, Kwargs - {2}, Execution Time - {3}".format(
        input_func.__name__,
        args,
        kwargs,
        end_time - start_time
    )
    return result
    return timed


@timetest
def foobar(*args, **kwargs):
    time.sleep(0.3)
    print "inside foobar"
    print args, kwargs

foobar(["hello, world"], foo=2, bar=5)

inside foobar
(['hello, world'],) {'foo': 2, 'bar': 5}
Method Name - foobar, Args - (['hello, world'],), Kwargs - {'foo': 2, 'bar': 5}, Execution Time - 0.30296087265
関数foobarをtimetestという名前の修飾子に渡しました.内部デコレータでは、関数foobarは変数InputHound funcとして参照されます.その結果、inputCount funcの後実行を参照する.
デコレータの名前にprepending @と、関数の上に同じを書くと、デコレータを呼び出し、その関数をデコレータに渡します.

メソッドデコレータ
メソッドDecoratorは、呼び出し元の関数を見つけ出さずに、クラスプロパティを装飾することでオーバーライドできます.
def method_decorator(method):

    def inner(city_instance):
    if city_instance.name == "SFO":
        print "Its a cool place to live in."
    else:
        method(city_instance)
    return inner


class City(object):

    def __init__(self, name):
    self.name = name

    @method_decorator
    def print_test(self):
    print self.name

p1 = City("SFO")

p1.print_test()

Its a cool place to live in.
上に示したスニペットでは、クラスメソッドPrintRank Testを飾ります.都市インスタンスの名前がSFOでないならば、MethodCount Decoratorは都市名を印刷します.

クラスデコレータ
他のcallableを返すcallableを作成する場合は、関数のデコレータメソッドは簡単です.戻り値を関数としたい場合は、関数のデコレータを使用する必要があります.ただし、デコレータに関数とは異なるものを返すカスタムオブジェクトを返す場合は、クラスのデコレータを使用する必要があります.
クラスを使用すると、装飾された呼び出し可能オブジェクトにメソッドとプロパティを追加したり、操作を実装できます.クラスに配置するときに特別な方法で記述するディスクリプタを作成することができます(例: classmethod , property )
class decoclass(object):

    def __init__(self, f):
    self.f = f

    def __call__(self, *args, **kwargs):
    # before f actions
    print 'decorator initialised'
    self.f(*args, **kwargs)
    print 'decorator terminated'
    # after f actions

@decoclass
def klass():
    print 'class'

klass()

連鎖装飾者
デコレータの連鎖は、複数の継承を使用して、多くのデコレータとして書くことができるクラスを構築するために使用できる方法に似ており、装飾の対象となる関数の定義の前に、デコレーション列を使用してデコレーション列を1つずつ含めることができます.
def makebold(f):
    return lambda: "<b>" + f() + "</b>"
def makeitalic(f):
    return lambda: "<i>" + f() + "</i>"

@makebold
@makeitalic
def say():
    return "Hello"

print say()
一つのことを念頭に置いておく必要がありますデコレータの順序を設定します.チェーンのデコレータを使用すると、スタックされている順番が一番下になります.

ファンクションとラップ
デコレータを使用するとき、我々は1つの機能を別のものと交換しています.
def decorator(func):
    """decorator docstring"""
    def inner_function(*args, **kwargs):
    """inner function docstring """
    print func.__name__ + "was called"
    return func(*args, **kwargs)
    return inner_function


@decorator
def foobar(x):
    """foobar docstring"""
    return x**2
名前とdocstringを印字しようとすると、次のようになります
print foobar.__name__
print foobar.__doc__

inner_function
inner function docstring
上記の観察は、機能foobarがInnerLight機能によって取り替えられていると結論するように導きます.これは、渡されている関数に関する情報を失っていることを意味します.ファンクションツールラップは、我々の救出に来ます.これはデコレータで使用される関数を受け取り、関数名、docstring、argemnetなどをコピーする機能を追加します.
from functools import wraps

def wrapped_decorator(func):
    """wrapped decorator docstring"""
    @wraps(func)
    def inner_function(*args, **kwargs):
    """inner function docstring """
    print func.__name__ + "was called"
    return func(*args, **kwargs)
    return inner_function


@wrapped_decorator
def foobar(x):
    """foobar docstring"""
    return x**2

print foobar.__name__
print foobar.__doc__

foobar
foobar docstring
上記の実装は、デコレータに渡される関数に関する情報を保持します.
どのようにクラスベースのデコレータ内のキャッシング情報について行きますか?
コメントでは、より多くの実装を参照してください.

引数を持つ装飾子
引数付き関数デコレータ
from functools import wraps

def decorator(arg1, arg2):

    def inner_function(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print "Arguements passed to decorator %s and %s" % (arg1, arg2)
        function(*args, **kwargs)
    return wrapper
    return inner_function


@decorator("arg1", "arg2")
def print_args(*args):
    for arg in args:
    print arg

 print print_args(1, 2, 3)

 Arguements passed to decorator arg1 and arg2
 1
 2
 3

引数を持つクラスベースのデコレータ
class ClassDecorator(object):

    def __init__(self, arg1, arg2):
    print "Arguements passed to decorator %s and %s" % (arg1, arg2)
    self.arg1 = arg1
    self.arg2 = arg2

    def __call__(self, foo, *args, **kwargs):

    def inner_func(*args, **kwargs):
        print "Args passed inside decorated function .%s and %s" % (self.arg1, self.arg2)
        return foo(*args, **kwargs)
    return inner_func


@ClassDecorator("arg1", "arg2")
def print_args(*args):
    for arg in args:
    print arg


 print_args(1, 2, 3)
 Arguements passed to decorator arg1 and arg2
 Args passed inside decorated function .arg1 and arg2
 1
 2
 3
どのように、あなたは任意の引数で装飾子を実装することについて行きますか?
SO Postに従ってみてください.
あなたはWrapt Libraryをさらに探検したいかもしれません.
記事はもともとApcelent Tech Blogに掲載された.