lru\u缓存会干扰由单个\u分派完成的类型检查

2024-10-03 21:30:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有三个注册函数的method dispatch decorator。一个是在int上发送,这很好。第二个在自定义类型上调度,也可以正常工作。第三个也是自定义类型,但是类是用lru_cache装饰器包装的。你知道吗

(为了使事情更复杂一些,该类通过另一个类的__call__方法上的methoddispatch以迂回的方式实例化。)

@lru_cache(maxsize=None, typed=True)
class QualifiedInterval:
    # stuff that works

在球场内:

@oph_utils.method_dispatch
def augmented(self, other):
    raise NotImplementedError

@augmented.register(int)
def _(self, other):
    return "works fine"


@augmented.register(Interval)
def _(self, other):
    return "works fine too"

@augmented.register(QualifiedInterval)
def _(self, other):
    return "only works if QualifiedInterval class does NOT have lru_cache"

(还有很多事情要做,但这些都不管用。)

基本上-如果我有lru\u缓存,并将一个限定的interval传递到函数中,它不会分派并引发NotImplementedError。如果我注释掉缓存装饰器,它就工作了。REPL的手动类型检查显示了相同的类型(“QualifiedInterval”)。我试着用几种不同的方法调用创建QualifiedInterval的命令,并试着将它赋给一个变量。还是不行。我试过在增广函数中做显式类型检查。如果启用了缓存,类型检查也会失败。你知道吗


Tags: 函数selfregister类型cachereturndefmethod
1条回答
网友
1楼 · 发布于 2024-10-03 21:30:11

分析出了什么问题

Basically - if I have lru_cache, and pass a QualifiedInterval into the function, it does not dispatch

lru_cache是返回一个decorator的函数,它包装了任何可调用的(包括类)。因此,当您将lru\u缓存应用于QualifiedInterval类时,该变量将被分配给包装函数,而不是类本身。你知道吗

>>> @lru_cache(maxsize=None, typed=True)
class QualifiedInterval:
    pass

>>> type(QualifiedInterval)
<class 'functools._lru_cache_wrapper'>

Single dispatch通过将第一个参数的类型匹配到适当的方法来工作。但是,当您传入一个QualifiedInterval的实例时,它的类型与functools.\u lru\u cache\u wrapper不匹配,因此单次分派会返回到基方法(它会引发NotImplemented)。你知道吗

解决方案

教单个分派匹配实际的原始类(类型),而不是包装类:

@augmented.register(QualifiedInterval.__wrapped__)
def _(self, other):
    return "show now work QualifiedInterval class has an lru_cache"

注意添加了.__wrapped__属性,该属性通过包装函数到达原始的unwrapped类。你知道吗

希望这一切都能澄清,并指明前进的方向:-)

相关问题 更多 >