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

Python 可以隐式检查的变量类型;“零度”;或;“空虚”;,python,boolean,type-hinting,Python,Boolean,Type Hinting,我有一个函数,它接收一个变量x,并检查它是否为“零”或“空” 使用类型提示语法,我将使用什么类型提示 我如何通过提供一个定制的\uuuu bool\uuuuu或\uuu len\uuuuu方法(因此bool(object)的结果可能是False),除了检查它是否实际实现了\uuuu bool\uuuu或\uu len\ucode>方法之外,来检查它是否是显式的 例如: def my_func(x: "what goes here?"): assert boolable(x) # wha

我有一个函数,它接收一个变量
x
,并检查它是否为“零”或“空”

使用类型提示语法,我将使用什么类型提示

我如何通过提供一个定制的
\uuuu bool\uuuuu
\uuu len\uuuuu
方法(因此
bool(object)
的结果可能是
False
),除了检查它是否实际实现了
\uuuu bool\uuuu
\uu len\ucode>方法之外,来检查它是否是显式的

例如:

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

我不想只接受任何东西;所有对象都有一个真值,但对于没有
\uuuu bool\uuuu
\uu len\uuuu
的类型,该值总是
真的

,因此首先,由于注释似乎对此有点混淆,我想我应该首先陈述我的假设。我假设您正在尝试检查某个内容是否为0或空,或者静态可bootable——也就是说,您使用PEP 484类型对代码进行注释,并运行mypy之类的类型检查器来确定某个变量是否为零

如果这不是您想要做的,并且您试图在运行时检查某个内容是否为零、是否为空或是否可bootable(当实际运行代码时),您可以只使用isinstance检查——例如
assert x==0
assert len(x)==0
assert hasattr(x)、\uuu bool\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu)或hasattr(x),\uuuuuuuuuuuuuuuuuuuuuu


如果您试图静态地检查某个内容是零还是空,那么遗憾的是,PEP 484类型无法做到这一点。基本上,PEP 484不允许您将“逻辑检查”与类型相关联——例如,您不能创建强制某些函数只接受正整数的约束

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

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

有一些--也就是说,我不会屏住呼吸等待这项计划的实施。这是一个相对复杂的特征

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


但是,如果要通过检查是否存在
\uuuubool\uuuu
\uuuu len\uuuu
方法来检查某些类型是否“可booable”,可以通过以下方式静态执行:

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


.

如果…
逻辑为实际可能的用例引发异常,是否可以
bool()
?这个断言可能没有必要?什么是“真正的boolable”?真/假实际上是1和0。如果x
不会,boolable(x)
会做什么呢?我想到了Truthy和Falsy。@DeepSpace如果变量没有
\uubool\uuuu
\ulen\uuuuu
dunder方法,它总是
True
,这不是期望的结果。
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