我正在尝试在类内部创建decorator,并且需要访问decorator 内部的self
这是我的代码
import functools
class Rtest(object):
def __init__(self, *args, **kwargs):
self.key1 = "foo"
self.value1 = "bar"
def continue_exception(self, func, **kwargs):
@functools.wraps(func)
def inner_function(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
import traceback
print(f"Error with {kwargs.get('key')} : {kwargs.get('value')}")
print(f"Exception {traceback.format_exc()}")
return
return inner_function
def add1(self, n1, n2):
return n1 + n2
@continue_exception(key=self.key1, value=self.value1)
def add2(self, n1, n2):
return n1 + n2
obj = Rtest()
print(obj.add1(4,5))
print(obj.add2("fdfd", 6))
我收到这个错误
@continue_exception(key="foo", value="bar")
TypeError:continue_exception((缺少2个必需的位置参数:"self"one_answers"func">
您的程序存在以下问题:
-
装饰器函数的定义有问题。当它在
@continue_exception(key="foo", value="bar")
中使用时,没有func
参数,它只会接收您传入的位置参数。因为此时它是先执行的,然后执行装饰功能。 -
continue_exception
是一个实例方法,除非你能把一个对象传递给它,否则你不能把它用作装饰器。所以你可以把它变成一个静态方法,是的,你可以,因为self
没有在函数内部使用。
以下代码修复了上述问题并成功运行。
import functools
class Rtest(object):
def __init__(self, *args, **kwargs):
self.key1 = "foo"
self.value1 = "bar"
@staticmethod
def continue_exception(**kwargs):
def wrapper(func):
@functools.wraps(func)
def inner_function(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
import traceback
print(f"Error with {kwargs.get('key')} : {kwargs.get('value')}")
print(f"Exception {traceback.format_exc()}")
return
return inner_function
return wrapper
def add1(self, n1, n2):
return n1 + n2
@continue_exception(key="foo", value="bar")
def add2(self, n1, n2):
return n1 + n2
obj = Rtest()
print(obj.add1(4,5))
print(obj.add2("fdfd", 6))
输出:
9
Error with None : None
Exception Traceback (most recent call last):
File "/home/wujun/Projects/code_test/test.py", line 15, in inner_function
return func(*args, **kwargs)
File "/home/wujun/Projects/code_test/test.py", line 29, in add2
return n1 + n2
TypeError: can only concatenate str (not "int") to str
None
如果要实时获取key1
和value1
的值,可以进行以下修改。
import functools
class Rtest(object):
def __init__(self, *args, **kwargs):
self.key1 = "foo"
self.value1 = "bar"
@staticmethod
def continue_exception(func):
@functools.wraps(func)
def inner_function(*args, **kwargs):
self, *_ = args
try:
return func(*args, **kwargs)
except Exception as e:
import traceback
print(f"Error with {self.key1} : {self.value1}")
print(f"Exception {traceback.format_exc()}")
return
return inner_function
def add1(self, n1, n2):
return n1 + n2
@continue_exception
def add2(self, n1, n2):
return n1 + n2
obj = Rtest()
print(obj.add1(4,5))
print(obj.add2("fdfd", 6))