Python类中的装饰器

220

有没有可能写出这样的代码:

class Test(object):
    def _decorator(self, foo):
        foo()

    @self._decorator
    def bar(self):
        pass

这个失败了:@self 中的 self 是未知的。

我还尝试过:

@Test._decorator(self)

也失败了:测试未知

我想暂时更改装饰器中的一些实例变量,然后运行装饰方法,再将它们改回来。

14个回答

3
我有一个装饰器的实现,可能会对你有所帮助。
    import functools
    import datetime


    class Decorator(object):

        def __init__(self):
            pass


        def execution_time(func):

            @functools.wraps(func)
            def wrap(self, *args, **kwargs):

                """ Wrapper Function """

                start = datetime.datetime.now()
                Tem = func(self, *args, **kwargs)
                end = datetime.datetime.now()
                print("Exection Time:{}".format(end-start))
                return Tem

            return wrap


    class Test(Decorator):

        def __init__(self):
            self._MethodName = Test.funca.__name__

        @Decorator.execution_time
        def funca(self):
            print("Running Function : {}".format(self._MethodName))
            return True


    if __name__ == "__main__":
        obj = Test()
        data = obj.funca()
        print(data)

2
使用静态方法,并在装饰器的内部函数(wrapper)中包含一个额外的参数(self)。
import functools 

class Test:

@staticmethod
def _decorator(f):

    @functools.wraps(f)
    def _wrapper(self, *args, **kwargs):
        # do some serious decorating (incl. calls to self!)
        print(self)

        return f(self, *args, **kwargs)

    return _wrapper

@_decorator
def bar(self):
    return 42

1
你可以装饰装饰器:
import decorator

class Test(object):
    @decorator.decorator
    def _decorator(foo, self):
        foo(self)

    @_decorator
    def bar(self):
        pass

0
对于Python 3和为了代码检查的缘故
def methoddecorator(deco: Callable[[Any, Callable], Callable]):
"""
Decorator to implement method decorators in the same class

Example of usage:

    class A:
        @methoddecorator
        def my_methods_deco(self, method):
            @wraps(method)
            def wrapper(this: 'A', *args, **kwargs):
                # do smth
                # N.B. for instance access use this, not self!
                return method(this, *args, **kwargs)
            return wrapper

        @my_methods_deco
        def my_method(self, a, b):
            ...

"""
@functools.wraps(deco)
def wrapped_deco(method):
    return deco(NotImplemented, method)
return wrapped_deco

使用这个超级装饰器来修补类。
顺便说一下,这段代码不支持像@deco(param=...)这样的装饰器参数,但是更复杂的代码可以支持。
def methoddecorator(deco):
"""
Decorator to implement method decorators in the same class
Supports optionally parametrized decorators

Example of usage:

    class A:
        @methoddecorator
        def my_methods_deco(self, _method=None, param1=None, param2=None):
            @wraps(method)
            def wrapper(this: 'A', *args, **kwargs):
                # do smth
                # deco params are also available here
                return method(this, *args, **kwargs)
            return wrapper

        @my_methods_deco
        def my_method1(self, a, b):
            ...

        @my_methods_deco(param1=11, param2=12)
        def my_method2(self, a, b):
            ...

"""
@wraps(deco)
def wrapped_deco(_method=None, **kwargs):
    return (
        deco(NotImplemented, _method)
        if _method is not None
        else partial(deco, NotImplemented, **kwargs)
    )
return wrapped_deco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接