How to annotate a dict of type to function that returns type

huangapple go评论58阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年6月9日 01:24:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定