如何在 Python 中有效地使用泛型来对具有两个相同类型(int 或 str)参数的函数进行类型提示?

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

我有一个函数,它接受两个相同类型的参数,可以是 int 或 str。我最初没有泛型的实现如下所示: 蟒蛇

def combine1(a: int | str, b: int | str) -> int | str:
    match a:
        case int():
            match b:
                case int():
                    return a + b
                case str():
                    return "error"
        case str():
            match b:
                case int():
                    return "error"
                case str():
                    return a + b

这个实现效率很低,因为它检查 b 的类型,即使我们知道它必须与 a 具有相同的类型。它还允许 a 和 b 具有不同类型的可能性,这不是预期的行为。 为了改进这一点,我想使用泛型让 mypy 理解 a 和 b 具有相同的类型。这是我的尝试: 蟒蛇

def combine2[T: int | str](a: T, b: T) -> T:
    match a:
        case int():
            return a + b
        case str():
            return a + b

但是,mypy 报告以下错误:

文本错误:返回值类型不兼容(得到“int”,预期“T”) [返回值]错误: + 不支持的操作数类型(“int”和“T”) [运算符]错误:返回值类型不兼容(得到“str”,预期 "T") [返回值] 错误: + ("T" 和 “T”)[运算符]

如何修改此函数以正确使用泛型并满足 mypy 的类型检查,同时确保该函数仅接受相同类型的两个参数(均为 int 或均为 str)并避免第一个实现的低效率?

这个问题与这个问题不同:如何使用类型提示来确保两个变量始终具有相同的类型?

因为我尝试建议使用泛型来解决这个问题。这个问题没有什么。 此外,这个问题没有在函数内部使用模式匹配。我的观点是避免检查两次变量的类型,因为我已经知道它们具有相同的类型。我只想检查 T 类型。

一个行不通的好解决方案是在类型 T 上使用模式匹配而不是变量

我也尝试过这个:

def combine3[T : int | str](a: T, b: T) -> T:
    match a,b:
        case int(),int():
            return a +b
        case str(), str():
            return a+b

错误:缺少返回语句 [return] 错误:返回不兼容 值类型(得到“int”,预期“T”)[返回值]错误: 返回值类型不兼容(得到“str”,预期为“T”) [返回值]

mypy 无法理解我提出的两种情况是唯一可能的情况。要删除第一个错误,我必须添加默认情况

def combine4[T : int | str](a: T, b: T) -> T:
    match a,b:
        case int(),int():
            return a +b
        case str(), str():
            return a+b
        case _ :
            return a
error: Incompatible return value type (got "int", expected "T")  [return-value]
error: Incompatible return value type (got "str", expected "T")  [return-value]

但我真的无法理解为什么它说函数返回 int 或 str 而不是 T。

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

此代码有效

def combine2[T: (int, str)](a: T, b: T) -> T:
    match a:
        case int():
            return a + b
        case str():
            return a + b

combine2(1,1)
#combine2("h",1) mypy returns an error but this is normal. I don t want the arguments to have a differnet type
combine2("s","j")
#combine2(3,"j") mypy returns an error but this is normal. I don t want the arguments to have a differnet type
© www.soinside.com 2019 - 2024. All rights reserved.