类方法的python装饰器
Posted
技术标签:
【中文标题】类方法的python装饰器【英文标题】:python decorator for class methods 【发布时间】:2018-07-14 23:22:17 【问题描述】:我有一个装饰器来注册一些类方法。如何正确获取self
和run
参数?
Traceback(最近一次调用最后一次):
TypeError: wrapper() got multiple values for keyword argument 'run'
【问题讨论】:
您的代码没有您描述的错误。 (假设from functools import *
)
【参考方案1】:
您的问题与装饰器无关。以更简单的形式:您正在做的是:
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)
【讨论】:
我正在做的是我想将一个“运行”参数传递给装饰器,这将告诉装饰器注册任务或执行它。但我不想在我的类方法中添加这个“运行”参数,因为它在方法中什么都不做。在这种情况下,我应该如何传递/处理“运行”参数? 你可以使用我所说的foo
作为你的wrapper
函数。更改其签名并从kwargs
获取run
。这实际上是the other answer 已经详细建议的内容......
是的,这可能是一个解决方案。谢谢!【参考方案2】:
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
【讨论】:
【参考方案3】:Python3 似乎有更好的参数处理程序,但不知道如何在 python2 中执行此操作:
从 functools 导入包装 def optional_debug(func): @wraps(函数) def 包装器(*args,debug=False,**kwargs): 如果调试: print('调用', func.__name__) 返回函数(*args,**kwargs) 返回包装 @optional_debug 定义垃圾邮件(a,b,c): 打印(a,b,c) 垃圾邮件(1,2,3)#1,2,3 spam(1,2,3, debug=True) # 调用垃圾邮件 # 1 2 3【讨论】:
以上是关于类方法的python装饰器的主要内容,如果未能解决你的问题,请参考以下文章
32.Python面向对象描述符运算符底层装饰器:闭包-闭包参数-内置装饰器-类装饰器
32.Python面向对象描述符运算符底层装饰器:闭包-闭包参数-内置装饰器-类装饰器