例如:
T = TypeVar("T", bound="CustomDict")
class CustomDict(dict):
def __init__(self) -> None:
super().__init__()
class dict_operator:
def __init__(self, method: Callable[..., Any]) -> None:
self.method = method
def __get__(self, instance: T, owner: Type[T]) -> Callable[..., Any]:
def wrapper(key: Any, *args: Any, **kwargs: Any) -> Any:
results = self.method(instance, key, *args, **kwargs)
print("Did something after __getitem__ or __setitem__")
return results
return wrapper
@dict_operator
def __getitem__(self, key: Any) -> Any:
return super().__getitem__(key)
@dict_operator
def __setitem__(self, key: Any, value: Any) -> None:
super().__setitem__(key, value)
我的:
Signature of "__getitem__" incompatible with supertype "dict"Mypyoverride Signature of "__getitem__" incompatible with supertype "Mapping"Mypyoverride (variable) Any: Any
我认为装饰器更改了重写方法的签名,但我不知道如何解释这一点。
问题不在于
__getitem__
和 __setitem__
上的类型注释。无论好坏,mypy(目前)都无法识别返回 __get__
的 Callable
在大多数情况下是代替真正的 Callable
的安全覆盖。最快的解决方法是将 __call__
添加到您的 dict_operator
类主体 (mypy Playground 1):
class CustomDict(dict):
...
class dict_operator:
def __init__(self, method: Callable[..., Any]) -> None: ...
def __get__(self, instance: T, owner: Type[T]) -> Callable[..., Any]:
# This needs to be the same as the return type of `__get__`
__call__: Callable[..., Any]
@dict_operator
def __getitem__(self, key: Any) -> Any: ... # OK
@dict_operator
def __setitem__(self, key: Any, value: Any) -> None: ... # OK
我不知道你这样做是否只是为了演示目的,但在我看来,你在这里输入的内容太多不精确;特别是
Callable[..., Any]
不是一个非常有用的类型注释。我不知道您使用的是哪个 Python 版本,但如果您能够使用 typing_extensions
代替,您就可以访问最新的类型结构以进行更好的静态检查。请参阅 mypy Playground 2 了解实现更严格打字的可能方法。