Python类型暗示:函数返回类型,作为参数提供,但类型是通用别名,如Union
我们可以很容易地指定函数的返回类型,即使我们期望的类型作为它的参数之一提供:Python类型暗示:函数返回类型,作为参数提供,但类型是通用别名,如Union,python,generics,types,mypy,pydantic,Python,Generics,Types,Mypy,Pydantic,我们可以很容易地指定函数的返回类型,即使我们期望的类型作为它的参数之一提供: 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
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模型)
那么,如何指定函数的返回类型应该是作为第一个参数提供的类型呢?即使我们提供的不是像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, Model2], {'bar':1}))) # Model2(bar='1')
因此,当我调用py_模型(Union[Model1,Model2],…)时,我希望它将返回Model1或Model2中的一个,因此Union[Model1,Model2]对to
函数使用“Callable”而不是运算符来构造类型,怎么样
然后可以将Union类型的构造函数作为参数
这种实施的一个例子是:
输入import Any、Callable、TypeVar、Type、Union
T=TypeVar('T')
V=TypeVar('V')
def to(t:Callable[[V],t],V:V)->t:
返回t(v)
G=联合[str,int]
def build_g(v:g)->g:
如果isinstance(v,int)或else str(v),则返回v
s:str=to(str,1)
i1:int=to(int,1)
i2:int=to(str,1)#确定:应为“int”类型,改为“str”
g1:G=to(build_G,1)#未引发错误
g2:G=to(build_G,“2”)#未引发错误
上面的代码只会在mypy中为
i2
Yes引发一个错误,因为G
不是一个类型。您希望联合[str,in](1)如何工作?很明显,G是泛型别名,所以我想用一些魔术来提供泛型别名,并使函数返回一些与此别名对应的实例。i、 e.Union[Model1,Model2],f将根据提供的值构造Model1或Model2中的一个,因此我想指定函数的返回类型也是Union[Model1,Model2],这没有魔力。您必须使用所需的逻辑编写一个实际执行该操作的函数function@AntonOvsyannikovJuanpa所说的是构造泛型类型的函数,而不是使用来
的函数。我已经发布了一个答案,可能会回答你的需要。工作,但实际上有点棘手。非常奇怪的是,泛型别名与类型相差如此之大,它们应该可以互换用作注释,所以应该有一些通用协议。
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, Model2], {'bar':1}))) # Model2(bar='1')