functools.wraps
,以便其具有适当的自省和组织功能,以备后用。wrapped_self
参数传递给__call__
方法来实现这一目的。理想情况应如下所示:
class A():
def __init__(self):
...
@LoggerDecorator(logger_name='test.log')
def do_something(self):
...
到目前为止,装饰器类是(基于David Beazley's Python Cookbook的配方的基本记录器装饰器):
class LoggerDecorator():
def __init__(self, func, logger_name):
wraps(func)(self)
self.logger_name = logger_name
def config_logger(self):
... # for example, uses `self.logger_name` to configure the decorator
def __call__(self, wrapped_self, *args, **kwargs):
self.config_logger()
wrapped_self.logger = self.logger
func_to_return = self.__wrapped__(wrapped_self, *args, **kwargs)
return func_to_return
def __get__(self, instance, cls):
if instance is None:
return self
else:
return types.MethodType(self, instance)
我遇到的错误是指__init__
显然没有识别出第三个参数:
TypeError: __init__() missing 1 required positional argument: 'func'
有人建议我将func
放在__call__
方法中。但是,如果我将它放在那里作为参数,则wrapped_self
不能正确地作为参数读取,并且会出现此错误:
__call__() missing 1 required positional argument: 'wrapped_self'
我已经尝试了许多方法来解决此问题,包括:将wraps(func)(self)
放在__call__
内;以及this very close but not quite filling all of the requirements solution的许多变体(问题是我似乎无法再访问wrapped_self
)。
答案 0 :(得分:3)
由于您正在实现带有参数的装饰器,因此__init__
的{{1}}方法应仅采用配置装饰器的参数,而LoggerDecorator
方法应变为实际的装饰器,返回包装函数:
__call__
答案 1 :(得分:0)
from functools import wraps
class LoggerDecorator:
def __init__(self, logger):
self.logger = logger
def __call__(self, func, *args, **kwargs):
print func, args, kwargs
# do processing
return func
@LoggerDecorator('lala')
def a():
print 1
以上内容应该可以正常工作。如果您打算使用关键字参数来调用装饰器,则可以从logger
中删除__init__
并使用**kwargs
,这将返回所传递的键盘参数的字典。