gpt4 book ai didi

mypy - 短路 `or` 的窄类型,当我有两种可能的情况时

转载 作者:行者123 更新时间:2023-12-02 15:45:46 28 4
gpt4 key购买 nike

我正在尝试注释以下代码。

当同时定义了 zonezones 时,或者当定义了 file 时(但不是同时定义了两者),该函数将起作用:

def get_file(zone: str, zones: dict[str, str]) -> pathlib.Path:
pass

def connect(
zone: str | None = None,
zones: dict[str, str] | None = None,
file: pathlib.Path | None = None,
) -> bool:
file = file or get_file(zone, zones)

但这让 mypy 生气了 -

1. Argument of type "str | None" cannot be assigned to parameter "zone" of type "str" in function "_get_vpn_file"
  Type "str | None" cannot be assigned to type "str"
    Type "None" cannot be assigned to type "str"
2. Argument of type "dict[str, str] | None" cannot be assigned to parameter "zones" of type "dict[str, str]" in function "_get_vpn_file"
  Type "dict[str, str] | None" cannot be assigned to type "dict[str, str]"
    Type "None" cannot be assigned to type "dict[str, str]"

然后我尝试进行一些激进的类型缩小:

def _check_params_are_ok(
zone: str | None, zones: dict[str, str] | None, file: pathlib.Path | None,
) -> tuple[str, dict[str, str], None] | tuple[None, None, pathlib.Path]:
if zone is not None and file is not None:
raise ValueError("Pass `file` or `zone`, but not both.")

if zone is not None and zones is None:
raise ValueError("connect: Must define `zones` when `zone` is defined.")

if zone is None and file is None:
raise ValueError("connect: Must define `zone` or `file`.")

assert file is not None or (zone is not None and zones is not None)

# Type narrowing
if zone is not None and zones is not None and file is None:
return zone, zones, file
if zone is None and zones is None and file is not None:
return zone, zones, file

raise NotImplementedError("This error from _check_params_ok shouldn't happen.")


def connect(
zone: str | None = None,
zones: dict[str, str] | None = None,
file: pathlib.Path | None = None,
) -> bool:
zone, zones, file = _check_params_are_ok(zone, zones, file)
file = file or get_file(zone, zones)

而且 mypy 仍然显示相同的错误。

即使添加非常明确的断言,Mypy 仍然显示相同的错误:

    zone, zones, file = _check_params_are_ok(zone, zones, file)
if file is None:
assert zone is not None and zones is not None
file = file or get_file(zone, zones)

目前我找到的最佳解决方案是内联转换类型,但这会影响代码的可读性并使行难以阅读:

    file = file or get_file(cast(str, zone), cast(dict[str, str], zones))

有没有什么好的方法可以缩小类型?

最佳答案

在您的代码中,当您执行 - 正如您所说的那样 - 非常清晰的断言时,您只能在 if< 的主体中分配给 file/声明:

if file is None:
assert zone is not None and zones is not None
file = get_file(zone, zones)

# file is now a pathlib.Path object
assert file.is_file() # this is now valid

那么你会非常明确,mypy 不应该再对此提示了。

关于mypy - 短路 `or` 的窄类型,当我有两种可能的情况时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74301962/

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