我有一个函数,该函数接收变量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
。
答案 0 :(得分:1)
因此,首先,由于评论似乎对此有些困惑,我认为我应该首先陈述一下我的假设。我假设您正在尝试检查某物是否为0或为空,或者是否可以静态地 -也就是说,您使用PEP 484类型注释代码并运行像mypy这样的类型检查器来确定变量是否为零。
如果不是您要尝试的操作,并且您正在尝试在运行时检查某些东西是否为零或为空或可枚举(实际运行时)您的代码),则可以只使用isinstance检查-例如诸如assert x == 0
或assert len(x) == 0
或assert 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支持协议之外的其他类型检查器。