为何不能用Dict[str, Any]标注**kwargs?正确标注方式是什么?
问题分析与解决方案
错误原因
你对**kwargs的类型标注语法理解有误:**kwargs: Dict[str, Any]的含义是每个传入的关键字参数的值必须是Dict[str, Any]类型,而非kwargs整体是一个Dict[str, Any]。这就导致类型检查器认为foo的number参数值需要是字典,但你传入了int,因此报错。
正确的标注方式
1. 任意键值对场景(值为任意类型)
如果kwargs可以接收任意键,值的类型无限制,直接标注值的类型为Any即可:
from typing import Any def foo(name: str, **kwargs: Any) -> int: modified_name: str = f'This is an example for {name}!' return some_other_func(modified_name, **kwargs) def bar(id_number: int, **kwargs: Any) -> int: name: str = some_func(id_number) return foo(name, number=id_number, **kwargs)
2. 修改kwargs字典的正确写法
你之前修改kwargs的代码存在两个问题:
- 键名写错:应该用字符串
"number"而非变量number kwargs的类型标注错误,导致赋值时类型不匹配
修正后的代码:
from typing import Any def bar(id_number: int, **kwargs: Any) -> int: name: str = some_func(id_number) kwargs["number"] = id_number # 键名改为字符串 return foo(name, **kwargs)
3. 精确类型场景(已知kwargs可能的键)
如果能明确kwargs允许的键和对应类型,可以用TypedDict配合Unpack(Python 3.11+)来做更精确的标注:
from typing import TypedDict, Unpack class FooKwargs(TypedDict, total=False): number: int other_param: str def foo(name: str, **kwargs: Unpack[FooKwargs]) -> int: modified_name: str = f'This is an example for {name}!' return some_other_func(modified_name, **kwargs)
total=False表示这些键都是可选的,类型检查器会验证传入的关键字参数是否符合定义的类型。
为什么之前的Union[int, Dict[str, Any]]能通过检查?
这个标注是告诉类型检查器,每个关键字参数的值可以是int或Dict[str, Any],刚好匹配你传入的number=int,因此不会报错。但这是一种妥协的写法,并不符合你实际想表达的“kwargs是一个任意键值对的字典”的语义,建议优先使用前面的正确标注方式。
内容的提问来源于stack exchange,提问作者ChrissyP
相关产品推荐
相关产品推荐

