使用返回类型声明处理 Python 类型检查器错误(字段默认值)

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

我在使用 Pyright 类型检查器的 Python 代码中遇到问题,特别是当我尝试从返回类型声明中删除 Any 时。

错误信息:

Function with declared return type "int" must return value on all code paths. "None" is incompatible with "int".

现在每个路径都会在某个时刻返回一个 int,这是一个错误还是我只需将 Union 事物用作 python 事物。

from dataclasses import dataclass
from typing import Any, Union, List

@dataclass
class IntOrString:
    I: Union[int, None] = None
    S: Union[str, None] = None

def funny_sum(xs: List[IntOrString]) -> int | Any:
    if not xs:
        return 0
    
    head, *tail = xs

    match head:
        case IntOrString(I=i) if i is not None:
            return i + funny_sum(tail)
        case IntOrString(S=s) if s is not None:
            return len(s) + funny_sum(tail)

xs: List[IntOrString] = [IntOrString(I=1), IntOrString(S="hello"), IntOrString(I=3), IntOrString(S="world")]
# Output will be 1 + 5 + 3 + 5 = 14
result = funny_sum(xs)

错误

def funny_sum(xs: List[IntOrString]) -> int: { ... }

在 Swift 中,枚举支持模式匹配,并且此代码可以正常工作。这是否意味着Python中的数据类不支持模式匹配?

我很感谢任何有关使用 Python 中的返回类型声明解决此问题的建议。

python pattern-matching python-typing pyright
1个回答
1
投票

类型检查器警告函数可能返回

None
的原因是因为并非所有模式都已用尽。

如果

head
中只有(恰好)1 个字段是
None
,则必然会匹配其中一种情况。但是,如果
I
S
都是
None
会发生什么?

在这种情况下,所有情况都不会匹配,函数将返回

None

由于 Python 的

dataclass
不允许定义互斥类型,因此您有 2 个选择。

添加一个应该引发错误的默认情况,或者您可以将

IntOrString
更改为具有
str | int
类型的单个字段。

选项 1 - 添加默认情况

def funny_sum(xs: List[IntOrString]) -> int | Any:
    if not xs:
        return 0
    
    head, *tail = xs

    match head:
        case IntOrString(I=i) if i is not None:
            return i + funny_sum(tail)
        case IntOrString(S=s) if s is not None:
            return len(s) + funny_sum(tail)
        case _:
            raise ValueError("Either I or S must be set!")

xs: List[IntOrString] = [IntOrString(I=1), IntOrString(S="hello"), IntOrString(I=3), IntOrString(S="world")]
# Output will be 1 + 5 + 3 + 5 = 14
result = funny_sum(xs)

选项 2 - 修改 IntOrString 类型

from dataclasses import dataclass
from typing import Any, Union, List

@dataclass
class IntOrString:
    V: Union[int, str]

def funny_sum(xs: List[IntOrString]) -> int | Any:
    if not xs:
        return 0
    
    head, *tail = xs

    match head.V:
        case int() as i:
            return i + funny_sum(tail)
        case str() as s:
            return len(s) + funny_sum(tail)

xs: List[IntOrString] = [IntOrString(V=1), IntOrString(V="hello"), IntOrString(V=3), IntOrString(V="world")]
# Output will be 1 + 5 + 3 + 5 = 14
result = funny_sum(xs)

选项 3 - 强制类型检查器

您可以强制类型检查器忽略推断的类型,而是使用您告诉它的类型。

def funny_sum(xs: List[IntOrString]) -> int:  # pyright: ignore
    ...
© www.soinside.com 2019 - 2024. All rights reserved.