[英]python decorator for class methods
我有一個裝飾器來注冊一些類方法。 如何正確獲取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'
你的問題與裝飾者無關。 以更簡單的形式:您正在做的是:
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)
run 參數來自於 fun,所以嘗試從函數的參數中獲取它:
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
Python3 似乎對參數有更好的處理,但不知道如何在 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.