在 class 中声明装饰器
Declaring decorator inside a class
我正在尝试在 Python 中使用自定义 wrappers/decorators,我想声明一个 inside 一个 class,这样我就可以打印属性的快照。我已经尝试了 this question 的东西但没有成功。
这是我想做的(注意:这段代码不起作用,我会在下面解释会发生什么)
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
def enter_exit_info(self, func):
def wrapper(*arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(*arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
预期输出为:
-- entering add_in_c
-- {'a': 2, 'b': 3, 'c': 0}
5
-- exiting add_in_c
-- {'a': 2, 'b': 3, 'c': 5}
-- entering mult_in_c
-- {'a': 2, 'b': 3, 'c': 5}
6
-- exiting mult_in_c
-- {'a': 2, 'b': 3, 'c': 6}
但是我这段代码给出了
Traceback (most recent call last):
File "C:\Users\cccvag\workspace\Test\src\module2.py", line 2, in <module>
class TestWrapper():
File "C:\Users\cccvag\workspace\Test\src\module2.py", line 18, in TestWrapper
@enter_exit_info
TypeError: enter_exit_info() takes exactly 2 arguments (1 given)
如果我尝试 @enter_exit_info(self)
或 @self.enter_exit_info
,我会得到 NameError
。我能做什么?
编辑:
我不需要首先在 class 中声明装饰器 物理上 ,只要它能够访问此 [的实例的属性即可=43=]。我认为它只能通过在 class 中声明它来制作, 证明我错了。
您需要明确处理 self
。
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
def enter_exit_info(func):
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(self, *arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
这是有效的 python,但在 class 级别有一个函数有点奇怪,它不是真正的方法。除非你有充分的理由这样做,否则将装饰器移动到模块级范围会更加惯用。
无需在 class 中定义装饰器,您只需拦截 self
参数即可:
import functools
def enter_exit_info(func):
@functools.wraps(func)
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(self, *arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
TL;DR : 你想要的是
def enter_exit_info(func):
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(*arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
记住
@decorate
def myfunc():
pass
实际上只是
的语法糖
def myfunc():
pass
my_func = decorate(my_func)
因此,由于在您的情况下,装饰函数被装饰器的 wrapper
函数替换,因此这个 wrapper
函数将接收当前实例作为第一个参数。
编辑:我非常同意其他答案,即在 class 中定义这个装饰器毫无意义。您不需要它来访问当前实例,因为它作为函数的第一个参数提供。 FWIW def
语句与在 class
语句中使用没有任何不同,它总是产生一个普通的旧 function
对象。使函数成为 "method"(并且 'automagically' 将当前实例作为第一个参数传递)的原因是属性解析机制,请参见 https://wiki.python.org/moin/FromFunctionToMethod
您好,您希望输出为字典格式吗?
如果你不想要字典格式的输出,你可以试试这个....
def enter_exit_info(func):
def wrapper(*arg, **kw):
print '-- entering', func.__name__
res = func(*arg, **kw)
print '-- exiting', func.__name__
return res
return wrapper
那么你的输出将是
-- entering add_in_c
5
-- exiting add_in_c
-- entering mult_in_c
6
-- exiting mult_in_c
我正在尝试在 Python 中使用自定义 wrappers/decorators,我想声明一个 inside 一个 class,这样我就可以打印属性的快照。我已经尝试了 this question 的东西但没有成功。
这是我想做的(注意:这段代码不起作用,我会在下面解释会发生什么)
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
def enter_exit_info(self, func):
def wrapper(*arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(*arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
预期输出为:
-- entering add_in_c
-- {'a': 2, 'b': 3, 'c': 0}
5
-- exiting add_in_c
-- {'a': 2, 'b': 3, 'c': 5}
-- entering mult_in_c
-- {'a': 2, 'b': 3, 'c': 5}
6
-- exiting mult_in_c
-- {'a': 2, 'b': 3, 'c': 6}
但是我这段代码给出了
Traceback (most recent call last):
File "C:\Users\cccvag\workspace\Test\src\module2.py", line 2, in <module>
class TestWrapper():
File "C:\Users\cccvag\workspace\Test\src\module2.py", line 18, in TestWrapper
@enter_exit_info
TypeError: enter_exit_info() takes exactly 2 arguments (1 given)
如果我尝试 @enter_exit_info(self)
或 @self.enter_exit_info
,我会得到 NameError
。我能做什么?
编辑:
我不需要首先在 class 中声明装饰器 物理上 ,只要它能够访问此 [的实例的属性即可=43=]。我认为它只能通过在 class 中声明它来制作,
您需要明确处理 self
。
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
def enter_exit_info(func):
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(self, *arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
这是有效的 python,但在 class 级别有一个函数有点奇怪,它不是真正的方法。除非你有充分的理由这样做,否则将装饰器移动到模块级范围会更加惯用。
无需在 class 中定义装饰器,您只需拦截 self
参数即可:
import functools
def enter_exit_info(func):
@functools.wraps(func)
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(self, *arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
class TestWrapper():
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 0
@enter_exit_info
def add_in_c(self):
self.c = self.a + self.b
print self.c
@enter_exit_info
def mult_in_c(self):
self.c = self.a * self.b
print self.c
if __name__ == '__main__':
t = TestWrapper(2, 3)
t.add_in_c()
t.mult_in_c()
TL;DR : 你想要的是
def enter_exit_info(func):
def wrapper(self, *arg, **kw):
print '-- entering', func.__name__
print '-- ', self.__dict__
res = func(*arg, **kw)
print '-- exiting', func.__name__
print '-- ', self.__dict__
return res
return wrapper
记住
@decorate
def myfunc():
pass
实际上只是
的语法糖def myfunc():
pass
my_func = decorate(my_func)
因此,由于在您的情况下,装饰函数被装饰器的 wrapper
函数替换,因此这个 wrapper
函数将接收当前实例作为第一个参数。
编辑:我非常同意其他答案,即在 class 中定义这个装饰器毫无意义。您不需要它来访问当前实例,因为它作为函数的第一个参数提供。 FWIW def
语句与在 class
语句中使用没有任何不同,它总是产生一个普通的旧 function
对象。使函数成为 "method"(并且 'automagically' 将当前实例作为第一个参数传递)的原因是属性解析机制,请参见 https://wiki.python.org/moin/FromFunctionToMethod
您好,您希望输出为字典格式吗? 如果你不想要字典格式的输出,你可以试试这个....
def enter_exit_info(func):
def wrapper(*arg, **kw):
print '-- entering', func.__name__
res = func(*arg, **kw)
print '-- exiting', func.__name__
return res
return wrapper
那么你的输出将是
-- entering add_in_c
5
-- exiting add_in_c
-- entering mult_in_c
6
-- exiting mult_in_c