Python 中的递归类型以及推断 `type(x)(...)` 类型的困难

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

尝试构建递归类型来注释嵌套数据结构,我点击了以下内容。

根据mypy,此代码是正确的:

IntType = int | list["IntType"] | tuple["IntType", ...]
StrType = str | list["StrType"] | tuple["StrType", ...]


def int2str(x: IntType) -> StrType:
    if isinstance(x, list):
        return list(int2str(v) for v in x)
    if isinstance(x, tuple):
        return tuple(int2str(v) for v in x)
    return str(x)

但不是这个,它应该是等效的:

IntType = int | list["IntType"] | tuple["IntType", ...]
StrType = str | list["StrType"] | tuple["StrType", ...]

def bad_int2str(x: IntType) -> StrType:
    if isinstance(x, (list, tuple)):
        return type(x)(bad_int2str(v) for v in x)  # error here
    return str(x)

错误信息是

line 6: error: Incompatible return value type (
    got "list[int | list[IntType] | tuple[IntType, ...]] | tuple[int | list[IntType] | tuple[IntType, ...], ...]", 
    expected "str | list[StrType] | tuple[StrType, ...]"
)  [return-value]
line 6: error: Generator has incompatible item type 
    "str | list[StrType] | tuple[StrType, ...]"; 
    expected "int | list[IntType] | tuple[IntType, ...]"  [misc]

我假设 mypy 可以推断

type(x)
list
tuple
。 这是 mypy 的限制还是这段代码有问题? 如果是这样,限制来自哪里?

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

Mypy 是一个静态类型检查器,这意味着它在运行时不会评估

type(x)(bad_int2str(v) for v in x)
。所以 Mypy 不可能知道表达式的类型是
StrType

您可以像下面的例子一样给出提示。

def good_int2str(x: IntType) -> StrType:
    if isinstance(x, (list, tuple)):
        ty: type[list | tuple] = type(x)
        return ty(good_int2str(v) for v in x)
    return str(x)

def another_good_int2str(x: IntType) -> StrType:
    if isinstance(x, (list, tuple)):
        return cast(type[list | tuple], type(x))(
            another_good_int2str(v) for v in x)
    return str(x)
© www.soinside.com 2019 - 2024. All rights reserved.