嵌套字典上的参数过多或参数过多

问题描述

我正在尝试以dict类型添加类型提示,该类型提示具有多个将功能绑定到它们的字段。 例如

from typing import Dict,Callable,Any,Union

def fn():
  print("Hello World")

def fn2(name):
   print("goodbye world",name)

d = {
  "hello" : {
    "world": fn
  },"goodbye": {
    "world": fn2
  }
} # type: Dict[str,Dict[str,Union[Callable[[],None],Callable[[str],None]]]]

d["hello"]["world"]()
d["goodbye"]["world"]("john")

我要解决的问题是,每当我尝试运行mypy(v0.782)时都会引发错误:

test2.py:17: error: Too few arguments
test2.py:18: error: Too many arguments

很显然,从函数定义和类型提示可以看出,我已经传递了正确的参数。我显然丢失了一些东西,因为它会引发错误。

但是,以下方法可行,因此我怀疑它与类型提示中的Union类型有关。

from typing import Dict,Union


def fn():
    print("Hello World")


d = {"hello": {"world": fn}}  # type: Dict[str,Callable[[],None]]]

d["hello"]["world"]()

解决方法

让我提醒您,使用Union时,如果不考虑以下约束,则会出现问题中所描述的问题:

只有对每个联合项目有效的操作才对联合类型有效。这就是为什么经常需要使用isinstance()检查以首先将联合类型缩小为非联合类型的原因。这也意味着建议避免使用union类型作为函数返回类型,因为调用者可能必须先使用isinstance()才能对值进行任何有趣的操作。[1]

作为一种解决方法,我建议您使用带有可选参数的单个函数。 我使用Protocol定义了带有可选参数的回调类型,该可选参数无法使用Callable[...]

表示
from typing import Protocol,Optional,Dict


class Fn(Protocol):
    def __call__(self,name: Optional[str] = None) -> None:
        ...


def fn(name: Optional[str] = None) -> None:
    if name is None:
        print("Hello World")
    else:
        print("goodbye world",name)


d: Dict[str,Dict[str,Fn]] = {
    "hello": {
        "world": fn
    },"goodbye": {
        "world": fn
    }
}

d["hello"]["world"]()
d["goodbye"]["world"]("john")

[1] https://mypy.readthedocs.io/en/stable/kinds_of_types.html#union-types

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...