可以隐式检查“零”或“空”的变量的类型

时间:2018-08-02 13:05:12

标签: python boolean type-hinting

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

使用PEP-484类型提示语法,我将使用哪种类型提示?

以及如何通过提供自定义__bool____len__方法来检查它是否显式为“ boolable”(因此bool(object)的结果可以< / em>是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

1 个答案:

答案 0 :(得分:1)

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

如果不是您要尝试的操作,并且您正在尝试在运行时检查某些东西是否为零或为空或可枚举(实际运行时)您的代码),则可以只使用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__方法的存在来检查某种类型是否“可boolable”,则可以通过using protocols进行静态操作:< / p>

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