如何以内联方式断言值非None?解决Python类型检查报错
问题
我有如下代码:
if foo: bar = 1 else: bar = maybe_return_int(baz)
maybe_return_int的返回类型为Optional[int],因此mypy报错:
error: Incompatible types in assignment (expression has type "int | None", variable has type "int") [assignment]
但在我的代码语境中,确定maybe_return_int(baz)绝不会返回None。为通过类型检查,我不得不写这样繁琐的代码:
if foo: bar = 1 else: bar_maybe_none = maybe_return_int(baz) assert bar_maybe_none is not None bar = bar_maybe_none
有没有更简洁的写法?我希望能有一个assert_not_none函数,像这样用:
if foo: bar = 1 else: bar = assert_not_none(maybe_return_int(baz))
我可以编写这样的assert_not_none函数吗?
我可以用cast,但更喜欢assert的实际检查功能(至少在断言未禁用时),而且用assert不用手动指定类型(我的实际代码中类型比int冗长得多)。
解决方案
当然可以实现这样的assert_not_none函数,利用Python的类型注解让mypy识别出返回值是非None类型,同时保留运行时的断言检查:
from typing import TypeVar, Optional T = TypeVar('T') def assert_not_none(value: Optional[T]) -> T: assert value is not None return value
说明
- 用
TypeVar实现泛型,函数可以适配任意类型的Optional输入,无需手动指定具体类型,正好满足你不想写冗长类型的需求。 - 运行时会执行
assert检查,默认Python不禁用断言(除非用-O参数运行),如果传入None会直接抛出AssertionError,保留了你想要的实际检查功能。 - mypy能识别这个函数的类型注解,明确输入为
Optional[T]时返回T,所以你的目标写法完全能通过类型检查:
if foo: bar = 1 else: bar = assert_not_none(maybe_return_int(baz))
这种写法既保持了代码简洁,又兼顾了类型检查和运行时断言的双重作用,比单独用cast更安全,比分步写assert更高效。
内容的提问来源于stack exchange,提问作者Kerrick Staley
相关产品推荐
相关产品推荐

