如果传递给带注释函数的参数类型与指定函数不匹配,是否可能产生python throw错误?

时间:2015-09-19 11:01:01

标签: python type-hinting python-3.5

python3.5的一个新功能是类型提示。例如,下面的代码现在有效:

def greeting(name: str) -> str:
    return 'Hello ' + name

但是,据我所知,它本身并没有检查任何东西,而且解释方式与此完全相同:

def greeting(name):
    return 'Hello ' + name

主要用于帮助静态分析器(并使代码更容易理解)。但是当将无效类型的参数传递给具有带注释的参数类型的函数时,是否存在(或计划在未来实施)以任何方式(可能通过使用某些第三方库)来发出python throw错误(仅使用类型提示语法)?

4 个答案:

答案 0 :(得分:5)

类型提示实现PEP 0484明确列为非目标

  

虽然建议的输入模块将包含一些构建块   运行时类型检查 - 特别是get_type_hints()函数    - 必须开发第三方软件包以实现特定的运行时类型检查功能,例如使用   装饰者或元类。使用类型提示来提高性能   优化是留给读者的练习。

由此可见,Python开发人员没有计划添加您所寻求的功能。引用提到装饰者,这似乎是要走的路。在概念中它似乎很简单 - 装饰器将对要装饰的函数使用get_type_hints()并迭代参数,根据任何提示检查它们的类型,如果存在冲突则抛出错误或者仅仅传递函数的参数。这与pzelasko的答案类似,但装饰者使用提示自动处理锅炉板代码。最简单的方法是简单地审查参数,但是如果返回类型与提示冲突,你也应该能够创建一个会引发错误的装饰器。我还没有Python 3.5并且没有时间去追求它 - 但对于想要了解装饰器和类型提示的人来说,这似乎是一个很好的学习练习。也许你可以成为PEP所暗示的“第三方”之一。

答案 1 :(得分:0)

我认为最简单的方法是检查类型:

def greeting(name):
    if type(name) is not str:
        raise TypeError('Expected str; got %s' % type(name).__name__)
    return 'Hello ' + name

答案 2 :(得分:0)

一个人可以使用库https://github.com/h2oai/typesentry在运行时执行此操作。

答案 3 :(得分:0)

自 python 3.7 发布以来,可以使用 functools.singledispatch 来做到这一点。

from functools import singledispatch

@singledispatch
def greet(arg: object):
    raise NotImplementedError(f"Don't know how to greet {type(arg)}")

@greet.register
def _(arg: str):
     print(f"Hello, {arg}!")
    
@greet.register
def _(arg: int):
    print(', '.join("Hello" for _ in range(arg)), "!")

greet("Bob")          # string implementation is called — prints "Hello, Bob!"
greet(4)              # int implementation is called — prints "Hello, Hello, Hello, Hello!"
greet(["Alice, Bob"]) # no list implementation, so falls back to the base implementation — will raise an exception

在上面的示例中,注册了将引发 NotImplementedError 的基本实现。这是在没有其他实现适合时返回的“回退”实现。

按照基本实现的定义,可以注册任意数量的特定于类型的实现,如示例所示——函数的行为完全不同,具体取决于提供给它的参数的类型,而 { {1}} 方法使用类型注释来注册具有特定 @singledispatch 的函数的特定实现。

一个 type 函数可以有任意数量的参数,但只有第一个参数的类型注释与调用哪个实现相关。