我开始进入 python 3.6 中的类型提示(又名注释),并且我无法理解此功能的一些动态方面。
我编写了以下代码段,我想添加注释和即使在查看了有关类型提示的文档后,也不知道如何实现。
这是函数:
def validate_expression(expression: ?):
try:
assert expression
except AssertionError as e:
...
expression
需要是断言起作用的任何内容(假设
bool(expression)
有效的任何表达式)。
我应该写什么而不是问号?
更新:
我知道大多数 python 表达式都可以转换为布尔值,但是我编写此代码的上下文是合理期望表达式的上下文 不 成为可断言的。
我的例子中的相关示例是
pandas.DataFrame
运行
bool(pandas.DataFrame())
会引发错误,我有充分的理由预计有人可能会尝试将数据帧传递给验证函数。
更新2: 以下 Cepner 的评论和答案,我现在明白:
-
在绝大多数情况下,任何 python 表达式都会有效地转换为布尔值,这要么被
typing.Any
覆盖,要么根本不添加注释。 -
在边缘我感兴趣的情况是
bool(pandas.DataFrame()) # --> ValueError
,注释不会有帮助,因为这是一个运行时错误。 - 如果存在与静态类型提示相关的另一个边缘情况,我不知道它。|| |鉴于相关示例的稀有/不存在,没有开箱即用的类型通常只描述转换为布尔值的能力的质量(类似于
-
),并且就我而言不值得费尽心思来解决这种边缘情况(尽管听到相关示例和弯曲解决方案会很有趣!)
typing.Iterable
), and as far as I'm concerned it is not worth bending over backwards to address such an edge case (although it would be interesting to hear of relevant example and a bend-y solution!)
在 Python 中,几乎任何表达式都可以转换为布尔值。因此,没有一种特定的类型提示可以完全捕获你想要的内容。你最终会使用
typing.Any
,这实际上与根本不使用类型提示相同。
你的选择
-
保持原样,使用
typing.Any
或不使用任何类型提示:
```python from typing import Any
def validate_expression(expression: Any): # 或 # def validate_expression(expression): try: assert expression except AssertionError as e: ... ```
这是最直接的方法,表明该函数接受任何类型的表达式。
- 记录预期行为:
虽然你不能在类型提示中强制执行此操作,但可以在文档字符串中清楚地记录预期行为:
```python def validate_expression(expression: Any): """验证表达式是否为真。
Args: expression: 要评估的表达式。应支持转换为布尔值。
Raises: AssertionError: 如果表达式不为真。 """ try: assert expression except AssertionError as e: ... ```
类型提示的局限性
重要的是要记住,Python 中的类型提示主要用于静态分析工具(如类型检查器),而不是在运行时强制执行。当涉及到
bool(expression)
的行为时,它在运行时确定,类型提示无法完全捕获它可能引发的所有潜在错误。
针对你提到的
pandas.DataFrame
的具体案例:
你不能使用类型提示来防止有人传递
pandas.DataFrame
到
validate_expression
函数中。这是因为在尝试将
pandas.DataFrame
转换为布尔值时发生的错误是一个运行时错误,类型提示无法阻止运行时错误。
在这种情况下,记录预期行为并让调用者负责传递合适的参数至关重要。如果需要,你可以在函数中添加显式运行时检查以处理特定情况,例如
pandas.DataFrame
。