如何注释可以转换为布尔值的参数?

时间:2019-08-29 14:26:57

标签: python python-3.x python-typing

我开始进入python 3.6中的类型提示(又称注释),但我无法弄清楚此功能的动态方面。

我编写了以下代码,即使查看了有关类型提示的文档,我也想添加注解,但不确定如何添加。

这是功能:

def validate_expression(expression: ?):
    try:
        assert expression
    except AssertionError as e:
        ...

expression必须是一个有效的断言(假设bool(expression)对其有效的任何表达式)。

我应该写什么而不是问号?

更新:

我知道大多数python表达式都可以转换为布尔值,但是在编写此代码的上下文中,可以合理地期望表达式不是是可断言的。

在我的案例中,相关示例是pandas.DataFrame。跑步 bool(pandas.DataFrame())引发错误,我有充分的理由期望有人会尝试将数据框传递给验证功能。

更新2: 根据{{​​3}}的评论和答案,我现在了解:  1.在绝大多数情况下,任何python表达式都具有对Boolean的有效转换,这可以用typing.Any覆盖,也可以完全不添加注释。  2.在我感兴趣的极端情况下(bool(pandas.DataFrame()) # --> ValueError),注释将无济于事,因为这是运行时错误。  3.如果还有另一种与静态类型提示相关的极端情况,我不知道。  4.鉴于相关示例的稀有性/不存在性,没有开箱即用的类型通常只描述要转换为布尔值的能力的质量(类似于typing.Iterable),就我而言'我担心没有必要向后弯腰去解决这种极端情况(尽管听到相关示例和弯腰的解决方案会很有趣!)

2 个答案:

答案 0 :(得分:0)

任何值都可以在布尔上下文中使用。除非后代类提供备用定义,否则object的实例被视为真实值。一切被认为是错误的(例如,空列表,空str,空dict,False本身等)都会这样做,因为它被专门定义为

这样,您可以使用的唯一类型提示是typing.Any

from typing import Any


def validate_expression(expression: Any):
    try:
        assert expression
    except AssertionError as e:
        ...

实际上,这几乎不值得明确说明。

答案 1 :(得分:0)

关于您的更新2:这是完成您想要做的事情的一种比较古怪的方式:

  1. 创建与定义__bool__方法的任何类型匹配的自定义Protocol。 (如果您还想支持Python 2,也许还有__nonzero__方法。)
  2. 查找或创建熊猫库的存根。确保DataFrame的类型提示不包含__bool__方法。也就是说,将与协议匹配。
  3. 创建一个使用您的自定义协议作为类型提示的函数。

例如:

# If you're using Python 3.8+
from typing import Protocol

# If you're not, run 'pip install typing_extensions' and do the below instead
from typing_extensions import Protocol

class SupportsBool(Protocol):
    def __bool__(self) -> bool: ...

class MyFakeDataFrame:
    # ...snip...
    pass

class MyFakeBoolableThing:
    def __bool__(self) -> bool:
        return True

def validate_expression(x: SupportsBool) -> None:
    bool(x)

# These all type-check!

validate_expression(True)
validate_expression(0)
validate_expression(MyFakeBoolableThing())

# This will *not* typecheck

validate_expression(MyFakeDataFrame())

# Perhaps surprisingly, these will also not typecheck:

validate_expression("foobar")
validate_expression([1, 2, 3])

后两个表达式不进行类型检查的原因是,字符串和列表均未定义自定义的__bool__方法(或Python 2中的__nonzero__方法):相反,它们定义了{ {1}}方法,如果__len__ / bool(...)不存在,则__len__函数将退回到检查__bool__

如果您确实希望您的validate函数接受此类表达式,则需要使用类似__nonzero__的类型-但不幸的是,我相信pandas DataFrame类确实可以实现 功能性Union[SupportsBool, SupportsInt]方法,因此如果采用这种方法,您将回到零平方。

因此,基本上,在这种情况下,您要么(1)被迫拒绝某些类型(如str或list),这些类型在bool'd时会做有意义的事情,或者(2)被迫接受__len__作为可接受的boolable东西。