mypy:“__setitem__”的签名与超类型 "list" 不兼容
mypy: Signature of "__setitem__" incompatible with supertype "list"
我正在尝试使用 List 的一个专门子类来创建一个由常规列表支持的 TokenList,但还包含一个带有 key/values 的元数据字典。一切都很好,直到我想为此添加类型,现在我收到此错误:
error: Signature of "__setitem__" incompatible with supertype "list"
...错误是下面的第一个重载:
import typing as T
class Token(dict):
...
class TokenList(T.List[Token]):
...
@T.overload
def __setitem__(self, key: int, tokens: T.Union[dict, Token]) -> None: ... # noqa, pragma: no cover
@T.overload
def __setitem__(self, key: slice, tokens: T.Union[T.Iterable[T.Union[dict, Token]], 'TokenList']) -> None: ... # noqa, pragma: no cover
def __setitem__(self, key, tokens): # noqa: F811
if isinstance(key, int):
token = tokens
token = self._dict_to_token_and_set_defaults(token)
super(TokenList, self).__setitem__(key, token)
else:
tokens = [self._dict_to_token_and_set_defaults(token) for token in tokens]
super(TokenList, self).__setitem__(key, tokens)
我试图找到 list
的类型定义以将其与我的进行比较,但未能找到。
除了忽略这个错误继续我的生活,还有什么办法解决这个问题吗?任何指点表示赞赏。
(如果重要的话,我正在使用 mypy 0.910 和 Python 3.9.1。)
你可以用reveal_type
找出任何对象的静态类型。所以尝试:
reveal_type(list.__setitem__)
给你:
reveal_type.py:2: note: Revealed type is "Overload(def [_T] (builtins.list[_T`1], typing_extensions.SupportsIndex, _T`1), def [_T] (builtins.list[_T`1], builtins.slice, typing.Iterable[_T`1]))"
您的原始代码的问题是,列表可以索引的不仅仅是 int
s 和 slice
s:它们支持任何可以用 [=22= 强制转换为整数的对象] 还有。
这意味着您需要进行两项更改:导入 typing_extensions
并将 int
替换为 typing_extensions.SupportsIndex
。
import typing_extensions as TE
...
def __setitem__(self, key: TE.SupportsIndex, tokens: T.Union[dict, Token]) -> None: ... # noqa, pragma: no cover
此外,这意味着您的实现不太正确,因为非整数非切片索引将被视为切片索引。我会这样写:
def __setitem__(self, key, tokens): # noqa: F811
if isinstance(key, slice):
tokens = [self._dict_to_token_and_set_defaults(token) for token in tokens]
else:
tokens = self._dict_to_token_and_set_defaults(tokens)
super().__setitem__(key, tokens)
我正在尝试使用 List 的一个专门子类来创建一个由常规列表支持的 TokenList,但还包含一个带有 key/values 的元数据字典。一切都很好,直到我想为此添加类型,现在我收到此错误:
error: Signature of "__setitem__" incompatible with supertype "list"
...错误是下面的第一个重载:
import typing as T
class Token(dict):
...
class TokenList(T.List[Token]):
...
@T.overload
def __setitem__(self, key: int, tokens: T.Union[dict, Token]) -> None: ... # noqa, pragma: no cover
@T.overload
def __setitem__(self, key: slice, tokens: T.Union[T.Iterable[T.Union[dict, Token]], 'TokenList']) -> None: ... # noqa, pragma: no cover
def __setitem__(self, key, tokens): # noqa: F811
if isinstance(key, int):
token = tokens
token = self._dict_to_token_and_set_defaults(token)
super(TokenList, self).__setitem__(key, token)
else:
tokens = [self._dict_to_token_and_set_defaults(token) for token in tokens]
super(TokenList, self).__setitem__(key, tokens)
我试图找到 list
的类型定义以将其与我的进行比较,但未能找到。
除了忽略这个错误继续我的生活,还有什么办法解决这个问题吗?任何指点表示赞赏。
(如果重要的话,我正在使用 mypy 0.910 和 Python 3.9.1。)
你可以用reveal_type
找出任何对象的静态类型。所以尝试:
reveal_type(list.__setitem__)
给你:
reveal_type.py:2: note: Revealed type is "Overload(def [_T] (builtins.list[_T`1], typing_extensions.SupportsIndex, _T`1), def [_T] (builtins.list[_T`1], builtins.slice, typing.Iterable[_T`1]))"
您的原始代码的问题是,列表可以索引的不仅仅是 int
s 和 slice
s:它们支持任何可以用 [=22= 强制转换为整数的对象] 还有。
这意味着您需要进行两项更改:导入 typing_extensions
并将 int
替换为 typing_extensions.SupportsIndex
。
import typing_extensions as TE
...
def __setitem__(self, key: TE.SupportsIndex, tokens: T.Union[dict, Token]) -> None: ... # noqa, pragma: no cover
此外,这意味着您的实现不太正确,因为非整数非切片索引将被视为切片索引。我会这样写:
def __setitem__(self, key, tokens): # noqa: F811
if isinstance(key, slice):
tokens = [self._dict_to_token_and_set_defaults(token) for token in tokens]
else:
tokens = self._dict_to_token_and_set_defaults(tokens)
super().__setitem__(key, tokens)