您可以根据传递给构造函数的参数输入提示重载方法的返回类型吗?

Cag*_*ury 2 python overloading type-hinting python-3.x

假设我有一堂这样的课:

class myclass:
    def __init__ (self, param1: Tuple[str,...], param2: bool) -> None:
        self.member1 = param1
        self.member2 = param2
        self.member3 = 10

    def gimmie(self) -> int | Tuple[str,...]:
        return self.member1 if self.member2 else self.member3
Run Code Online (Sandbox Code Playgroud)

有什么方法可以确保 gimmie 的返回不是类型而是int | Tuple[str,...]orint 类型 Tuple[str,...]

编辑:

有几个答案涉及到重要的杂技来做到这一点,而我真正想做的只是cast返回。因此,每个答案都对代码“气味”进行了评论。

问题很简单,我构造了一个带有标志的对象,并且其中一个方法根据该标志返回两种类型中的一种。如果这是糟糕的设计,那么“正确”的方法是什么?

Jas*_*ijn 6

这是使用泛型解决此问题的方法:

from __future__ import annotations
from typing import overload, Literal, Generic, TypeVar, cast

T = TypeVar('T')


class myclass(Generic[T]):
    member1: tuple[str, ...]
    member2: bool
    member3: int

    @overload
    def __init__(self: myclass[tuple[str, ...]], param1: tuple[str, ...], param2: Literal[True]) -> None:
        ...

    @overload
    def __init__(self: myclass[int], param1: tuple[str, ...], param2: Literal[False]) -> None:
        ...

    def __init__(self, param1: tuple[str, ...], param2: bool) -> None:
        self.member1 = param1
        self.member2 = param2
        self.member3 = 10

    def gimmie(self) -> T:
        return cast(T, self.member1 if self.member2 else self.member3)


reveal_type(myclass(('a', 'b'), True).gimmie())
# note: Revealed type is "builtins.tuple*[builtins.str]"

reveal_type(myclass(('a', 'b'), False).gimmie())
# note: Revealed type is "builtins.int*"
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 这种方法需要注释self参数以赋予其不同的静态类型。通常,我们不会注释self,所以请确保不要忘记这一点!
  • 遗憾的是,a if b else c如果不添加cast.

我确实同意 Samwise 的观点,即这种类型的柔道是一种代码味道,并且可能隐藏了项目设计的问题。