首页 > 解决方案 > 使用 *args 时函数参数的类型安全 (mypy)

问题描述

使用 对以下代码进行类型检查mypy

def foo(a: str, b: float, c: int):
    print(a, b, c + 1)

foo('ok', 2.2, 'bad')

也揭示了无效的呼叫foo

error: Argument 3 to "foo" has incompatible type "str"; expected "int"

现在假设我们有一个如下的包装函数:

from typing import Callable, Any

def say_hi_and_call(func: Callable[..., Any], *args):
    print('Hi.')
    func(*args)

并使用它进行无效调用

say_hi_and_call(foo, 'ok', 2.2, 'bad')

mypy不会报告任何错误,相反我们只会在运行时了解此错误:

TypeError: must be str, not int

我想早点发现这个错误。是否有可能以mypy能够报告问题的方式细化类型注释?

标签: pythontypespython-3.6typecheckingmypy

解决方案


好的,我想出的唯一解决方案是使函数的数量明确,即

from typing import Any, Callable, TypeVar

A = TypeVar('A')
B = TypeVar('B')
C = TypeVar('C')

def say_hi_and_call_ternary(func: Callable[[A, B, C], Any], a: A, b: B, c: C):
    print('Hi.')
    func(a, b, c)

def foo(a: str, b: float, c: int):
    print(a, b, c + 1)

say_hi_and_call_ternary(foo, 'ok', 2.2, 'bad')

当然,也需要类似的say_hi_and_call_unary等等say_hi_and_call_binary

但是由于我重视我的应用程序不会在 PROD 中爆炸而不是保存一些 LOC,所以我很高兴mypy能够报告错误,现在肯定是这种情况:

error: Argument 1 to "say_hi_and_call_ternary" has incompatible type "Callable[[str, float, int], Any]"; expected "Callable[[str, float, str], Any]"

推荐阅读