67

これは物事を少し進めすぎている可能性がありますが、ほとんどは好奇心からです..

コンテキストマネージャーとデコレーターの両方として同時に機能する呼び出し可能なオブジェクト (関数/クラス) を持つことは可能でしょうか?

def xxx(*args, **kw):
    # or as a class

@xxx(foo, bar)
def im_decorated(a, b):
    print('do the stuff')

with xxx(foo, bar):
    print('do the stuff')
4

5 に答える 5

60

Python 3.2 以降、これのサポートは標準ライブラリにも含まれています。クラスから派生contextlib.ContextDecoratorすることで、デコレーターまたはコンテキスト マネージャーの両方として使用できるクラスを簡単に作成できます。この機能は、Python 2.x に簡単に移植できます。基本的な実装は次のとおりです。

class ContextDecorator(object):
    def __call__(self, f):
        @functools.wraps(f)
        def decorated(*args, **kwds):
            with self:
                return f(*args, **kwds)
        return decorated

このクラスからコンテキスト マネージャーを派生させ、通常どおりメソッド__enter__()とメソッドを定義します。__exit__()

于 2012-02-09T15:26:51.150 に答える
15
class Decontext(object):
    """
    makes a context manager also act as decorator
    """
    def __init__(self, context_manager):
        self._cm = context_manager
    def __enter__(self):
        return self._cm.__enter__()
    def __exit__(self, *args, **kwds):
        return self._cm.__exit__(*args, **kwds)
    def __call__(self, func):
        def wrapper(*args, **kwds):
            with self:
                return func(*args, **kwds)
        return wrapper

今、あなたはできる:

mydeco = Decontext(some_context_manager)

そしてそれは両方を可能にします

@mydeco
def foo(...):
    do_bar()

foo(...)

with mydeco:
    do_bar()
于 2012-02-09T15:38:10.320 に答える
8

次に例を示します。

class ContextDecorator(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
        print("init", foo, bar)

    def __call__(self, f):
        print("call")
        def wrapped_f():
            print("about to call")
            f()
            print("done calling")
        return wrapped_f

    def __enter__(self):
        print("enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")

with ContextDecorator(1, 2):
    print("with")

@ContextDecorator(3, 4)
def sample():
    print("sample")

sample()

これは以下を出力します:

init 1 2
enter
with
exit
init 3 4
call
about to call
sample
done calling
于 2012-02-09T15:35:03.737 に答える