[英]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.