Python デコレータ

巴扎黑
リリース: 2016-12-09 13:31:33
オリジナル
1290 人が閲覧しました

含まれるもの:

1、decorators

2、functools


まず、tornado で使用されるデコレータ
1、@tornado.web.authenticated を見てみましょう

引用

これでメソッドを修飾して要求しますユーザーがログインしていることを確認します。


Python コード

def authenticated(method):  
    """Decorate methods with this to require that the user be logged in."""  
    @functools.wraps(method)  
    def wrapper(self, *args, **kwargs):  
        if not self.current_user:  
            if self.request.method in ("GET", "HEAD"):  
                url = self.get_login_url()  
                if "?" not in url:  
                    if urlparse.urlsplit(url).scheme:  
                        # if login url is absolute, make next absolute too  
                        next_url = self.request.full_url()  
                    else:  
                        next_url = self.request.uri  
                    url += "?" + urllib.urlencode(dict(next=next_url))  
                self.redirect(url)  
                return  
            raise HTTPError(403)  
        return method(self, *args, **kwargs)  
    return wrapper
ログイン後にコピー


次のコードでは、ユーザーのログイン方法を検証する必要があります。このデコレーターを使用すると、繰り返し行われる多くの検証コードを簡素化できます。 @tornado.web.authenticated をメソッドに追加するだけでOKです。
2. @tornado.web.asynchronous

Python コード

def asynchronous(method):  
    @functools.wraps(method)  
    def wrapper(self, *args, **kwargs):  
        if self.application._wsgi:  
            raise Exception("@asynchronous is not supported for WSGI apps")  
        self._auto_finish = False  
        with stack_context.ExceptionStackContext(  
            self._stack_context_handle_exception):  
            return method(self, *args, **kwargs)  
    return wrapper
ログイン後にコピー


このデコレーターは self._auto_finish を False に設定します。
次に、単一インタレスト モード デコレーターを作成しましょう:

Python コード

def singleton(cls):  
    instances = {}  
    def get_instance():  
        if cls not in instances:  
            instances[cls] = cls()  
        return instances[cls]  
    return get_instance  
 
@singleton  
class Foo:  
    def __init__(self):  
        pass  
  
class Bar:  
    def __init__(self):  
        pass  
  
f = Foo()  
m = Foo()  
print f,m,f == m  
  
a = Bar()  
b = Bar()  
print a,b,a == b
ログイン後にコピー


結果は次のとおりです:
<__main__.Foo インスタンス at 0x103152c20<__main__.Foo インスタンス at 0x103152c20> True
< __main__ .Bar 0x103152c68 のインスタンス> <__main__.Bar 0x103152cb0 のインスタンス> False
@singleton このデコレータはクラスのシングルトン モードを実装し、クラスが 1 回だけインスタンス化されるようにします。

デコレータを使用してパラメータとメソッドの戻り結果を確認します:

Python コード

#-*-coding:utf-8-*-  
  
def accepts(*types):  
    def check_accepts(f):  
#        assert len(types) == f.func_code.co_argcount  
        def new_f(*args, **kwds):  
            for (a, t) in zip(args, types):  
                assert isinstance(a, t), \  
                       "arg %r does not match %s" % (a,t)  
            return f(*args, **kwds)  
        new_f.func_name = f.func_name  
        return new_f  
    return check_accepts  
  
def returns(rtype):  
    def check_returns(f):  
        def new_f(*args, **kwds):  
            result = f(*args, **kwds)  
            assert isinstance(result, rtype), \  
                   "return value %r does not match %s" % (result,rtype)  
            return result  
        new_f.func_name = f.func_name  
        return new_f  
    return check_returns  
 
@accepts(int, (int,float))  
@returns((int,float))  
def func(arg1, arg2):  
    return arg1 * arg2  
  
print func(1,2.0)
ログイン後にコピー



Python コード

def check_param_isvalid():  
    def check(method):  
        def check_param(*args,**kwargs):  
            for a in args:  
                assert isinstance(a, int),"arg %r does not match %s" % (a,int)  
                assert a > 100000,"arg %r must gt 100000" % a  
            return method(*args, **kwargs)  
        return check_param  
    return check  
 
@check_param_isvalid()  
def foo(*args):  
    print args  
  
foo(200000,5000)
ログイン後にコピー


result:
assert a > 100000,"arg %r should gt 100 000" %a
AssertionError: arg 5000 must gt 100000

Quote

設計目標:

新しい構文は、ユーザー定義の呼び出し可能オブジェクトや既存の組み込みの classmethod() および staticmethod() を含む任意のラッパーで機能する必要がありますこれこの要件は、デコレータ構文がラッパー コンストラクターへの引数の受け渡しをサポートする必要があることも意味します
* 定義ごとに複数のラッパーを処理します
* 何が起こっているかを明確にする 少なくとも、新しいユーザーがそれを作成するときに安全に無視できることは明らかである必要があります。独自のコード
* 「一度説明すると覚えやすい」構文であること
* 将来の拡張を難しくしないこと
* それを使用するプログラムは、非常に頻繁に使用することが期待されるため、入力しやすいこと
* ではないコードをすばやくスキャンすることはより困難になりますが、すべての定義、特定の定義、または関数が受け入れる引数を検索するのは簡単でなければなりません
* 言語に依存するエディターやその他の「おもちゃ」などの二次サポート ツールを不必要に複雑にしないでください。パーサー ツールが世に出ています [12]"
* 将来のコンパイラーがデコレーター用に最適化できるようにします。Python 用の JIT コンパイラーがいつか登場することを期待して、関数定義の前にデコレーターの構文が必要になる傾向があります
* move現在隠されている機能の終わりから、もっと前面に出てくるところまで [13]


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート