英文:
How to annotate a dict of type to function that returns type
问题
I want to use a dict which maps a type to a callable which returns the same type. E.g.
MY_DICT = {
bytes: lambda x: x,
int: lambda x: int.from_bytes(x, 'big'),
str: lambda x: x.decode('utf-8'),
}
i.e. each value is a callable which takes a bytes
value and returns the corresponding type for its key.
I'm wondering how I should annotate this dict for mypy? So far I have come up with:
dict[type, typing.Callable[[bytes], typing.Any]]
But I'm wondering if there is any way to remove the typing.Any
and to statically encode that the returned type must match the type key? Thanks for any advice!
I am using python 3.11.
英文:
I want to use a dict which maps a type to a callable which returns the same type. E.g.
MY_DICT = {
bytes: lambda x: x,
int: lambda x: int.from_bytes(x, 'big'),
str: lambda x: x.decode('utf-8'),
}
i.e. each value is a callable which takes a bytes
value and returns the corresponding type for its key.
I'm wondering how I should annotate this dict for mypy? So far I have come up with:
dict[type, typing.Callable[[bytes], typing.Any]]
But I'm wondering if there is any way to remove the typing.Any
and to statically encode that the returned type must match the type key? Thanks for any advice!
I am using python 3.11.
答案1
得分: 2
Type mappings 在Python中尚不受支持(但是?)。但是,您可以编写一个 Protocol
,它模仿了 collections.abc
中的 MutableMapping
的某些方面,以实现大致相同的效果,如果您愿意不将其直接编写为字典(字典文字):
import typing as t
T = t.TypeVar("T")
class MyDict(t.Protocol):
def __getitem__(self, item: type[T]) -> t.Callable[[bytes], T]: ...
def __setitem__(self, key: type[T], value: t.Callable[[bytes], T]) -> None: ...
# 无法编写包含所有条目的字典文字,但您可以以类型安全的方式初始化、设置和检索值
MY_DICT: MyDict = {}
MY_DICT[bytes] = lambda x: x
MY_DICT[int] = lambda x: int.from_bytes(x, "big")
MY_DICT[str] = lambda x: x.decode("utf-8")
# mypy 生效的类型检查
MY_DICT[bytes] = b"" # mypy: 赋值中的类型不兼容(表达式类型为 "bytes",目标类型为 "Callable[[bytes], bytes]")[assignment]
reveal_type(MY_DICT[list[int]]) # mypy: 揭示的类型是 "def (builtins.bytes) -> builtins.list[builtins.int]"
如果您需要更多来自 dict
的方法API,请在 MyDict
中填写方法存根签名。
英文:
Type mappings are not supported in Python (yet?). You can, however, write a Protocol
which imitates some aspects of collections.abc.
MutableMapping
to achieve roughly the same effect, if you're willing to forgo writing it as a direct dictionary (dictionary literal):
import typing as t
T = t.TypeVar("T")
class MyDict(t.Protocol):
def __getitem__(self, item: type[T]) -> t.Callable[[bytes], T]: ...
def __setitem__(self, key: type[T], value: t.Callable[[bytes], T]) -> None: ...
# Can't write a dictionary literal with all the entries here, but you can initialise, set, and retrieve values in a type-safe manner
MY_DICT: MyDict = {}
MY_DICT[bytes] = lambda x: x
MY_DICT[int] = lambda x: int.from_bytes(x, "big")
MY_DICT[str] = lambda x: x.decode("utf-8")
# Type-checking in effect by mypy
MY_DICT[bytes] = b"" # mypy: Incompatible types in assignment (expression has type "bytes", target has type "Callable[[bytes], bytes]") [assignment]
reveal_type(MY_DICT[list[int]]) # mypy: Revealed type is "def (builtins.bytes) -> builtins.list[builtins.int]"
If you need more method API from dict
, just fill up the method stub signatures in MyDict
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论