[英]define a decorator as method inside class
我正在尝试在我的 class 中创建一个方法来计算特定 function 的完整运行。我想使用一个简单的装饰器。 我找到了这个参考并重写了这个简单的脚本:
class myclass:
def __init__(self):
self.cnt = 0
def counter(function):
"""
this method counts the runtime of a function
"""
def wrapper(self, **args):
function(**args)
self.counter += 1
return wrapper
@myclass.counter
def somefunc():
print("hello from somefunc")
if __name__ == "__main__":
obj = myclass()
# or if comment @myclass.counter
# somefunc = myclass.counter(somefunc)
somefunc()
当然,我得到:
TypeError: wrapper() missing 1 required positional argument: 'self'
我试图将计数器重写为 class 方法:
class myclass:
def __init__(self):
self.cnt = 0
def counter(self, function):
"""
this method counts the runtime of a function
"""
def wrapper(**args):
function(**args)
self.cnt += 1
return wrapper
def somefunc():
print("hello from somefunc")
if __name__ == "__main__":
obj = myclass()
somefunc = obj.counter(somefunc)
for i in range(10):
somefunc()
print(obj.cnt)
哪个工作正常但我认为它不是有效的装饰器定义。 有什么方法可以在 class 方法中定义装饰器并将自变量传递给它的 function 吗? 或者在 class 中定义装饰器是没用的?
编辑:------- 首先,我无法在 class 方法之外定义装饰。 其次,我正在尝试制作一个预定的 class,它在固定的时间间隔和特定的时间内运行特定的 function(作为输入),因此我需要计算它。
所以我可以为你起草一些东西,下面是代码:
def count(func):
def wrapper(self):
TestClass.call_count += 1
func(self)
return wrapper
class TestClass(object):
call_count = 0
@count
def hello(self):
return 'hello'
if __name__ == '__main__':
x = TestClass()
for i in range(10):
x.hello()
print(TestClass.call_count)
为什么在 class 中使用装饰器会导致问题:
在decorator function
并不直接。原因如下:
原因 1每个 class 方法都必须采用一个参数self
,它是 class 的instance
,通过它调用 function。 现在,如果你让装饰器 function 接受一个self
参数,装饰器调用@count
将失败,因为它被转换为count()
,它不传递self
参数,因此错误:
TypeError: wrapper() missing 1 required positional argument: 'self'
原因 2现在,为了避免您可以通过更改如下声明,将decorator
设置为 static:
@staticmethod
def count(func):
pass
但是你有另一个错误:
TypeError: 'staticmethod' object 不可调用
这意味着您也不能拥有 static 方法。 如果在 class 中不能有 static 方法,则必须将self
实例传递给该方法,但如果将self
实例传递给它, @count
装饰器调用将不会传递self
实例,因此它不会'不工作。
所以这里有一个博客很好地解释了它,与之相关的问题以及替代方案是什么。
我个人更喜欢选择有一个helper class
来保存我所有可以使用的decorators
,而不是它定义的唯一 class。 这将使您可以灵活地重用装饰器,而不是重新定义它们,这将遵循意识形态
一次编码,一遍又一遍地重用。
您的第二个代码示例在功能上等同于标准装饰器。 标准装饰器语法只是同一事物的简写,即重新分配等于闭包的 function 值(预定义为 arguments 的 function 指针),其中闭包是您的装饰器包装器,将原始值作为其预定义参数。
这是标准语法的等价物。 注意需要提前创建计数器 class 实例。 装饰器语法引用该实例,因为它必须指示保存计数器的特定 object,而不仅仅是 object 的 class:
class myclass:
def __init__(self):
self.cnt = 0
def counter(self,function):
"""
this method counts the number of runtime of a function
"""
def wrapper(**args):
function(self,**args)
self.cnt += 1
return wrapper
global counter_object
counter_object = myclass()
@counter_object.counter
def somefunc(self):
print("hello from somefunc")
if __name__ == "__main__":
for i in range(10):
somefunc()
print(counter_object.cnt)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.