【问题标题】:the type of a variable that can be implicitly checked for "zeroness" or "emptiness"可以隐式检查“零”或“空”的变量的类型
【发布时间】:2018-08-07 00:50:30
【问题描述】:

我有一个函数接收变量x 并检查它是“零”还是“空”。

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

我将如何通过提供自定义__bool____len__ 方法来检查它是否明确为“boolable”(因此bool(object) 的结果可能是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

【问题讨论】:

  • bool()if ... 逻辑能否针对实际可能的用例引发异常?断言可能没有必要?
  • “真正的布尔型”是什么意思? True/False 实际上是 1 和 0。boolable(x) 会做什么,if x 不会?
  • Truthy and Falsy 浮现在脑海中。stackoverflow.com/questions/39983695/…
  • @DeepSpace 如果一个变量没有__bool____len__ dunder 方法,它总是True,这不是我们想要的结果。

标签: python boolean type-hinting


【解决方案1】:

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

如果那不是您正在尝试做的事情,并且您正在尝试检查某些东西在 runtime 时是否为零、空或可布尔值(实际运行时)您的代码),您可以只使用 isinstance 检查 - 例如assert x == 0assert len(x) == 0assert hasattr(x, '__bool__') or hasattr(x, '__len__') 之类的东西。


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

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

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

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

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


但是,如果您想通过检查 __bool____len__ 方法的存在来检查某个类型是否为“布尔型”,您可以通过 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.

【讨论】:

    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 2011-10-15
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多