首页 > 解决方案 > Python 3.5+ 中类型提示的动态检查

问题描述

typing模块在 Python 3.5+ 中实现了类型提示。但是,这不是强制的,它目前似乎只是为了静态类型检查器的利益而存在,mypy例如PyCharm。我希望这将是鸭子打字的可行替代方案。

问题:有没有办法在 Python 3.7+ 中打开我在 Google 搜索中找不到的动态类型检查?例如,如果我定义

def greeting(name: str) -> str:
    return name

那么这应该在执行时失败:

greeting([12])

我不介意为此检查付出时间代价,因为出于我的目的,无论如何我都必须使用assert语句手动实现它,并且类型提示更加简洁和描述性。

更新:下面的评论者注意到typen包将动态地为我强制执行类型提示。所以这是一个肯定的答案,它将更新一个旧问题的答案,该问题的范围是 Python 3.6 并以否定的形式回答。我已经验证了规范typen示例按预期工作:

from typen import enforce_type_hints

@enforce_type_hints
def halve_integer(a: int) -> float:
    return a / 2

halve_integer(5)  # 2.5
halve_integer(5.0)  # ParameterTypeError

唯一的缺点是每个函数都需要被修饰来获得行为,而不是有一个开关来为所有事情打开它。

更新 2:下面的答案还指出pydantic也解决了这个问题。所以这是两个积极的解决方案。然而,pydantic似乎更倾向于数据建模,并且对他们的验证装饰器有一些强烈的警告:

validate_arguments 装饰器处于beta 阶段,它已在 v1.5 中临时添加到 pydantic 中。它在未来的版本中可能会发生重大变化,并且它的接口在 v2 之前不会是具体的。当它仍然是临时的时,来自社区的反馈将非常有用;评论 #1205 或创建一个新问题。

标签: pythonpython-3.xduck-typingpython-typing

解决方案


我喜欢这个帖子中给出的答案,所以我会在这里给出:

您可以在 Python3 中使用注解,这可能会帮助您获得静态类型的一些好处。

但是,如果要在 Python 中完全强制执行静态类型,那么它就不再是 Python 了。它是一种鸭式的动态语言,因此会失去所有的活力。如果你真的打算使用静态类型语言,最好不要使用 Python。

并引用 PEP 563 中的话:

Python 仍将是一种动态类型语言,作者不希望强制类型提示,即使按照惯例

就个人而言,有些工具在运行时使用类型注释进行类型检查和验证,因为注释可以通过__annotations__属性访问。例如,我在项目中使用的pydantic 。但它有自己的特点,例如,它尽可能地尝试进行隐式类型转换。

一些例子:

from pydantic import validate_arguments, ValidationError, BaseModel
... 
... 
... @validate_arguments
... def sum_foo(a: int, b: int) -> int:
...     return a + b
... 
sum_foo("Hello", 1)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "pydantic/decorator.py", line 25, in pydantic.decorator.validate_arguments.wrapper_function
  File "pydantic/decorator.py", line 107, in pydantic.decorator.ValidatedFunction.call
  File "pydantic/main.py", line 346, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for SumFoo
a
  value is not a valid integer (type=type_error.integer)
class data(BaseModel):
...     a: int = 0
...     b: int = 1
...     
d = data(a=0, b="Hello")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "pydantic/main.py", line 346, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for data
b
  value is not a valid integer (type=type_error.integer)


推荐阅读