python类型注释中的链接引用

假设我有一个函数,它接受一个值和任意数量的函数,让我们调用chain_call的函数.

没有类型,简单的天真实现将是:

def chain_call(input_value, *args):
    for function in args:
        input_value = function(input_value)
    return input_value

正如您想象的那样,input_value可能是真正的任何东西,但它始终与* args中的第一个Callable中唯一必需的参数相同:List [Callable].

从此处开始,Callable的第一个也是唯一必需的参数与前一个返回类型的类型相同.

到目前为止,我已经设法定义了一个非常通用的类型,但它太松散了.

def chain_call(input_value: Any, *args: List[Callable[Any], Any]) -> Any: ...

我真正喜欢的是什么

T = TypeVar('T')

def chain_call(input_value: T, *args: List[Callable[T, ...], tr]) -> tr: ...

其中,Calable n 1的T是Callable n的tr,最终的return-type是Callable n_max的tr.我不知道如何用类型系统表达这一点,并且会喜欢任何指导.

最佳答案 不幸的是,目前这不是可以使用PEP 484类型提示键入的内容.

你可以做的最好的事情是使用重载来近似签名:基本上,我们硬编码签名应该达到一定数量然后再回到推断’任何’:

from typing import TypeVar, overload, Any, Callable

T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
T4 = TypeVar('T4')

@overload
def chain_call(input_value: T1, 
               *f_rest: Callable[[T1], T1]) -> T1: ...
@overload
def chain_call(input_value: T1, 
               f1: Callable[[T1], T2],
               f2: Callable[[T2], T3],
               f3: Callable[[T3], T4],
               f4: Callable[[T4], Any],
               *f_rest: Callable[[Any], Any]) -> Any: ...
@overload
def chain_call(input_value: T1, 
               f1: Callable[[T1], T2],
               f2: Callable[[T2], T3],
               f3: Callable[[T3], T4]) -> T4: ...
@overload
def chain_call(input_value: T1, 
               f1: Callable[[T1], T2],
               f2: Callable[[T2], T3]) -> T3: ...
@overload
def chain_call(input_value: T1, 
               f1: Callable[[T1], T2]) -> T2: ...
def chain_call(input_value, *f_rest):
    for function in f_rest:
        input_value = function(input_value)
    return input_value

在这里,我硬编码了最多3个输入函数应该发生的事情(并且在所有callables碰巧具有相同输入和输出类型的特殊情况下以重载开始).

这种技术是类型化的当前类型,如zip函数,它可以接受任意数量的iterables.

注意:您可能需要使用master中最新版本的mypy才能使此代码逐字工作.

点赞