gpt4 book ai didi

python - 如何将这两个类装饰器与 functools.update_wrapper 一起使用?

转载 作者:行者123 更新时间:2023-11-28 18:19:58 26 4
gpt4 key购买 nike

我正在阅读有关装饰器的内容,并尝试混合使用这两个示例,使它们成为类装饰器而不是常规函数。第一个只允许您为每个参数运行一次函数,第二个计算您运行该函数的次数。它们都可以很好地分开工作,但是当我尝试同时用两者装饰一个简单的函数时,它会失败……或者并没有真正失败,但会打印出意想不到的错误结果。我做了一些阅读,发现 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__。所以你在 Memoize 中的 funcCallCounter 中的 func 覆盖,这意味着 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(因为它从未被调用)。

关于python - 如何将这两个类装饰器与 functools.update_wrapper 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45685582/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com