如何标记不可达的Python代码

26 投票
8 回答
11900 浏览
提问于 2025-04-15 11:22

在Python中,怎么用一种“Python风格”的方式来标记那些永远不会被执行的代码呢?就像下面这个例子:

gender = readFromDB(...) # either 'm' or 'f'
if gender == 'm':
    greeting = 'Mr.'
elif gender == 'f':
    greeting = 'Ms.'
else:
    # What should this line say?

8 个回答

8

在Python 3.11及以上版本中,你可以使用typing.assert_never来确认某段代码是不可达的,这种方式可以被静态类型检查工具,比如mypypyright验证。

from typing import assert_never

foo: int = 123

if isinstance(foo, str):
    assert_never(foo)  # unreachable

静态类型检查工具会检查上面的if块确实是不可达的。如果在运行时意外到达了assert_never的那部分代码,它会抛出一个AssertionError错误:

>>> from typing import assert_never
>>> assert_never(123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/.../lib/python3.11/typing.py", line 2464, in assert_never
    raise AssertionError(f"Expected code to be unreachable, but got: {value}")
AssertionError: Expected code to be unreachable, but got: 123

在Python 3.11之前的版本中,你需要从typing_extensions模块中导入assert_never

from typing_extensions import assert_never  # python < 3.11

示例

assert_nevertyping.Literal

下面是一个使用typing.assert_nevertyping.Literal的例子,来确认OP问题中的else块是不可达的:

from typing import Literal
from typing_extensions import assert_never

var: Literal["m", "f"] = "m"

if var == "m":
    ...
elif var == "f":
    ...
else:
    assert_never(var)  # unreachable

assert_nevertyping.NoReturn

这里是一个函数的例子,它的返回类型注解是typing.NoReturn

import time
from typing import NoReturn
from typing_extensions import Never, assert_never

def foo() -> NoReturn:
    while True:
        time.sleep(1)

bar: Never = foo()

assert_never(bar)  # unreachable

typing.Never类型在Python 3.11及以上版本的typing模块中可用,而在早期版本中则在typing_extensions中可用。

assert_nevertyping.Union

这是另一个例子,使用if/elif/else块来匹配一个变量的类型:

from typing import Union
from typing_extensions import assert_never

var: Union[int, str, float] = "123"

if isinstance(var, int):
    ...
elif isinstance(var, str):
    ...
elif isinstance(var, float):
    ...
else:
    assert_never(var)  # unreachable

想要查看更多示例,包括如何匹配枚举类型的值,可以查看Python类型文档中的不可达代码和穷尽性检查

9

你可以抛出一个异常:

raise ValueError("Unexpected gender; expected 'm' or 'f', got %s" % gender)

或者如果你希望数据库只返回'm'或'f',可以使用assert False:

assert False, "Unexpected gender; expected 'm' or 'f', got %s" % gender
32

在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要将它们转换成一种程序能处理的格式。

比如说,如果我们从一个网页上获取了一些信息,这些信息可能是以文本的形式存在的。我们需要把这些文本解析成程序能理解的结构,比如数组或者对象。这样,程序才能对这些数据进行操作,比如显示、计算或者存储。

在这个过程中,我们可能会用到一些工具或者库,它们可以帮助我们更方便地处理这些数据。使用这些工具,就像是用一个强大的助手来帮我们完成繁琐的工作,让我们能更专注于编写程序的逻辑。

总之,数据处理是编程中非常重要的一部分,掌握了这部分内容,我们就能更好地与程序进行互动,创造出更有趣的功能。

raise ValueError('invalid gender %r' % gender)

撰写回答