None: pass consume(**kwar-6ren">
gpt4 book ai didi

python - 从函数的关键字参数生成 TypedDict

转载 作者:行者123 更新时间:2023-12-03 16:58:59 27 4
gpt4 key购买 nike

foo.py :

kwargs = {"a": 1, "b": "c"}

def consume(*, a: int, b: str) -> None:
pass

consume(**kwargs)
mypy foo.py :
error: Argument 1 to "consume" has incompatible type "**Dict[str, object]"; expected "int"
error: Argument 1 to "consume" has incompatible type "**Dict[str, object]"; expected "str"
这是因为 objectint 的父类(super class)型和 str ,因此推断。如果我声明:
from typing import TypedDict

class KWArgs(TypedDict):
a: int
b: str
然后注释 kwargsKWArgs , mypy检查通过。这实现了类型安全,但需要我复制 consume 的关键字参数名称和类型。在 KWArgs .有没有办法生成这个 TypedDict从类型检查时的函数签名,这样我就可以最大限度地减少维护中的重复?

最佳答案

据我所知,这个 [1] 没有直接的解决方法,但有另一种优雅的方式来实现这一点:
我们可以利用 typing s NamedTuple创建一个保存参数的对象:

ConsumeContext = NamedTuple('ConsumeContext', [('a', int), ('b', str)])
现在我们定义 consume接受它作为参数的方法:
def consume(*, consume_context : ConsumeContext) -> None:
print(f'a : {consume_context.a} , b : {consume_context.b}')
整个代码将是:
from typing import NamedTuple

ConsumeContext = NamedTuple('ConsumeContext', [('a', int), ('b', str)])

def consume(*, consume_context : ConsumeContext) -> None:
print(f'a : {consume_context.a} , b : {consume_context.b}')

ctx = ConsumeContext(a=1, b='sabich')

consume(consume_context=ctx)
运行 mypy 会产生:
Success: no issues found in 1 source file
它会识别 ab是参数,并批准。
运行代码会输出:
a : 1 , b : sabich
但是,如果我们更改 b要不是字符串,mypy 会提示:
foo.py:9: error: Argument "b" to "ConsumeContext" has incompatible type "int"; expected "str"
Found 1 error in 1 file (checked 1 source file)
通过这种方式,我们通过定义一次方法的参数和类型来实现对方法的类型检查。
[1] 因为如果定义 TypedDict或函数签名,基于另一个,需要知道另一个 __annotations__ ,这在检查时是未知的,并且定义一个装饰器来在运行时强制转换类型错过了类型检查的重点。

关于python - 从函数的关键字参数生成 TypedDict,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63910610/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com