lru_cache会干扰single_dispatch完成的类型检查

时间:2017-06-17 01:09:38

标签: python python-3.x dispatch lru single-dispatch

我有一个method dispatch decorator,有三个注册函数。一个人发送int,工作正常。第二个调度自定义类型,也可以正常工作。第三个也是自定义类型,但Class包含lru_cache装饰器。

(为了使事情变得复杂一点,该类通过另一个类的__call__方法上的methoddispatch以环形方式实例化。)

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

Pitch课程内:

@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_cache,并将QualifiedInterval传递给函数,它不会调度并引发NotImplementedError。如果我注释掉缓存装饰器,它就可以了。 REPL中的手动类型检查显示相同的类型(“QualifiedInterval”)。我尝试了几种不同的方式调用创建QualifiedInterval的命令,并尝试将其分配给变量。仍然无法正常工作。我已尝试在Augmented函数中进行显式类型检查。如果启用了缓存,那么类型检查也会失败。

1 个答案:

答案 0 :(得分:1)

分析什么是错误的

  

基本上 - 如果我有lru_cache,并将QualifiedInterval传递给函数,则不会发送

lru_cache是一个返回包含任何可调用(包括类)的decorator的函数。因此,当您将 lru_cache 应用于 QualifiedInterval 类时,该变量将分配给包装函数而不是类本身。

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

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

Single dispatch的工作原理是将第一个参数的类型与适当的方法相匹配。但是,当您传入 QualifiedInterval 的实例时,其类型与 functools._lru_cache_wrapper 不匹配,因此单个调度会回退到基本方法(这会引发< EM> NotImplemented

解决方案

教授单个调度以匹配实际原始类(类型)而不是包装类:

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

请注意添加.__wrapped__属性,该属性通过包装函数到达原始的未包装类。

希望清除它并展示前进的方向: - )