lru_cache干扰了single_dispatch完成的类型检查 [英] lru_cache interferes with type checking done by single_dispatch

查看:134
本文介绍了lru_cache干扰了single_dispatch完成的类型检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法调度修饰器,三个注册功能.一个在int上调度,效果很好.分派给自定义类型的第二个,也可以正常工作.第三个也是自定义类型,但是Class用lru_cache装饰器包装.

I have a method dispatch decorator with three registered functions. One dispatches on int, which works fine. The second dispatched on a custom type, also works fine. The third is also a custom type, but the Class is wrapped with the lru_cache decorator.

(为了使事情更复杂一点,该类通过另一类的__call__方法上的方法调度以a回的方式实例化.)

(To make things a little more complicated, the class is instantiated in a roundabout way via a methoddispatch on the __call__ method of another class.)

@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"

(还有很多事情要做,但这是行不通的.)

(There's a lot more going on, but this is the bits that don't work.)

基本上-如果我具有lru_cache,并将QualifiedInterval传递给该函数,则它不会分派并引发NotImplementedError.如果我注释掉缓存装饰器,它将起作用.并且在REPL上的手动类型检查会以两种方式显示相同的类型("QualifiedInterval").我尝试以几种不同的方式调用创建QualifiedInterval的命令,并尝试将其分配给变量.仍然不起作用.我尝试在Augmented函数中进行显式类型检查.如果启用了缓存,那么类型检查也会在那里失败.

Basically - if I have lru_cache, and pass a QualifiedInterval into the function, it does not dispatch and raises NotImplementedError. If I comment out the cache decorator, it works. And manual type checking at the REPL shows the same type ("QualifiedInterval") either way. I've tried calling the command that created the QualifiedInterval several different ways, and tried assigning it to a variable. Still doesn't work. I've tried doing explicit typechecking in the Augmented function. The typecheck fails there as well, if caching is enabled.

推荐答案

分析出了什么问题

基本上-如果我具有lru_cache,并将QualifiedInterval传递给该函数,则它不会调度

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

lru_cache 是一个返回装饰器的函数,该函数包装了所有可调用的对象(包括类) .因此,当您将 lru_cache 应用于 QualifiedInterval 类时,该变量将被分配给包装函数而不是类本身.

The lru_cache is function that returns a decorator that wraps any callable (including classes). So when you apply the lru_cache to the QualifiedInterval class, that variable becomes assigned to the wrapper function rather than the class itself.

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

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

单派发通过匹配第一个参数为适当的方法.但是,当您传入 QualifiedInterval 的实例时,其类型与 functools._lru_cache_wrapper 不匹配,因此,单次调度将退回到基本方法(引发未实现.

Single dispatch works by matching the type of the first parameter to the appropriate method. However, when you pass in an instance of QualifiedInterval, its type doesn't match functools._lru_cache_wrapper, so single dispatch falls back to the base method(which raises NotImplemented.

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

Teach single dispatch to match on the actual original class (type) instead of the wrapped class:

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

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

Note the addition of the .__wrapped__ attribute which reaches through the wrapper function to get to the original unwrapped class.

希望可以解决所有问题并显示前进的方向:-)

Hope that clears it all up and shows the way forward :-)

这篇关于lru_cache干扰了single_dispatch完成的类型检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆