为什么不能使用 Dict[str, Any] 或 Mapping[str, Any] 来输入 **kwargs?你应该怎么打字?

问题描述 投票:0回答:1

我目前正在尝试学习如何最好地在我的 Python 代码中包含类型,但我对如何在我的函数签名中正确键入

**kwargs
感到有点困惑。

我目前拥有的一个最小例子:

def foo(name: str, **kwargs: Dict[str, 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: Dict[str, Any]) -> int:

    name: str = some_func(id_number)
    
    return foo(name, number=id_number, **kwargs)

我期望发生什么:由于

foo
没有指定
number
关键字参数,我希望它被收集到
foo
kwargs
中,这本质上是一个
Dict[str, Any]
。由于“int”是“Any”类型,我应该不会对打字有任何抱怨。

真正发生的事情:在运行时,

number
被收集到
foo
kwarg
s 和
some_other_func
可以安全地提取
number
关键字参数。然而,mypy(版本 1.1.1)抱怨如下

error: Argument "number" to "foo" has incompatible type "int"; expected "Dict[str, Any]"

pyright(版本 1.1.292)的类似投诉:

Argument of type "int" cannot be assigned to parameter "number" of type "Dict[str, Any]" in function "foo"  "int" is incompatible with "Dict[str, Any]"

这是预期的行为吗?如果我传递直接被调用者在函数签名中没有的关键字参数,我是否应该期望类型检查器抱怨?

继续这个我想好吧,我将直接在

number
中添加
kwargs
作为键(我不确定这是否是好的做法,但这不是重点),所以这样我肯定会通过一个
Dict[str, Any]
。这基本上是我尝试过的:

def bar(id_number: int, **kwargs: Dict[str, Any]) -> int:

    name: str = some_func(id_number)
    
    kwargs[number] = id_number
    
    return foo(name, **kwargs)

但是现在我得到错误(来自 mypy):

error: Incompatible types in assignment (expression has type "int", target has type "Dict[str, Any]"

类似来自pyright:

Argument of type "int" cannot be assigned to parameter "__value" of type "Dict[str, Any]" in function "__setitem__"  "int" is incompatible with "Dict[str, Any]"

但这更令人困惑,为什么他们似乎暗示我正在分配给

kwargs
,而实际上我正在分配给
kwargs
中的一个键?

这是否意味着我应该在 inside

kwargs
中输入值?

如果我输入

kwargs
作为“Union[int, Dict[str, Any]]”,我没有遇到任何问题。所以这似乎证实了这个问题。但是为什么会有不同的行为呢?我们应该知道
kwargs
是一个映射,所以避免额外的打字换行,这仅仅是为了方便吗?但我在任何地方都看不到这一点,我也不是 100% 相信我对它的工作原理是正确的。

最后,我也尝试过使用

Mapping[str, Any]
而不是
Dict[str, Any]
,但它有同样的问题。

tl;dr:

kwargs
是一个包含函数签名未指定的关键字的字典,它可以像
Dict[str, Any]
一样访问和修改。为什么我不能像一个一样打字?我应该怎么打字?

python mypy python-typing pyright
1个回答
0
投票

当您使用

**kwargs
时,密钥始终是一个字符串。要对该键的值进行类型检查,您只需对该键的一个可能值进行类型检查。 有关更多详细信息,请查看this问题及其答案。

© www.soinside.com 2019 - 2024. All rights reserved.