如何指定无法访问的python代码

phi*_*hag 13 python

在python中指定无法访问的代码的pythonic方法是什么,如:

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

Dav*_*ave 26

raise ValueError('invalid gender %r' % gender)
Run Code Online (Sandbox Code Playgroud)

  • 从Pythonic宣言来看……“……错误永远不应该悄无声息地过去。除非明确地沉默。” (2认同)

Jas*_*sha 8

使用 python 版本 3.11+,您可以使用可以通过静态类型检查器(例如和 )typing.assert_never进行验证的方式来断言不可达性。mypypyright

from typing import assert_never

foo: int = 123

if isinstance(foo, str):
    assert_never(foo)  # unreachable
Run Code Online (Sandbox Code Playgroud)

静态类型检查器将验证if上面的 -block 确实无法访问。如果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
Run Code Online (Sandbox Code Playgroud)

对于 3.11 之前版本的 python,您需要assert_nevertyping_extensions模块导入。

from typing_extensions import assert_never  # python < 3.11
Run Code Online (Sandbox Code Playgroud)

例子

assert_nevertyping.Literal

这是一个typing.assert_never与 一起使用的示例typing.Literal,断言elseOP 问题中的 -block 无法访问:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

该类型在python >=3.11 的模块和早期版本的 python中typing.Never可用。typingtyping_extensions

assert_nevertyping.Union

这是另一个使用//if块来匹配变量类型的示例:elifelse

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
Run Code Online (Sandbox Code Playgroud)

有关更多示例,包括与枚举类型的值进行匹配,请参阅关于Unreachable Code 和 Exhaustiveness Checking的 Python 类型文档。


zen*_*azn 7

这取决于你的性别是无论怎么肯定'm''f'.

如果你绝对肯定,请使用if...else而不是if...elif...else.只是让每个人都更容易.

但是,如果数据格式不正确,您应该提出异常,以便更轻松地进行测试和修复错误.在这种情况下,您可以使用性别中立的问候语,但对于任何更大的问题,特殊值只会使bug更难找到.

  • “总是”有可能出现格式错误的数据。 (2认同)

mar*_*cog 7

你可以提出一个例外:

raise ValueError("Unexpected gender; expected 'm' or 'f', got %s" % gender)
Run Code Online (Sandbox Code Playgroud)

如果您希望数据库仅返回'm'或'f',则使用断言False:

assert False, "Unexpected gender; expected 'm' or 'f', got %s" % gender
Run Code Online (Sandbox Code Playgroud)


S.L*_*ott 5

我实际上认为这是有地方的。

class SeriousDesignError(Exception):
    pass
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做

if number % 2 == 0:
    result = "Even"
elif number % 2 == 1:
    result = "Odd"
else:
    raise SeriousDesignError()
Run Code Online (Sandbox Code Playgroud)

我认为这是最有意义的错误消息。只能通过设计错误(或维护不好,这是同一回事)引起这种情况。

  • 在提高SDE时,我仍然会包含一个描述性字符串,例如`raise SeriousDesignError('数字必须为偶数或奇数')。 (2认同)