我开始进入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
),就我而言'我担心没有必要向后弯腰去解决这种极端情况(尽管听到相关示例和弯腰的解决方案会很有趣!)
答案 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:这是完成您想要做的事情的一种比较古怪的方式:
__bool__
方法的任何类型匹配的自定义Protocol。 (如果您还想支持Python 2,也许还有__nonzero__
方法。)DataFrame
的类型提示不包含__bool__
方法。也就是说,不将与协议匹配。例如:
# 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东西。