有选择地推断修饰功能的类型

时间:2019-11-29 20:29:23

标签: python typechecking mypy

我有一个装饰函数,该函数填充函数的前两个参数,并且仅要求调用者填充其余参数。它用于处理数据库事务(前两个参数是连接和游标,如果没有异常发生,则提交事务)。

我尝试使mypy推断修饰函数的类型,但跳过前两个参数。不幸的是没有成功。

由于数据库事务代码很复杂,所以我准备了一个简化的示例:

'..' is not recognized as an internal or external command,

装饰器应填充第一个参数,例如与@decorator def add(a: int, b: int, zero: bool = False) -> int: if zero: return 0 else: return a + b 一起使用,并使1函数仅需要一个参数。 add逻辑仅用于确保也存在关键字参数的情况下起作用。

zero
def decorator(fn):

    def wrapper(*args, **kwargs):
        return fn(1, *args, **kwargs)  # note the first argument `1`

    return wrapper

到目前为止我尝试过的事情:

1。

add(1)  # = 2

…很好,但是类型推断仅适用于返回类型,不适用于参数。如果我将参数设置为字符串,mypy不会将其视为问题,并且在运行时会崩溃。

2。

T = TypeVar('T')

def decorator(fn: Callable[..., T]) -> Callable[..., T]:

    def wrapper(*args: Any, **kwargs: Any) -> T:
        return fn(1, *args, **kwargs)  

    return wrapper

…这仅反映了此原始T = TypeVar('T', bound=Callable) def decorator(fn: T) -> T: def wrapper(*args: Any, **kwargs: Any) -> T: return fn(1, *args, **kwargs) return cast(T, wrapper) 函数的签名,并且是错误的。 Mypy将抱怨缺少add的论点。

3。

add

...这是行不通的,因为Args = TypeVar('Args') KwArgs = TypeVar('KwArgs') Result = TypeVar('Result') class OriginalCallable(Protocol): def __call__(self, a: int, *args: Args, **kwargs: KwArgs) -> Result: ... class DecoratedCallable(Protocol): def __call__(self, *args: Args, **kwargs: KwArgs) -> Result: ... def decorator(fn: OriginalCallable) -> DecoratedCallable: def wrapper(*args: Any, **kwargs: Any) -> Result: return fn(1, *args, **kwargs) return cast(DecoratedCallable, wrapper) add的签名不完全匹配,但正确的是,但对于装饰器,我无法知道所有装饰功能的签名。

最后,我该如何解决呢?

关于long thread,关于mypy的装饰器支持尚不完善,但是我的情况尚未完全涵盖。在python中,有一些内置函数可以执行类似的操作(functool.partial,@ staticmethod等),但是找不到如何定义此行为的方法。

0 个答案:

没有答案