用于类方法和函数的装饰器

时间:2016-03-17 17:28:44

标签: python decorator

我有一位装饰师

def deco(func):
    def inner(params):
        #< DO STUFF WITH func >
    return inner

和基类

class GenericClass:
    def __init__(self,value):
        self.value = value
    def method(self,params):
        print 'NOT IMPLEMENTED YET'
    def other_method(self):
        print 'GOOD TO GO'

我希望能够在GenericClass的子类上修饰“方法”方法,例如检查输入/输出或处理异常(方法“方法”将被覆盖)

我想要做的就是......

class ChildClass(GenericClass):
    @deco
    def method(self,params):
        #< NEW METHOD >

我不是专家python开发人员,并且该级别的所有文档都非常令人困惑(即元类,装饰器中的细微之处,__call__方法等等)并且我没有在SO上找到解决方案。

2 个答案:

答案 0 :(得分:4)

知道了。您基本上是在询问如何编写可应用于函数和方法的装饰器。这是可能的:

def deco(func):
    def inner(*args):
        print('DECORATED: args={}'.format(args))
        func(*args)
    return inner

class Class:
    @deco
    def method(self, param): print('PARAM is {}'.format(param))

@deco
def func(a, b, c): print('{} {} {}'.format(a, b, c))

Class().method('X')

func(1, 2, 3)

<强>输出:

DECORATED: args=(<__main__.Class instance at 0x7f740c6297a0>, 'X')
PARAM is X
DECORATED: args=(1, 2, 3)
1 2 3

<强> P.S。

一年后,我在这里找到了一篇有用的帖子(8年前被问过):Using the same decorator (with arguments) with functions and methods。如果你关心装饰函数的实际参数,那么在那里描述的方法将是有用的。

答案 1 :(得分:1)

我明白了。诀窍是模块级函数(除了闭包,我猜,你可能不想装饰它)有一个简单的名称,而方法至少有两个部分在他们的限定名称。 忘记inspect.ismethod - 由于某种原因它在这种情况下不起作用,虽然它应该是明显的选择,可能是一个bug。

def can(*fargs):
    def wrapper(func):
        if len(func.__qualname__.split('.')) > 1:
            def calling(self, *args, **kwargs):
                self, thing = args[0], args[1]
                do_stuff(thing)
                func(*args, **kwargs)
        else:
            def calling(*args, **kwargs):
                thing = args[0]
                do_stuff(thing)
                func(*args, **kwargs)
        return calling
    return wrapper

class C:
    @can(2, 3)
    def test(self, x):
        print(7, ismethod(self.test), x)

@can()
def test(x):
    print(8, ismethod(test), x)

c = C()
c.test(12)

test(8)