类方法的python装饰器
我有一个装饰器来注册一些类的方法。 我怎样才能正确地获得self和run参数?
class Task(object):
_tasks = []
@staticmethod
def register(name):
def decorator(fn):
@wraps(fn)
def wrapper(self=None, run=True, *args, **kwargs):
if not run:
task = defaultdict()
task['name'] = name
task['fn'] = getattr(self, fn.__name__, None)
task['obj'] = self
task['args'] = deepcopy(args)
task['kwargs'] = deepcopy(kwargs)
Task._tasks.append(task)
else:
return fn(self, *args, **kwargs)
return wrapper
return decorator
class Test(object):
def __init__(self, name):
self.name = name
@Task.register('foo')
def foo(self, v1, v2):
print 'running foo in object {} with arguments {} {}'.format(self.name, v1, v2)
@Task.register('hello')
def hello(self):
print 'running hello in object {} '.format(self.name)
def load(self):
self.foo('1', '2', run=False)
self.hello(run=False)
t1=Test('t1')
t1.load()
回溯(最近一次通话最后):
TypeError: wrapper() got multiple values for keyword argument 'run'
运行参数来自乐趣,所以尝试从函数的参数中获取它:
from collections import defaultdict
from copy import deepcopy
from functools import wraps
class Task(object):
_tasks = []
@staticmethod
def register(name):
def decorator(fn):
@wraps(fn)
def wrapper(self=None, *args, **kwargs):
run = kwargs.pop('run', True)
if not run:
task = defaultdict()
task['name'] = name
task['fn'] = getattr(self, fn.__name__, None)
task['obj'] = self
task['args'] = deepcopy(args)
task['kwargs'] = deepcopy(kwargs)
Task._tasks.append(task)
else:
return fn(self, *args, **kwargs)
return wrapper
return decorator
你的问题与装饰者无关。 以一种更简单的形式:你正在做的是这样的:
def foo(run=False, *args, **kwargs):
print(run, args, kwargs)
foo(1, 2, run=True) # TypeError: foo() got multiple values for argument 'run'
从你的函数签名中,python会尝试设置run=1 , args = (2,) ,然后运行到TypeError 。
一个修复 - 虽然不是一个很好的 - 可能是:
def foo(*args, **kwargs):
run = kwargs.pop('run', False) # run defaults to False; remove from kwargs
print(run, args, kwargs)
Python3似乎有更好的hanlder参数,但不知道如何在python2中做到这一点:
from functools import wraps
def optional_debug(func):
@wraps(func)
def wrapper(*args, debug=False, **kwargs):
if debug:
print('Calling', func.__name__)
return func(*args, **kwargs)
return wrapper
@optional_debug
def spam(a,b,c):
print(a,b,c)
spam(1,2,3) # 1,2,3
spam(1,2,3, debug=True) # Calling spam # 1 2 3
链接地址: http://www.djcxy.com/p/28565.html
