python - 如何围绕另一个类方法包装装饰器?
问题描述
我创建了一个用于管理日志记录的装饰器。我希望在装饰函数运行之前和之后进行日志记录。该函数在与非常基本的函数交互时工作正常,但是,当与作为其他类的一部分的方法交互时,事情就会中断。我怀疑这个问题是有两个self
论点的结果。你知道如何解决它吗?
简化的装饰器类
class Logger:
def __init__(self, logging_type:str = 'debug'):
self.logging_type = logging_type
def __call__(self, decorated_function:callable):
self.func = decorated_function
return getattr(self, self.logging_type)
def debug(self, *args, **kwargs):
print("starting function")
output = self.func(*args, **kwargs)
print("Completing Function")
return output
我们看到装饰器适用于基本功能:
@Logger(logging_type="debug")
def simple_function(x):
return x**2
In [2]: simple_function(3)
starting function
Completing Function
Out[2]: 9
但是,与其他类一起工作时会失败:
class BigClass:
def __init__(self, stuff = 10):
self.stuff = stuff
@Logger(logging_type="debug")
def cool_function(self, input1: int):
return self.stuff + input1
In [16]: test = BigClass()
...: test.cool_function(3)
starting function
然后它在输出行上遇到类型错误:
TypeError: cool_function() missing 1 required positional argument: 'input1'
想法?
解决方案
一定要阅读 juanpa.arrivillaga 的内容丰富的答案。但这里有一个更简单的方法。在编写这种类型的类装饰器时,__call__
应该返回一个普通函数而不是成员函数,如下所示:
class Logger:
def __init__(self, logging_type:str = 'debug'):
self.logging_function = getattr(self, logging_type)
def __call__(self, decorated_function: callable):
def f(*args, **kwargs):
return self.logging_function(decorated_function, *args, **kwargs)
return f
def debug(self, decorated_function, *args, **kwargs):
print("starting function")
output = decorated_function(*args, **kwargs)
print("Completing Function")
return output
@Logger(logging_type="debug")
def simple_function(x):
return x**2
class BigClass:
def __init__(self, stuff = 10):
self.stuff = stuff
@Logger(logging_type="debug")
def cool_function(self, input1: int):
return self.stuff + input1
print(simple_function(12))
test = BigClass()
print(test.cool_function(3))
输出:
starting function
Completing Function
144
starting function
Completing Function
13
推荐阅读
- angular - 基于位置的 Angular 2 组件模板上的自定义 CSS 类
- regex - 使用正则表达式的最佳方式
- python-3.x - 当我使用变量参数初始化 dag 时,它会引发异常
- php - Woocommerce 中的自定义类别页面标题
- javascript - 如何按时间倒序从 DynamoDB 获取项目?
- python-3.x - WebElement.text 的访问时间增加
- tensorflow - 构建张量流图时如何定义需要输入numpy数组(不是张量)的损失函数?
- python - 如何在不使用额外内存的情况下将 Pandas 数据帧转换为 Numpy 数组
- node.js - 使用模板的请求技能的响应存在问题,Alexa 技能使用模板指令
- nginx - 如何解决 nginx 上的“索引”问题