代码之家  ›  专栏  ›  技术社区  ›  exhuma

如果返回类型取决于参数的输入类型,如何键入提示函数?

  •  5
  • exhuma  · 技术社区  · 8 年前

    假设我有一个函数,可以将Python数据类型转换为Postgres数据类型,如下所示:

    def map_type(input):
        if isinstance(input, int):
            return MyEnum(input)
        elif isinstance(input, str):
            return MyCustomClass(str)
    

    我可以键入以下提示:

    def map_type(input: Union[int, str]) -> Union[MyEnum, MyCustomClass]: ...
    

    但是这样的代码即使正确,也无法进行类型检查:

    myvar = map_type('foobar')
    print(myvar.property_of_my_custom_class)
    

    完整示例(工作代码,但类型提示错误):

    from typing import Union
    from enum import Enum
    
    
    class MyEnum(Enum):
        VALUE_1 = 1
        VALUE_2 = 2
    
    
    class MyCustomClass:
    
        def __init__(self, value: str) -> None:
            self.value = value
    
        @property
        def myproperty(self) -> str:
            return 2 * self.value
    
    
    def map_type(value: Union[int, str]) -> Union[MyEnum, MyCustomClass]:
    
        if isinstance(value, int):
            return MyEnum(value)
        elif isinstance(value, str):
            return MyCustomClass(value)
        raise TypeError('Invalid input type')
    
    
    myvar1 = map_type(1)
    print(myvar1.value, myvar1.name)
    
    myvar2 = map_type('foobar')
    print(myvar2.myproperty)
    

    我知道我可以将映射分为两个函数,但目标是拥有一个泛型类型映射函数。

    我也在考虑使用类和多态性,但是我该如何输入最顶级的类方法呢?因为它们的输出类型将取决于具体的实例类型。

    1 回复  |  直到 8 年前
        1
  •  12
  •   Michael0x2a    8 年前

    这到底是什么 function overloads

    简而言之,您可以执行以下操作:

    from typing import overload
    
    # ...snip...
    
    @overload
    def map_type(value: int) -> MyEnum: ...
    
    @overload
    def map_type(value: str) -> MyCustomClass: ...
    
    def map_type(value: Union[int, str]) -> Union[MyEnum, MyCustomClass]:
        if isinstance(value, int):
            return MyEnum(value)
        elif isinstance(value, str):
            return MyCustomClass(value)
        raise TypeError('Invalid input type')
    

    现在,当你这么做的时候 map_type(3) ,mypy将理解返回类型为 MyEnum .

    在运行时,唯一真正运行的函数是最后一个——前两个函数被完全重写和忽略。