可以隐式检查 "zeroness" 或 "emptiness" 的变量类型

the type of a variable that can be implicitly checked for "zeroness" or "emptiness"

我有一个接收变量 x 并检查它是 "zeroness" 还是 "emptiness" 的函数。

使用 PEP-484 类型提示语法,我会使用什么类型提示?

我如何通过提供自定义 __bool____len__ 方法来检查它是否明确为“boolable”(因此 bool(object) [=35 的结果=]可能是False),除了检查它是否真的实现了__bool____len__方法?

示例:

def my_func(x: "what goes here?"):
    assert boolable(x)  # what to do in this line?
    if x:
        "some logic"
    else:
        "some other logic"

我不想随便接受任何对象;所有对象都有一个真值,但对于没有 __bool____len__ 的类型,它总是 True.

所以首先,由于评论似乎对此有些困惑,我想我应该先陈述我的假设。我假设您正在尝试检查某些内容是否为 0 或空,或者是否可布尔 静态 —— 也就是说,您使用 PEP 484 类型和 [=61= 注释您的代码] 像 mypy 这样的类型检查器来确定变量是否为零。

如果这不是您想要做的,并且您正在尝试检查 [= 处的内容是否为零、空或可布尔值61=]time (实际上 运行ning 你的代码),你可以只使用 isinstance 检查——例如assert x == 0assert len(x) == 0assert hasattr(x, '__bool__') or hasattr(x, '__len__').

之类的东西

如果您正在 尝试静态检查某些内容是否为零或为空,不幸的是,无法使用 PEP 484 类型执行此操作。基本上,PEP 484 不允许您将 "logical checks" 与类型相关联——例如,您不能创建强制某些函数只接受正整数的约束。

这在更复杂的类型系统(参见依赖类型系统、细化类型系统等)中是可能的,但实现此类系统非常复杂,因此 PEP 484 极不可能被修改以支持诸如此类的功能这在不久的将来。

也就是说,一些计划,至少 mypy 会添加对 文字 的简单依赖类型的支持。例如,虽然我们可能无法轻易判断某个任意变量是否为零,但我们 可以 判断文字 0 是否为零。 (此功能在尝试键入 open(...) 函数时特别有用,例如 - 根据第二个参数的值,它 returns 是不同的类型)。

有一些 related discussion here -- 那就是说,我不会屏住呼吸等待它的实施。这是一个相对复杂的功能。

目前,唯一真正的替代方法是回退到使用 运行时间检查,或者只是重构您的代码,这样您就不需要检查某些内容是否为零或为空。


但是,如果您想通过检查 __bool____len__ 方法的存在来检查某些类型是否为 "boolable",您可以通过 using protocols:

from typing import Union
from typing_extensions import Protocol

class HasBool(Protocol):
    def __bool__(self) -> bool: ...

class HasLen(Protocol):
    def __len__(self) -> int: ...

Boolable = Union[HasBool, HasLen]

def accepts_boolable(x: Boolable) -> None: pass

accepts_boolable(3)
accepts_boolable("asdf")

class NotBoolable: pass

accepts_boolable(NotBoolable())  # Mypy reports an error

您需要先使用 pip 安装 typing_extensions 包。协议还不是标准库的一部分,但有望在不久的将来实现标准化。我也不确定 mypy 之外的其他类型检查器是否支持协议。

More documentation about protocols.