[英]How to use these two class decorators together with functools.update_wrapper?
我正在閱讀有關裝飾器的內容,並嘗試將這兩個示例混合在一起,並使它們成為類裝飾器而不是常規函數。 第一個只允許你為每個參數運行一次函數,第二個只計算你運行該函數的次數。 它們都工作得很好但是當我嘗試同時裝飾一個簡單的函數時它失敗了......或者並沒有真正失敗但是會打印出意想不到的錯誤結果。 我做了一些閱讀,發現functools模塊可以幫助,但我不知道如何。
from functools import update_wrapper
class Memoize:
def __init__(self, func):
self.func = func
self.memo = dict()
update_wrapper(self, func)
def __call__(self, *args):
if args not in self.memo:
self.memo[args] = self.func(args)
else:
print("cls decorator. You have printed this before")
return self.memo[args]
class CallCounter:
def __init__(self, func):
self.func = func
self.calls = 0
self.__name__ = func.__name__
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
self.calls += 1
return self.func(*args, **kwargs)
@Memoize
@CallCounter
def doubleprint(x):
for elem in x:
print(elem + " " + elem)
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Bye')
print(doubleprint.calls)
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Hello')
doubleprint('Bye')
print(doubleprint.calls)
默認情況下update_wrapper
更新__dict__
從包裹類。 所以,你的func
在Memoize
被覆蓋與func
在CallCounter
這意味着Memoize
直接調用你的doubleprint()
函數調用從未CallCounter
。
class Memoize:
def __init__(self, func):
self.func = func
print(type(self.func)) # <class '__main__.CallCounter'>
self.memo = dict()
update_wrapper(self, func)
print(type(self.func)) # <class 'function'>
您可以通過以下方式解決此問題
update_wrapper(self, func, updated=[])
這不會將__dict__
從CallCounter
復制到Memoize
實例中,但仍會復制__name__, __doc__
等。
要訪問CallCounter
類,您將:
print(doubleprint.__wrapped__.calls)
但是你需要上面的修復,否則它將始終打印0
(因為它永遠不會被調用)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.