【发布时间】:2019-09-19 09:55:57
【问题描述】:
我有类似以下的内容:
from typing import TypeVar, Callable, Generic, Type, Union, Optional
T = TypeVar("T")
V = TypeVar("V")
class DescClass(Generic[T, V]):
"""A descriptor."""
def __init__(self, func: Callable[[T], V]) -> None:
self.func = func
def __get__(self, instance: Optional[T], owner: Type[T]) -> Callable[[], V]:
return self.func.__get__(instance, owner)
class C:
@DescClass
def f(self): ...
...Mypy 将返回此错误:
test.py:12: error: "Callable[[T], Any]" has no attribute "__get__"
为func指定类型的规范方法是什么,以便Mypy理解它是一个描述符(and thus always has a __get__)?
更新:在搜索 Mypy 帮助时,“描述符”has no hits 有点幽默。
【问题讨论】:
-
@juanpa.arrivillaga 对。
class MyCallable: def __call__(self): ...等等等等等等.... -
也许是protocols/structural types的一个很好的用例
-
@FilipDimitrovski 因为未来(读作:愚蠢、健忘、粗心……)我可能会尝试使用函数式语法和一些可调用的非函数对象来修补补丁:
C.g = DescClass(callable_obj),它会不工作。 -
@RickTeachey 我不得不放弃自己尝试合并协议,尽管它相当复杂(需要 classmethds 等),而且我不确定协议是否是问题的根源。我最终选择了
abc.ABC。阅读this question 中的答案/cmets。您的用例可能很简单,以至于它“可以正常工作”,但它绝对不是一个可以投入生产的功能,至少这是我的印象。 -
可以将描述符的类型定义为
class Descriptor(Protocol[T, V]): def __get__(self, instance: Optional[T], owner: Optional[Type[T]]) -> V: pass(如果需要数据描述符,请添加__set__/__del__)。当DescClass设置为采用func: Descriptor[T, Callable[[], V]]时,这将正常工作。然而,从 MyPy 0.812 开始,最终的问题是def“创建”只是一个Callable[[C], Any]"没有任何信息表明它也是一个描述符。