Hul*_*ner 5 python types type-hinting higher-kinded-types python-3.x
假设我有一个函数接受一个值和任意数量的函数,让我们调用 chain_call 的函数。
如果没有类型,一个简单的实现将是:
def chain_call(input_value, *args):
for function in args:
input_value = function(input_value)
return input_value
Run Code Online (Sandbox Code Playgroud)
如你想象,将input_value可以是任何东西真的,但它总是一样的第一的第一个也是唯一需要的参数Callable在*args: List[Callable]。
从这里开始,Callable第一个也是唯一必需的参数与前一项返回类型的类型相同。
到目前为止,我已经设法定义了一个非常通用的类型,但它太松散了。
def chain_call(input_value: Any, *args: List[Callable[Any], Any]) -> Any: ...
Run Code Online (Sandbox Code Playgroud)
我真正喜欢的是这样的
T = TypeVar('T')
def chain_call(input_value: T, *args: List[Callable[T, ...], tr]) -> tr: ...
Run Code Online (Sandbox Code Playgroud)
其中TforCallable n+1是trof Callable n,最终返回类型是 tr of Callable n_max。我不确定如何用类型系统表达这一点,并且希望得到任何指导。
这个完全类型化的函数存在于dry-python/returns.
我们称之为flow:
from returns.pipeline import flow
assert flow('1', int, float, str) == '1.0'
Run Code Online (Sandbox Code Playgroud)
问题是,它是通过我们的库附带的flow自定义插件完全键入的。mypy因此,它将捕获此错误情况(以及许多其他错误情况):
from returns.pipeline import flow
def convert(arg: str) -> float:
...
flow('1', int, convert)
# error: Argument 1 to "convert" has incompatible type "int"; expected "str"
Run Code Online (Sandbox Code Playgroud)
文档:https ://returns.readthedocs.io/en/latest/pages/pipeline.html