24

重複の可能性:
Python デコレータを理解する

私は Python デコレータを使用するのはまったく初めてであり、最初の印象で理解していることから、それらは単なるシンタックス シュガーにすぎません。

より複雑な用途のためのより深い用途はありますか?

4

2 に答える 2

18

はい、それは構文糖です。それらがなくてもすべてを実現できますが、コードを数行追加するだけです。しかし、より簡潔なコードを書くのに役立ちます。

例:

from functools import wraps

def requires_foo(func):
    @wraps(func)
    def wrapped(self, *args, **kwargs):
        if not hasattr(self, 'foo') or not self.foo is True:
            raise Exception('You must have foo and be True!!')
        return func(self, *args, **kwargs)
    return wrapped

def requires_bar(func):
    @wraps(func)
    def wrapped(self, *args, **kwargs):
        if not hasattr(self, 'bar') or not self.bar is True:
            raise Exception('You must have bar and be True!!')
        return func(self, *args, **kwargs)
    return wrapped

class FooBar(object):

    @requires_foo                 # Make sure the requirement is met.
    def do_something_to_foo(self):
        pass

デコレータを互いにチェーン/スタックすることもできます。

class FooBar(object):
    @requires_bar
    @requires_foo                 # You can chain as many decorators as you want
    def do_something_to_foo_and_bar(self):
        pass

OK、たくさんのデコレータが積み重なってしまう可能性があります。

知っている!他のデコレータを適用するデコレータを書きます。

したがって、これを行うことができます:

def enforce(requirements):
    def wrapper(func):
        @wraps(func)
        def wrapped(self, *args, **kwargs):
            return func(self, *args, **kwargs)
        while requirements:
            func = requirements.pop()(func)
        return wrapped
    return wrapper

class FooBar(object):
    @enforce([reguires_foo, requires_bar])
    def do_something_to_foo_and_bar(self):
        pass

これはただ遊ぶための小さなサンプルです。

于 2012-09-06T09:55:03.730 に答える
1

コードを非常に明示的にするので、デコレータの構文が本当に好きです

たとえば、Django には次の login_required デコレータがあります: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required

関数/ビューに @login_required 動作を挿入するには、デコレータをアタッチするだけです ( if: ... else: ... コントロール式をどこにでも配置するのとは対照的に)。

PEPを読んでください!

http://www.python.org/dev/peps/pep-0318/

行われた言語決定とその理由についての歴史を失ってしまった

于 2012-09-06T09:22:21.160 に答える