Python类型提示:函数返回类型,以参数形式给出,但类型是通用别名,例如Union

问题描述

即使提供了我们期望的类型作为其参数之一,我们也可以轻松地指定函数的返回类型:

from typing import TypeVar,Type,Union

T = TypeVar('T')


def to(t: Type[T],v) -> T:
    return t(v)


s: str = to(str,1)
i: int = to(str,1)  # Ok: Expected type 'int',got 'str' instead

但是如果我们提供Union [str,int]作为第一个参数是行不通的(看不到函数本身,我们可以对此Union做一些更复杂的事情,即基于所提供的Union构建pydantic模型)

G = Union[str,int]
g: G = to(G,1) # Expected type 'Type[T]',got 'object' instead 

那么如何指定函数的返回类型应该是作为第一个参数提供的呢?即使我们不提供int或str之类的纯类型,也可以提供Union?

更新

更准确地说,是我想装饰的功能

from typing import Type,Union

from pydantic import validate_arguments,BaseModel


def py_model(t,v: dict):
    def fabric():
        def f(x):
            return x

        f.__annotations__['x'] = t
        return validate_arguments(f)

    f = fabric()
    return f(v)

class Model1(BaseModel): foo: int
class Model2(BaseModel): bar: str

print(repr(py_model(Union[Model1,Model2],{'foo':1}))) # Model1(foo=1)
print(repr(py_model(Union[Model1,{'bar':1}))) # Model2(bar='1')

因此,当我调用py_model(Union [Model1,Model2],...)时,我希望它会返回Model1或Model2中的一个,因此会返回Union [Model1,Model2]

解决方法

to函数中使用“ Callable”代替操作符来构造类型怎么样?

然后您可以将Union类型的构造函数用作参数。

这种实现的一个例子是:

from typing import Any,Callable,TypeVar,Type,Union

T = TypeVar('T')
V = TypeVar('V')


def to(t: Callable[[V],T],v: V) -> T:
    return t(v)

G = Union[str,int]

def build_g(v:G) -> G:
    return v if isinstance(v,int) else str(v)


s: str = to(str,1)
i1: int = to(int,1)
i2: int = to(str,1)  # Ok: Expected type 'int',got 'str' instead

g1: G = to(build_g,1) # No error raised
g2: G = to(build_g,"2") # No error raised

上面的代码仅在i2的mypy中引发错误