关于python:装饰器的问题,带有包装类方法的参数

Problems with decorator with arguments to wrap class method

我正试图用包装特定类的方法的参数编写一个装饰器。我尝试了函数和类修饰器,但遇到了不同的错误。玩弄签名的争论没有帮助。

示例用法

1
2
3
4
5
6
7
8
9
10
11
class X(object):
    def __init__():
        self.a = True
        self.b =""

    @my_deco([])
    def xfunc(self, x, y):
        do stuff...

foo = X()
foo.xfunc()

函数修饰器:

1
2
3
4
5
6
7
8
9
10
11
12
def my_deco(param1):
    def wrapped(func):
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return func(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return param1
        return wrapped_f
    return wrapped

给出此错误:typeError:wrapped()只接受1个参数(给定3个)

类修饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class my_deco(object):

    def __init__(self, param1=False):
        self.param1 = param1

    def __call__(self, f):

        @wraps(f)
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return f(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return self.param1
        return wrapped_f
    #
    #def __get__(self, obj, objtype):
    #   """Support instance methods."""
    #    import functools
    #    return functools.partial(self.__call__, obj)

给出此错误:typeerror:call()只接受2个参数(给定3个)

有什么线索可以让这个工作吗?


在尝试创建可运行的代码作为示例发布时,我遇到了错误。可能是在写包装纸的时候弄混了,为了让它工作,我忽略了一个简单的错误。

下面是工作示例。我犯的错误是,我没有为正在测试的方法向修饰器传递参数,因此导致了异常。这解释了这个问题,因为装饰器需要一个参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def my_deco(param1):
    def wrapped(func):
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return func(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return param1
        return wrapped_f
    return wrapped

class Base(object):
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2
        self.a = False
        self.b =""

    @my_deco([])
    def xfunc(self, x, y):
        return x + y

def ClassFactory(attr1, attr2, base=Base):
    class NewClass(Base):
        def __init__(self):
            super(NewClass, self).__init__(attr1, attr2)

    return NewClass

ChildClass = ClassFactory("foo","bar")
child = ChildClass()

print child.xfunc(1, 2) # no exception
print child.xfunc('x', 2) # throws exception