【问题标题】:lru_cache interferes with type checking done by single_dispatchlru_cache 干扰由 single_dispatch 完成的类型检查
【发布时间】:2017-06-17 01:09:37
【问题描述】:

我有一个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 的命令,并尝试将其分配给变量。还是不行。我尝试在增强函数中进行显式类型检查。如果启用了缓存,类型检查也会失败。

【问题讨论】:

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


    【解决方案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 不匹配,因此单次调度回退到基本方法(引发 未实施

    解决方案

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

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

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

    希望能解决所有问题并指明前进的方向:-)

    【讨论】:

    • 所以这行得通。 (谢谢!)但是为什么一方面type(instanceofQualifiedInterval)返回QualifiedInterval,而另一方面type(instanceofQualifiedInterval) is QualifiedInterval返回false。
    猜你喜欢
    • 2019-06-22
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 2021-05-05
    • 1970-01-01
    相关资源
    最近更新 更多