代码之家  ›  专栏  ›  技术社区  ›  Tobias Hermann

使用*args时函数参数的类型安全性(mypy)

  •  2
  • Tobias Hermann  · 技术社区  · 6 年前

    使用检查下列代码的类型 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')
    

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

    TypeError: must be str, not int
    

    我想早点发现这个错误。是否有可能以这样的方式优化类型注释 梅皮 能报告问题吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Tobias Hermann    6 年前

    好的,我唯一想到的解决方案是使函数的arity显式,即。

    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]"