本文介绍了可以隐式检查“零"的变量的类型;或“空虚"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它接收一个变量 x 并检查它是零"还是空".

I have a function that receives a variable x and checks for it's "zeroness" or "emptiness".

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

Using PEP-484 type hinting syntax, what type hint would I use?

我将如何检查它是否明确boolable" 通过提供自定义的 __bool____len__ 方法(因此 bool(object) 的结果可以False),除了检查它是否真的实现了 __bool____len__ 方法?

And how would I check if it is explicitly "boolable" by providing a custom __bool__ or __len__ method (so the outcome of bool(object) could be False), apart from checking if it actually has implemented a __bool__ or __len__ method?

示例:

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.

I don't want to accept just any object; all objects have a truth value but for types without __bool__ or __len__ that's always True.

推荐答案

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

So first, since the comments seem to be a little confused about this, I figure I should probably state my assumptions first. I'm assuming that you're trying to check whether something is 0 or empty, or is boolable statically -- that is, you annotate your code using PEP 484 types and run a typechecker like mypy to determine whether a variable is zero or not.

如果这不是您要执行的操作,并且您要检查运行时(实际运行时)是否为零、空或布尔值你的代码),你可以只使用 isinstance 检查——例如诸如 assert x == 0assert len(x) == 0assert hasattr(x, '__bool__') 或 hasattr(x, '__len__) 之类的东西').

If that is not what you're trying to do, and you're trying to check if something is zero or empty or boolable at runtime (when actually running your code), you can just use isinstance checks -- e.g. stuff like assert x == 0 or assert len(x) == 0 or assert hasattr(x, '__bool__') or hasattr(x, '__len__').

如果您正在尝试静态检查某些内容是否为零或为空,则遗憾的是无法使用 PEP 484 类型执行此操作.基本上,PEP 484 不允许您将逻辑检查"与类型相关联——例如,您不能创建一个约束,要求某些函数只接受正整数.

If you are trying statically check if something is zero or empty, there is unfortunately no way of doing this with PEP 484 types. Basically, PEP 484 doesn't let you associate "logical checks" with types -- you can't create a constraint mandating that some function accepts only positive ints, for example.

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

This is possible in more sophisticated type systems (see dependent type systems, refinement type systems, etc...) but implementing such type systems is very complex so it's extremely unlikely that PEP 484 will be modified to support features like this in the near future.

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

That said, there are some plans for at least mypy to add support for simple dependent types for literals. For example, while we might not be able to easily tell whether some arbitrary variable is zero or not, we can tell that the literal 0 is a zero. (This feature is particularly useful when trying to type the open(...) function, for example -- it returns a different type depending on the value of the second argument).

这里有一些相关讨论——也就是说,我不会持有你的呼吸等待这个被实施.这是一个相对复杂的功能.

There's some related discussion here -- that said, I wouldn't hold your breath waiting for this to be implemented. It's a relatively complex feature.

就目前而言,唯一真正的替代方案是退回使用运行时检查或仅重构您的代码,这样您就无需检查某些内容是否为零或为空.

For now, the only real alternatives are to fall back to using runtime checks or to just restructure your code so you don't need to check if something is zero or empty.

但是,如果您想通过检查 __bool____len__ 方法的存在来检查某个类型是否boolable",您可以通过 使用协议:

However, if you want to check if some type is "boolable" by checking for the presence of the __bool__ or __len__ methods, you can do so statically by 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 支持协议之外的其他类型检查器.

You'll need to install the typing_extensions package using pip first. Protocols aren't yet a part of the standard library, but are expected to be standardized in the near future. I'm also not sure if other type checkers beyond mypy support protocols yet.

有关协议的更多文档.

这篇关于可以隐式检查“零"的变量的类型;或“空虚"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 17:19