键入检查函数参数是“Pythonic”吗? [关闭]

Posted

技术标签:

【中文标题】键入检查函数参数是“Pythonic”吗? [关闭]【英文标题】:Is it "Pythonic" to type check function arguments? [closed] 【发布时间】:2022-01-05 08:09:01 【问题描述】:

来自 C/C++ 背景,我一直对 Python 缺乏强大的类型检查感到失望。因此,它总是引导我编写这种风格的代码:

def function (this_should_be_list, this_should_be_int):

    isFristArgList = isinstance(this_should_be_list,list)
    if not isFristArgList:
        raise Exception("The first argument should be a list!")

    isSecondArgInt = isinstance(this_should_be_int,int)
    if not IsSecondArgInt:
        raise Exception ("The second argument should be an int!")

    ....
    ....
    ....

    return

这导致代码更加复杂和臃肿,在我的理解中,这与编写尽可能清晰的代码的“Pythonic 哲学”相反。与这种动态检查方法相反,有人可能会说,如果没有它,function 也会失败并引发一些异常,因此它并没有什么区别,但我认为这真的很难预测(尤其是在具有多个嵌套调用的更大代码库中)是否存在某些极端情况错误,这些错误将使 function 在“表面”上正确执行,但与我们的预期不符。

所以我的问题是,我应该如何在 Python 中解决这个问题? 由于我以前使用 C/C++ 的经验,我是否只是偏向于强类型的“样式”,并且应该只接受 Python 的鸭子类型? 或者,有没有更优雅的方式在 Python 中进行类型检查?

【问题讨论】:

首先你可以使用类型提示来代替。那么就没有规则了:如果您发现有人在滥用您的 API 或者错误消息在他们这样做时很含糊,那么您就可以开始保护您的 API。否则让鸭子打字行动 虽然 python 不支持强类型检查,但它支持类型提示已经有一段时间了,至少 3.5 及更高版本。请参阅文档中的 Support for type hints。 使用 mypy! mypy-lang.org 【参考方案1】:

使用类型注释和mypy。这为您提供了静态类型检查的所有好处,并且通常不需要对编写 Python 代码的方式进行重大更改,除了在函数声明中添加注释。

# Annotate your parameters like this:
def function(this_should_be_list: list, this_should_be_int: int):
    pass


# Then when you run mypy on your code, it tells you when types don't match:
function([1, 2, 3], 10)  
function(10, "foo")   # error: Argument 1 to "function" has incompatible type "int"; expected "List[Any]"   
                      # error: Argument 2 to "function" has incompatible type "str"; expected "int"

只需运行 mypy 作为常规测试策略的一部分,类似于验证 C++ 代码是否通过编译时检查的方式。如果这样做,通常不需要进行运行时检查,就像在 C++ 代码中一样。

【讨论】:

感谢您的回答,mypy 看起来是一个非常有用的工具! 运行时检查对用户访问的函数仍然有效。特别是当它们防止错误以不清楚的方式出现或在代码的后面出现时。【参考方案2】:

如有必要,可以以 Python 方式完成,但您需要确定 type 是否真正重要。例如,第一个变量 必须list,还是必须是可迭代的?第二个必须是一个int,还是需要一个非零小数部分?

假设这两个问题的答案都是“是”,我会将您的代码修改为:

def function (this_should_be_list, this_should_be_int):

    if not hasattr(this_should_be_list, '__iter__'):
        raise Exception("The first argument should be an iterable!")

    if this_should_be_int%1 != 0:
        raise Exception ("The second argument should be integer!")

    ....
    ....
    ....

    return

【讨论】:

以上是关于键入检查函数参数是“Pythonic”吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何在流中键入检查日期对象?

什么是更 Pythonic - 函数组合、lambdas 或其他东西? [关闭]

检查参数类型的 Pythonic 方法

导入内部函数是pythonic吗?

应用三参数函数“减少”列表的pythonic方法是啥?

函数返回多个值是pythonic吗?