python - How to use these two class decorators together with functools.update_wrapper? -
i reading decorators , tried mix these 2 examples , make them class decorators instead of regular functions. first 1 lets run function once per argument , second 1 counts how many times you've run function. both work fine separated when try decorate simple function both @ same time fails... or doesn't fail prints unexpected wrong result. did reading , found functools module can i'm not sure how.
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. have printed 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): 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)
by default update_wrapper
updates __dict__
wrapped class. func
in memoize
being overwritten func
in callcounter
means memoize
directly calling doubleprint()
function , never calling 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'>
you can fix doing:
update_wrapper(self, func, updated=[])
which not copy __dict__
callcounter
memoize
instance still copy __name__, __doc__
, etc.
to access callcounter
class would:
print(doubleprint.__wrapped__.calls)
but need fix above or print 0
(because never called).
Comments
Post a Comment