python - lru_cache 干扰 single_dispatch 完成的类型检查

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

我有一个method dispatch decorator具有三个注册功能。其中一个在 int 上调度,效果很好。第二个在自定义类型上调度,也可以正常工作。第三个也是自定义类型,但该类是用 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 的命令,并尝试将其分配给变量。还是不行。我尝试在增强函数中进行显式类型检查。如果启用了缓存,类型检查也会失败。

最佳答案

问题分析

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

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 不匹配,因此单个调度会回退到基本方法(这会引发 未实现

解决方案

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

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

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

希望一切都清楚并指明前进的方向:-)

关于python - lru_cache 干扰 single_dispatch 完成的类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44599852/

相关文章:

python - 在 Keras 中使用 K.eval() 将 Tensor 转换为 np.array 返回 InvalidArgumentError

python - 如何使用装饰器类来装饰实例方法?

python - 在单元格条件下对 pandas 进行多个切片行

python - 使用用户输入在python中循环和求和

javascript - 在更新时显示日志文件的内容

python - 为什么这个 OpenCV 掩蔽函数不迭代?

python - 将一个数据帧的列乘以另一个数据帧的值,由键确定

.net - 如何在 XP 上的 .Net 应用程序中调试 AccessViolationException

java - Java程序中多线程的使用和vs需要在EDT上创建Swing对象

Android NFC前台调度问题