我有一个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函数中进行显式类型检查。如果启用了缓存,那么类型检查也会失败。
答案 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__
属性,该属性通过包装函数到达原始的未包装类。
希望清除它并展示前进的方向: - )