Python 中的 compose 函数的类型检查似乎不起作用

问题描述 投票:0回答:1

我正在尝试注释“compose”函数的类型,但我无法让 mypy 告诉我我错了。

在下面的代码中,first 和 eval 的定义按预期工作,将返回类型更改为(比如说)int 会给我一个错误。

但是,compose 的定义却不然。我可以将结果函数的返回值更改为几乎任何值,而 mypy 不会注意到它。

应该是这样吗?我可以做什么来进行类型检查以检查特定类型?

from typing import Sequence, TypeVar, Callable

T = TypeVar('T')
S = TypeVar('S')
H = TypeVar('H')

def first(l: Sequence[T], h : Sequence[S]) -> tuple[T,S]:
    return (l[0],h[0])

def eval(f : Callable[[T],S], arg : T) -> S :
    return f(arg)

def compose (f : Callable[[T],S], g : Callable[[H],T]) -> Callable[[H],int]: #no complaints?
    def aux(x):
        a = g(x)
        b = f(a)
        return b
    return aux
python mypy
1个回答
2
投票

您需要向内部函数添加类型,对于您需要的最通用的解决方案

ParamSpec

from typing import Callable, TypeVar, ParamSpec


T = TypeVar('T')
S = TypeVar('S')
P = ParamSpec('P')


def compose(f: Callable[[S], T], g: Callable[P, S]) -> Callable[P, T]:
    def _composed(*args: P.args, **kwargs: P.kwargs) -> T:
        a = g(*args, **kwargs)
        b = f(a)
        return b
    return aux

当然,如果您只是将一个参数硬编码到组合函数中,则不需要

ParamSpec
— 只需
TypeVar
就足够了:

from typing import Callable, TypeVar


T = TypeVar('T')
S = TypeVar('S')
R = TypeVar('R')


def compose(f: Callable[[S], R], g: Callable[[T], S]) -> Callable[[T], R]:
    def _composed(arg: T) -> R:
        a = g(arg)
        b = f(a)
        return b
    return aux

更大的挑战是将其推广为可变参数

compose
。 Python 的类型提示系统在变量方面非常有限。据我所知,目前唯一的方法是使用
typing.overload
为每个数量定义单独的类型提示。例如,这是我在
compose
库的类型存根中所做的操作:

from typing import Callable, ParamSpec, TypeVar, overload


P = ParamSpec('P')
R1 = TypeVar('R1')
R2 = TypeVar('R2')
R3 = TypeVar('R3')
# and so on up to whatever arity you want to support.


@overload
def compose(f1: Callable[P, R1], /) -> Callable[P, R1]:
    ...
@overload
def compose(f2: Callable[[R1], R2], f1: Callable[P, R1], /) -> Callable[P, R2]:
    ...
@overload
def compose(f3: Callable[[R2], R3], f2: Callable[[R1], R2], f1: Callable[P, R1], /) -> Callable[P, R3]:
    ...
# and so on up to whatever arity you want to support.
© www.soinside.com 2019 - 2024. All rights reserved.