How to pass an argument to a method decorator
我有一个这样的方法装饰师。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class MyClass: def __init__(self): self.start = 0 class Decorator: def __init__(self, f): self.f = f self.msg = msg def __get__(self, instance, _): def wrapper(test): print(self.msg) print(instance.start) self.f(instance, test) return self.f return wrapper @Decorator def p1(self, sent): print(sent) c = MyClass() c.p1('test') |
这个很好用。但是,如果我想向decorator传递一个参数,该方法将不再作为参数传递,并且我得到以下错误:
TypeError: init() missing 1 required positional argument: 'f'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class MyClass: def __init__(self): self.start = 0 class Decorator: def __init__(self, f, msg): self.f = f self.msg = msg def __get__(self, instance, _): def wrapper(test): print(self.msg) print(instance.start) self.f(instance, test) return self.f return wrapper @Decorator(msg='p1') def p1(self, sent): print(sent) @Decorator(msg='p2') def p2(self, sent): print(sent) |
如何将参数传递给decorator类,为什么它要重写该方法?
描述符协议在这里没有多大作用。您只需将函数本身传递给
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class MyClass: def __init__(self): self.start = 0 class Decorator: def __init__(self, msg): self.msg = msg def __call__(self, f): def wrapper(instance, *args, **kwargs): print(self.msg) # access any other instance attributes return f(instance, *args, **kwargs) return wrapper @Decorator(msg='p1') def p1(self, sent): print(sent) >>> c = MyClass() >>> c.p1('test') p1 test |
将调用一个装饰器。
在您的情况下,您将在
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 | class MyClass: def __init__(self): self.start = 0 class Decorator: def __init__(self, msg): self.msg = msg def __call__(self, f): self.f = f return self def __get__(self, instance, _): def wrapper(test): print(self.msg) self.f(instance, test) return self.f return wrapper @Decorator(msg='p1') def p1(self, sent): print(sent) @Decorator(msg='p2') def p2(self, sent): print(sent) |
第一个例子是因为调用
但在第二个示例中,您手动调用
当使用参数调用decorator时,您调用的函数实际上并不是作为decorator本身工作的。相反,它是一个装饰工厂(一个函数或其他可调用的,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class MyClass: def __init__(self): self.start = 0 def decorator_factory(msg): def decorator(f): def wrapper(self, test): # you might want to replace test with *args and **kwargs print(msg) print(self.start) return f(self, test) return wrapper return decorator @decorator_factory(msg='p1') def p1(self, sent): print(sent) @decorator_factory(msg='p2') def p2(self, sent): print(sent) |
我对decorator工厂的命名方式与我对不同层次嵌套函数的明确命名方式相同,但是您当然应该使用一些对您的用例有实际意义的东西作为顶级名称。您可能还希望将其移出类命名空间,因为它可以调用EDOCX1的所有实例(可能有愚蠢的结果,因为它不打算是一个方法)。